diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..3c35603a13 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# Ignore git submodules as they produce an error +# if the clone is copied to the intermediate docker build container! +db4.8 +leveldb +tor diff --git a/.gitattributes b/.gitattributes index 26d7549356..32e27c96e3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,13 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + src/version.cpp export-subst + +# Shell scripts etc +*.sh eol=lf +configure eol=lf +configure.ac eol=lf +Makefile.am eol=lf diff --git a/.gitignore b/.gitignore index 3800402a03..b86e70894e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,18 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + src/*.exe -src/shadowcoin -src/shadowcoind -src/test_shadow +src/spectrecoin +src/spectrecoind +src/aliaswallet +src/aliaswalletd +src/test_spectre src/build.h +src/clientversion.h +src/.libs .*.swp *.*~* *.bak @@ -10,20 +20,113 @@ src/build.h *.orig *.o *.P -*.patch *.dat *.autosave -.shadowcoin +.spectrecoin +.aliaswallet #compilation and Qt preprocessor part *.qm -Makefile -shadow +spectre +aliaswallet #resources cpp qrc_*.cpp +#moc +moc_*.cpp +#ui +ui_*.h #qt creator *.pro.user +CMakeLists.txt.user +CMakeSettings.json #mac specific .DS_Store -build +build*/ +db4.8/build_unix +.deps +.dirstamp +Makefile +Makefile.in +config.log +configure +depcomp +missing +install-sh +config.guess +config.status +config.sub +test-driver +aclocal.m4 +autom4te.cache +ar-lib +compile +libtool +ltmain.sh + +!db4.8/build_unix/configure +openssl-1.1.0h +spectre.config +spectre.creator +spectre.creator.user +spectre.files +spectre.includes += +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +Spectre.app +boost_1_67_0/ +libevent-2.1.8-stable/ +packages64bit/ +src/spectre.pdb +*.dll +src/x64/ +src/bin/ +src/.vs/ +src/src.vcxproj +src/src.vcxproj.user +src/src.vcxproj.filters +src/spectre.lib +src/spectre.exp +src/mocinclude.opt +src/.qmake.stash +src/debug/ +src/release/moc_predefs.h.cbt +src/release/mocinclude.opt +src/release/moc_predefs.h +src/spectre.ilk +packages64bit.zip +src/src.sln +packages64bit_static/ +doc/Windows build instructions.docx +doc/Windows build instructions.pdf +doc/~$ndows build instructions.docx + +openssl-1\.1\.0h\.tar\.gz + +boost_1_67_0\.tar\.gz + +Makefile\.am\.user +/build-src-Desktop_Qt* +/Prebuild.Spectre.libraries.zip + +# CLion/IntelliJ files +.idea/ +*.iml +cmake-*/ + +moc_predefs.h +/build-tests-Desktop_Qt* + +# Temp build files +releaseNotesToDeploy.txt +Checksum-Aliaswallet-* + +# Visual Studio +.vs/ +*.aps -!src/leveldb/Makefile +# Mac +*.dmg +.qmake.stash diff --git a/.reuse/dep5 b/.reuse/dep5 new file mode 100644 index 0000000000..5934cfc935 --- /dev/null +++ b/.reuse/dep5 @@ -0,0 +1,131 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ALIAS +Upstream-Contact: ALIAS Developers +Source: https://github.com/aliascash/alias-wallet + +# ############################################################################ +# MIT Licenses +Files: doc/* Docker/*/*.patch src/qt/forms/* src/qt/locale/* src/qt/res/assets/css/* src/qt/res/assets/fonts/Footable/* +Copyright: 2025 ALIAS Developers +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: src/qt/res/assets/fonts/Framework-icon/* src/qt/res/assets/icons/* src/qt/res/assets/img/* src/qt/res/assets/js/* +Copyright: 2025 ALIAS Developers +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: src/qt/res/assets/plugins/framework/* src/qt/res/assets/svg/* src/qt/res/icons/* src/qt/res/images/* +Copyright: 2025 ALIAS Developers +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: src/qt/res/qml/* src/qt/res/src/* src/src.aps src/osx/app-slide-arrow.png +Copyright: 2025 ALIAS Developers +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: external/*/patches/* scripts/patches/* src/qt/res/alias-qt.rc src/qt/res/index.html src/qt/res/qml/main.qml +Copyright: 2025 ALIAS Developers +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: src/qt/res/assets/plugins/bootstrapv3/* +Copyright: 2018 Twitter +License: MIT + +Files: src/qt/res/assets/plugins/classie/* +Copyright: 2016 https://github.com/desandro/classie +License: MIT + +Files: src/qt/res/assets/plugins/contextMenu/* +Copyright: 2013 Sudhanshu Yadav +License: MIT + +Files: src/qt/res/assets/plugins/iscroll/* +Copyright: 2008 Matteo Spinelli http://cubiq.org +License: MIT + +Files: src/qt/res/assets/plugins/jdenticon/* +Copyright: 2014 Daniel Mester Pirttijärvi +License: MIT + +Files: src/qt/res/assets/plugins/markdown/* +Copyright: 2014 Simon Waldherr http://simon.waldherr.eu/ +License: MIT + +Files: src/qt/res/assets/plugins/md5/* +Copyright: 2014 Yi-Cyuan Chen +License: MIT + +Files: src/qt/res/assets/plugins/pace/* +Copyright: 2016 https://github.com/HubSpot/pace +License: MIT + +Files: src/qt/res/assets/plugins/qrcode/* +Copyright: 2015 Twitter @davidshimjs +License: MIT + +Files: src/qt/res/assets/plugins/modernizr* +Copyright: 2016 https://modernizr.com/ +License: MIT + +Files: src/qt/res/assets/plugins/jquery* +Copyright: 2014 jQuery Foundation and other contributors +License: MIT + +Files: src/qt/res/assets/plugins/footable/* +Copyright: 2014 Steven Usher & Brad Vincent +License: MIT + +Files: src/test/data/* +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +Files: m4/* +Copyright: 2020 Alias Developers +Copyright: 2016 SpectreCoin Developers +License: MIT + +# ############################################################################ +# BSD-2-Clause Licenses +Files: src/lz4/* +Copyright: 2011 Yann Collet +License: BSD-2-Clause + +Files: src/qt/res/assets/plugins/identicon/* +Copyright: 2013 Stewart Lord +License: BSD-2-Clause + +Files: src/qt/res/assets/plugins/shajs/* +Copyright: 2008 Brian Turek +License: BSD-2-Clause + +Files: src/qt/res/assets/plugins/pnglib/* +Copyright: 2010 Robert Eisele +License: BSD-2-Clause + +# ############################################################################ +# GPL-3.0-or-later Licenses +Files: external/berkeleydb-cmake/patches/config.guess external/berkeleydb-cmake/patches/config.sub +Copyright: Per Bothner, Ben Elliston +License: GPL-3.0-or-later + +# ############################################################################ +# OFL-1.1 Licenses +Files: src/qt/res/assets/fonts/FontAwesome/* src/qt/res/assets/fonts/Montserrat/* src/qt/res/assets/fonts/*.otf +Copyright: Dave Gandy http://fontawesome.io +Copyright: Google, Inc. +License: OFL-1.1 + +# ############################################################################ +# CC-BY-4.0 Licenses +Files: src/qt/res/assets/plugins/emojione/* +Copyright: 2016 EmojiOne +License: CC-BY-4.0 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f4c4c7f567..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,83 +0,0 @@ ---- -language: cpp -compiler: gcc -os: linux -sudo: required -dist: trusty -matrix: - fast_finish: true -env: - global: - - MAKEJOBS=-j3 - - DEPS_URL=https://deps.shadow.cash/ - matrix: - - BUILD=win32 HOST=i686-w64-mingw32 DISTNAME=i686-win PACKAGES="mingw-w64 g++-mingw-w64" BITS=32 MAKEFILE=makefile.linux-mingw BOOST_LIB_SUFFIX="-mt-s" OUTPUT_SUFFIX=".exe" QMAKEOPTS="-xplatform win32-g++" BOOST_THREAD_LIB_SUFFIX="_win32-mt-s" - - BUILD=win64 HOST=x86_64-w64-mingw32 DISTNAME=x86_64-win PACKAGES="mingw-w64 g++-mingw-w64" BITS=64 MAKEFILE=makefile.linux-mingw BOOST_LIB_SUFFIX="-mt-s" OUTPUT_SUFFIX=".exe" QMAKEOPTS="-xplatform win32-g++" BOOST_THREAD_LIB_SUFFIX="_win32-mt-s" - - BUILD=macosx HOST=x86_64-apple-darwin14 DISTNAME=x86_64-darwin PACKAGES="clang llvm-dev" BOOST_LIB_SUFFIX="-mt-s" BOOST_THREAD_LIB_SUFFIX="-mt-s" DEPS=shadow-deps-osx.tar.xz EXTRADEPS=osxcross.tar.xz - QMAKE_CXXFLAGS="-I/home/vagrant/deps/SDK/MacOSX10.9/usr/include -DBOOST_HAS_INT128=1" QMAKEOPTS="-xplatform macx-clang-linux" OTOOL=${HOST}-otool INSTALLNAMETOOL=${HOST}-install_name_tool STRIP=${HOST}-strip - - BUILD=linux64 MAKEFILE=makefile.unix BOOST_LIB_SUFFIX="-mt" BITS=64 -# - BUILD=macosx MAKEFILE=makefile.osx BOOST_LIB_SUFFIX="-mt" TODO: osx daemon!! - -before_install: - - sudo apt-get -qq update - -install: - - if [ "$DEPS" == "" ]; then export DEPS=shadow-deps-${BUILD}.tar.xz; fi - - export INDIR=$HOME/inputs - - export DEPSDIR=$HOME/deps${BITS} - - export PATH=$DEPSDIR/host/bin:$DEPSDIR:$DEPSDIR/bin:$PATH - - export QTDIR=$TRAVIS_BUILD_DIR - - sudo apt-get install build-essential $PACKAGES - - mkdir -p $INDIR $DEPSDIR - - cd $INDIR && wget --user="$AUTH_USER" --password="$AUTH_PASSWORD" $DEPS_URL/$DEPS `[ $EXTRADEPS != "" ] && echo $DEPS_URL/$EXTRADEPS` - - cd $DEPSDIR && tar xf $INDIR/$DEPS - - if [ $EXTRADEPS != "" ]; then tar xf $INDIR/$EXTRADEPS; fi -script: - - echo 'Build Daemon' && echo -en 'travis_fold:start:script.daemon\\r' - - - cd $TRAVIS_BUILD_DIR/src - - if [ "$MAKEFILE" != "" ]; then make $MAKEJOBS -f $MAKEFILE HOST="$HOST" STATIC=1 OPENSSL_INCLUDE_PATH="$DEPSDIR/include" OPENSSL_LIB_PATH="$DEPSDIR/lib" DEPSDIR="$DEPSDIR" CURDIR="$TRAVIS_BUILD_DIR/src" USE_UPNP=1 BOOST_LIB_SUFFIX="$BOOST_LIB_SUFFIX" DEBUGFLAGS= && install -s shadowcoind${OUTPUT_SUFFIX} $INDIR/; fi - - - echo -en 'travis_fold:end:script.daemon\\r' - - - - echo 'Build Qt' && echo -en 'travis_fold:start:script.qt\\r' - - - cd $TRAVIS_BUILD_DIR - - qmake $QMAKEOPTS QMAKE_LRELEASE="$DEPSDIR/host/bin/lrelease" INCLUDEPATH="$DEPSDIR/include" LIBS="-L$DEPSDIR/lib" BOOST_LIB_SUFFIX="$BOOST_LIB_SUFFIX" BOOST_THREAD_LIB_SUFFIX="$BOOST_THREAD_LIB_SUFFIX" RELEASE=1 DEFINES=BOOST_THREAD_USE_LIB QMAKE_CXXFLAGS="-frandom-seed=shadow $QMAKE_CXXFLAGS" USE_BUILD_INFO=1 USE_O3=1 - - if [[ "$BUILD" =~ "linux" ]]; then sed -i 's^,-whole-archive -lleveldb -Wl,^,-lleveldb,^' Makefile; fi - - make $MAKEJOBS - - - echo -en 'travis_fold:end:script.qt\\r' - - - - echo 'Package executables' && echo -en 'travis_fold:start:script.package\\r' - - - export BUILD=umbra_`if [ "$TRAVIS_TAG" != "" ]; then [ "${TRAVIS_TAG:0:1}" == "v" ] && echo ${TRAVIS_TAG:1}_ || echo ${TRAVIS_TAG}_; fi`${BUILD} - - export UPLOAD=${BUILD}.zip; - - if [ -d release ]; then cd release; fi - - if [ -f umbra${OUTPUT_SUFFIX} ]; then install -s umbra${OUTPUT_SUFFIX} $INDIR/; export UPLOAD=${BUILD}.zip; fi - - if [ -d Umbra.app ]; then contrib/macdeploy/createdmg; mv umbra.macosx.dmg $INDIR/${BUILD}.dmg; export UPLOAD=${BUILD}.dmg; fi - - - cd $INDIR - - if [ -f umbra${OUTPUT_SUFFIX} ]; then zip $INDIR/$UPLOAD umbra${OUTPUT_SUFFIX} shadowcoind${OUTPUT_SUFFIX}; fi - - sha256sum $UPLOAD > $INDIR/${UPLOAD}.sha256sum.txt - - - echo -en 'travis_fold:end:script.package\\r' - - - cd $TRAVIS_BUILD_DIR # Need to be in build dir last - -after_script: - - if [ "$TRAVIS_TAG" = "" ]; then travis_retry curl --max-time 60 --upload $INDIR/$UPLOAD https://transfer.sh/$UPLOAD; fi - -deploy: - - provider: releases - api_key: - secure: qzpItzq8Y5nEh+CIHWvMbygRZsYvdBeU4xOttJRXOuXG4wUzuza1o5xJCkUr+qhm+/XLH01NkFLy8jahTv7JcNa2GCBnvfoI9JGReQIlX3hi7XcrqFZb8VhMmqC7AmOs+igGgt9rusP3ZtsmOd0yjh8kKJui0sRNam3wU0iPpu6b87Gxp9wZ13l0hQm6D89+iAT+hjTkyN4lMJLYIEEin7AXDWltjx11z7tKMEQEL533gVgJ6eBSW0DxBYZ8toE0HySJb9xAW3M8D0EsZfYBRMQe+5q1cLqbNpYVPQIWs2gMFmnCdI4e+jSp0aXyy0Y9YxjBxm17z7MRixG5Tz6XfWc/9qhiBEawklF6fGjR68nky5JqNW31BEEQiBaryfl5O3OWRiM0a2V1qjOb3m90rtl3GdEK8Yu0LutQnvZSnAyut9WuQxaYc4ovdsT0XFbnEfHdego0evAfV/I8mgwTdcChM3aJGPdJZEb81/TvIZZMxVLqFkQ4Z3Cf5RxoqfFZt4DviPg6KT6dMCUTpI3uDs3SQR5gEuBczzKpUVrIuvxi2T3hV1D9VYY2MqZuGa5mu5JlMG7thA0VMeJMAhQm15TdXkmuyZwmaWkLXKfJAwpL1U3MEaQKC0wFFSUZ0km41hAaWgEtZGBQLKQCukIXb21qLR0KX8cMw5OkvBnhRxs= - file: # Linter thinks this is broken? - - $INDIR/$UPLOAD - - $INDIR/${UPLOAD}.sha256sum.txt - overwrite: true - on: - tags: true - diff --git a/.tx/config b/.tx/config index e85f28f0db..a31a116f42 100644 --- a/.tx/config +++ b/.tx/config @@ -1,9 +1,14 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + [main] host = https://www.transifex.com -[shadowcore.umbra_qt] -file_filter = src/qt/locale/umbra_.ts -source_file = src/qt/locale/umbra_en.ts +[alias-wallet.alias_qt] +file_filter = src/qt/locale/alias_.ts +source_file = src/qt/locale/alias_en.ts source_lang = en type = QT - diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..6732f5fffd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,222 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +cmake_minimum_required(VERSION 3.13) +project(ALIAS VERSION 5.1.0 LANGUAGES CXX C) + +message(STATUS "") +message(STATUS "=== Setting defaults =======================================================") +set(CLIENT_VERSION_MAJOR 5) +set(CLIENT_VERSION_MINOR 1) +set(CLIENT_VERSION_REVISION 0) +set(CLIENT_VERSION_BUILD 0) +set(CLIENT_VERSION_GIT_SHA1 "---") +set(VERSION_STRING "${CLIENT_VERSION_MAJOR}.${CLIENT_VERSION_MINOR}.${CLIENT_VERSION_REVISION}.${CLIENT_VERSION_BUILD}") +set(CMAKE_VERBOSE_MAKEFILE OFF) +set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/android") + +set(TOR_ARCHIVE_MAC_HASH "733380c234c8a4796d6bfefec536afd6469f8d7d") +set(TOR_ARCHIVE_WIN64_HASH "36ab45ca414795560a4c946fcb49848b919569bf") +set(TOR_ARCHIVE_WIN32_HASH "66cef46b02d6e788840899baca11e2a2f9f5241a") +set(VCRUNTIME_ARCHIVE_WIN64_HASH "85cffbf41e957dcc9c5dd528af84c03474e76b8c") +set(VCRUNTIME_ARCHIVE_WIN32_HASH "9af511350e0772bf1f543abd375304af2e616273") + +set(CMAKE_CXX_STANDARD 17) +if (WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") + add_compile_definitions(NOMINMAX) +endif () + +if (ANDROID) + set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES};DebugAndroid;ReleaseAndroid" CACHE STRING "" FORCE) + if(DEFINED ENV{BOOST_ROOT}) + message(STATUS "Getting settings from environment") + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(BOOST_ROOT "$ENV{BOOST_ROOT}") + set(BOOST_INCLUDEDIR "$ENV{BOOST_INCLUDEDIR}") + set(Boost_INCLUDE_DIR "$ENV{BOOST_INCLUDEDIR}") + set(BOOST_LIBRARYDIR "$ENV{BOOST_LIBRARYDIR}") + set(Boost_LIBRARY_DIR "$ENV{BOOST_LIBRARYDIR}") + set(BerkeleyDB_ROOT_DIR "$ENV{BerkeleyDB_ROOT_DIR}") + set(BERKELEYDB_INCLUDE_DIR "$ENV{BERKELEYDB_INCLUDE_DIR}") + set(leveldb_DIR "$ENV{leveldb_DIR}") + set(OPENSSL_ROOT_DIR "$ENV{OPENSSL_ROOT_DIR}") + set(ENABLE_GUI ON) + endif() + message(STATUS "Configuring for Android") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-deprecated-declarations -Wno-dangling-else") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold") + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(STATUS "Configuring on/for Linux") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + message(STATUS "Configuring on/for macOS") +elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows") + message(STATUS "Configuring on/for Windows") + add_definitions(-DBOOST_ALL_DYN_LINK) + add_definitions("/wd4244") + add_definitions("/wd4267") + add_definitions(-DWIN32_LEAN_AND_MEAN) + + if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") + set(DEPLOY_QT_BINARY_TYPE_OPTION "--debug") + set(WINDEPLOYQT_TARGET_FOLDER "Debug") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER}") + else() + set(DEPLOY_QT_BINARY_TYPE_OPTION "--release") + set(WINDEPLOYQT_TARGET_FOLDER "Release") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER}") + endif() + + find_program(UNZIP unzip) + if (${UNZIP} STREQUAL "UNZIP-NOTFOUND") + message(FATAL_ERROR "You need to install 'unzip'!") + endif () +endif () + +if (POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif () + +message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") +set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) +include(GetGitRevisionDescription) +get_git_head_revision(GIT_REFSPEC CLIENT_VERSION_GIT_SHA1) +include(GNUInstallDirs) +message(STATUS "Building in '${CMAKE_BUILD_TYPE}' mode") + +message(STATUS "") +message(STATUS "=== Boost ==================================================================") +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_STATIC_RUNTIME ON) +set(Boost_USE_MULTITHREADED ON) +set(Boost_NO_SYSTEM_PATHS ON) +set(Boost_ARCHITECTURE -x64) +find_package(Boost 1.72.0 REQUIRED COMPONENTS atomic chrono date_time filesystem iostreams program_options regex system thread) +message(STATUS "Boost_VERSION: ${Boost_VERSION}") +message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}") +message(STATUS "Boost_LIBRARY_DIRS: ${Boost_LIBRARY_DIRS}") +message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}") +add_compile_definitions(BOOST_SPIRIT_THREADSAFE) + +message(STATUS "") +message(STATUS "=== Qt =====================================================================") +if (ENABLE_GUI) + if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(Qt5_DIR "C:/Qt/5.12.7/msvc2017_64/lib/cmake/Qt5") + list(APPEND CMAKE_PREFIX_PATH "C:/Qt/5.12.7/msvc2017_64/lib/cmake") + endif() + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTOUIC ON) + set(CMAKE_AUTORCC ON) + + find_package(Qt5 REQUIRED COMPONENTS + Core + Gui + Widgets + WebView + WebChannel + WebSockets + QuickWidgets + Quick + Svg + Concurrent + LinguistTools + ) + + message(STATUS "Qt5Core version: ${Qt5Core_VERSION}") + message(STATUS "Qt5Widgets version: ${Qt5Widgets_VERSION}") + message(STATUS "Qt5Gui version: ${Qt5Gui_VERSION}") + + include("${Qt5_LinguistTools_DIR}/Qt5LinguistToolsMacros.cmake" OPTIONAL) + + if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) + get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) + find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/delivery) + elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION) + get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY) + find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + endif() +else() + message(STATUS "Building without UI, skipping Qt detection") +endif() + +message(STATUS "") +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + message(STATUS "=== Tor binary archive =====================================================") + if (NOT TOR_ARCHIVE) + include(DownloadFile) + set(TOR_ARCHIVE "${CMAKE_BINARY_DIR}/Tor.libraries.MacOS.zip") + download_file(https://github.com/aliascash/resources/raw/master/resources/Tor.libraries.MacOS.zip ${TOR_ARCHIVE} SHA1 ${TOR_ARCHIVE_MAC_HASH}) + endif () +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + message(STATUS "=== Tor and VCRuntime binary archives ======================================") + if (CMAKE_CL_64) + message(STATUS "Using x64 archives") + set(WINDOWS_ARCH_SUFFIX "Win64") + else() + message(STATUS "Using x86 archives") + set(WINDOWS_ARCH_SUFFIX "Win32") + endif() + + if (NOT TOR_ARCHIVE) + message(STATUS "Downloading Tor archive (official Tor Project)") + include(DownloadFile) + set(TOR_ARCHIVE "${CMAKE_BINARY_DIR}/Tor.libraries.${WINDOWS_ARCH_SUFFIX}.zip") + download_file( + "https://archive.torproject.org/tor-package-archive/torbrowser/14.0.3/tor-win64-0.4.8.11.zip" + ${TOR_ARCHIVE} + SHA256 "" + ) + else() + message(STATUS "Using Tor archive from given path") + endif() + + if (NOT VCRUNTIME_ARCHIVE) + message(STATUS "Downloading VCRuntime archive (Microsoft official)") + include(DownloadFile) + set(VCRUNTIME_ARCHIVE "${CMAKE_BINARY_DIR}/VCRuntime.libraries.${WINDOWS_ARCH_SUFFIX}.zip") + download_file( + "https://aka.ms/vs/16/release/vc_redist.x64.exe" + ${VCRUNTIME_ARCHIVE} + SHA256 "" + ) + else() + message(STATUS "Using VCRuntime archive from given path") + endif() +endif() + +message(STATUS "") +message(STATUS "=== OpenSSL ================================================================") +set(OPENSSL_USE_STATIC_LIBS TRUE) +find_package(OpenSSL) +message(STATUS "OPENSSL_FOUND: ${OPENSSL_FOUND}") +message(STATUS "OPENSSL_INCLUDE_DIR: ${OPENSSL_INCLUDE_DIR}") +message(STATUS "OPENSSL_CRYPTO_LIBRARY: ${OPENSSL_CRYPTO_LIBRARY}") +message(STATUS "OPENSSL_SSL_LIBRARY: ${OPENSSL_SSL_LIBRARY}") +message(STATUS "OPENSSL_LIBRARIES: ${OPENSSL_LIBRARIES}") +message(STATUS "OPENSSL_VERSION: ${OPENSSL_VERSION}") + +message(STATUS "") +message(STATUS "=== Berkeley DB ============================================================") +find_package(BerkeleyDB 4) + +message(STATUS "") +message(STATUS "=== LevelDB ================================================================") +find_package(leveldb) +message(STATUS "LevelDB directory: ${leveldb_DIR}") +message(STATUS "LevelDB version: ${leveldb_VERSION}") + +message(STATUS "") +message(STATUS "=== Dive into subdirs... ===================================================") +add_subdirectory(src) diff --git a/Docker/CentOS/Dockerfile b/Docker/CentOS/Dockerfile new file mode 100644 index 0000000000..413383cb4c --- /dev/null +++ b/Docker/CentOS/Dockerfile @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-centos-8:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for CentOS 8" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for CentOS 8" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-CentOS.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-CentOS.sha256" +ENV CHKSUM_FILE="Checksum-Alias-CentOS-8.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/CentOS/Dockerfile_noUpload b/Docker/CentOS/Dockerfile_noUpload new file mode 100644 index 0000000000..0fa447ccb3 --- /dev/null +++ b/Docker/CentOS/Dockerfile_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-centos-8:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for CentOS 8 (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/CentOS/QT5BinaryPath.patch b/Docker/CentOS/QT5BinaryPath.patch new file mode 100644 index 0000000000..5247dd02f4 --- /dev/null +++ b/Docker/CentOS/QT5BinaryPath.patch @@ -0,0 +1,17 @@ +--- configure.ac 2018-07-22 22:50:33.225640603 +0200 ++++ configure.ac.fedora 2018-08-03 23:39:28.970937691 +0200 +@@ -78,10 +78,10 @@ + AC_SUBST([QT5_CFLAGS]) + AC_SUBST([QT5_LDFLAGS]) + AC_SUBST([QT5_LIBS]) +- MOC="${with_qt5//\/include\//\/lib\//}/bin/moc" +- UIC="${with_qt5//\/include\//\/lib\//}/bin/uic" +- RCC="${with_qt5//\/include\//\/lib\//}/bin/rcc" +- LRELEASE="${with_qt5//\/include\//\/lib\//}/bin/lrelease" ++ MOC="${with_qt5//\/include\//\/lib64\//}/bin/moc" ++ UIC="${with_qt5//\/include\//\/lib64\//}/bin/uic" ++ RCC="${with_qt5//\/include\//\/lib64\//}/bin/rcc" ++ LRELEASE="${with_qt5//\/include\//\/lib64\//}/bin/lrelease" + AC_SUBST([MOC]) + AC_SUBST([UIC]) + AC_SUBST([RCC]) diff --git a/Docker/Debian/Dockerfile_Buster b/Docker/Debian/Dockerfile_Buster new file mode 100644 index 0000000000..c8fd83f40c --- /dev/null +++ b/Docker/Debian/Dockerfile_Buster @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-debian-buster:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Debian Buster" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Debian Buster" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Debian-Buster.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Debian-Buster.sha256" +ENV CHKSUM_FILE="Checksum-Alias-Debian-Buster.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/Debian/Dockerfile_Buster_noUpload b/Docker/Debian/Dockerfile_Buster_noUpload new file mode 100644 index 0000000000..c1d979c50e --- /dev/null +++ b/Docker/Debian/Dockerfile_Buster_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-debian-buster:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Debian Buster (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/Debian/Dockerfile_Stretch b/Docker/Debian/Dockerfile_Stretch new file mode 100644 index 0000000000..3ad7453a2a --- /dev/null +++ b/Docker/Debian/Dockerfile_Stretch @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-debian-stretch:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Debian Stretch" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Debian Stretch" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Debian-Stretch.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Debian-Stretch.sha256" +ENV CHKSUM_FILE="Checksum-Alias-Debian-Stretch.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/Debian/Dockerfile_Stretch_noUpload b/Docker/Debian/Dockerfile_Stretch_noUpload new file mode 100644 index 0000000000..99b5cb54a5 --- /dev/null +++ b/Docker/Debian/Dockerfile_Stretch_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-debian-stretch:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Debian Stretch (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/Fedora/Dockerfile b/Docker/Fedora/Dockerfile new file mode 100644 index 0000000000..4bcb567808 --- /dev/null +++ b/Docker/Fedora/Dockerfile @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-fedora:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Fedora" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Fedora" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Fedora.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Fedora.sha256" +ENV CHKSUM_FILE="Checksum-Alias-Fedora.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/Fedora/Dockerfile_noUpload b/Docker/Fedora/Dockerfile_noUpload new file mode 100644 index 0000000000..7a5d25fb48 --- /dev/null +++ b/Docker/Fedora/Dockerfile_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-fedora:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Fedora (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/Fedora/QT5BinaryPath.patch b/Docker/Fedora/QT5BinaryPath.patch new file mode 100644 index 0000000000..5247dd02f4 --- /dev/null +++ b/Docker/Fedora/QT5BinaryPath.patch @@ -0,0 +1,17 @@ +--- configure.ac 2018-07-22 22:50:33.225640603 +0200 ++++ configure.ac.fedora 2018-08-03 23:39:28.970937691 +0200 +@@ -78,10 +78,10 @@ + AC_SUBST([QT5_CFLAGS]) + AC_SUBST([QT5_LDFLAGS]) + AC_SUBST([QT5_LIBS]) +- MOC="${with_qt5//\/include\//\/lib\//}/bin/moc" +- UIC="${with_qt5//\/include\//\/lib\//}/bin/uic" +- RCC="${with_qt5//\/include\//\/lib\//}/bin/rcc" +- LRELEASE="${with_qt5//\/include\//\/lib\//}/bin/lrelease" ++ MOC="${with_qt5//\/include\//\/lib64\//}/bin/moc" ++ UIC="${with_qt5//\/include\//\/lib64\//}/bin/uic" ++ RCC="${with_qt5//\/include\//\/lib64\//}/bin/rcc" ++ LRELEASE="${with_qt5//\/include\//\/lib64\//}/bin/lrelease" + AC_SUBST([MOC]) + AC_SUBST([UIC]) + AC_SUBST([RCC]) diff --git a/Docker/OpenSUSE/Dockerfile b/Docker/OpenSUSE/Dockerfile new file mode 100644 index 0000000000..5a941e7fe6 --- /dev/null +++ b/Docker/OpenSUSE/Dockerfile @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-opensuse-tumbleweed:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for openSUSE Tumbleweed" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for openSUSE Tumbleweed" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-OpenSUSE-Tumbleweed.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-OpenSUSE-Tumbleweed.sha256" +ENV CHKSUM_FILE="Checksum-Alias-OpenSUSE-Tumbleweed.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/OpenSUSE/Dockerfile_noUpload b/Docker/OpenSUSE/Dockerfile_noUpload new file mode 100644 index 0000000000..a31c697e0c --- /dev/null +++ b/Docker/OpenSUSE/Dockerfile_noUpload @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-opensuse-tumbleweed:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for openSUSE Tumbleweed (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/RaspberryPi/Dockerfile_Buster b/Docker/RaspberryPi/Dockerfile_Buster new file mode 100644 index 0000000000..3fd58f6520 --- /dev/null +++ b/Docker/RaspberryPi/Dockerfile_Buster @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-raspi-buster:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Raspberry Pi (Buster)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Raspberry Pi (Buster)" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-RaspberryPi-Buster-aarch64.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-RaspberryPi-Buster-aarch64.sha256" +ENV CHKSUM_FILE="Checksum-Alias-RaspberryPi-Buster-aarch64.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/RaspberryPi/Dockerfile_Buster_noUpload b/Docker/RaspberryPi/Dockerfile_Buster_noUpload new file mode 100644 index 0000000000..5ee6b08f9d --- /dev/null +++ b/Docker/RaspberryPi/Dockerfile_Buster_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-raspi-buster:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Raspberry Pi Buster (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/Ubuntu/Dockerfile_18_04 b/Docker/Ubuntu/Dockerfile_18_04 new file mode 100644 index 0000000000..0547d92003 --- /dev/null +++ b/Docker/Ubuntu/Dockerfile_18_04 @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-ubuntu-18-04:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Ubuntu 18.04" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Ubuntu 18.04" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Ubuntu-18-04.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Ubuntu-18-04.sha256" +ENV CHKSUM_FILE="Checksum-Alias-Ubuntu-18-04.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/Ubuntu/Dockerfile_18_04_noUpload b/Docker/Ubuntu/Dockerfile_18_04_noUpload new file mode 100644 index 0000000000..38c5f2a0a0 --- /dev/null +++ b/Docker/Ubuntu/Dockerfile_18_04_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-ubuntu-18-04:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Ubuntu 18.04 (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/Docker/Ubuntu/Dockerfile_20_04 b/Docker/Ubuntu/Dockerfile_20_04 new file mode 100644 index 0000000000..88b34ef579 --- /dev/null +++ b/Docker/Ubuntu/Dockerfile_20_04 @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Stage 1: Build Alias Wallet +# ============================================================================= +FROM aliascash/alias-wallet-builder-ubuntu-20-04:2.6 AS build + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build stage for Ubuntu 20.04" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet + +# ============================================================================= +# Stage 2: Upload binaries to GitHub +# ============================================================================= +FROM aliascash/github-uploader:latest AS uploader + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet upload stage for Ubuntu 20.04" + +ARG GITHUB_CI_TOKEN=1234567 +ARG ALIAS_RELEASE=latest +ARG ALIAS_REPOSITORY=alias-wallet +ARG GIT_COMMIT=unknown +ARG REPLACE_EXISTING_ARCHIVE='' + +ENV ARCHIVE="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Ubuntu-20-04.tgz" +ENV ARCHIVE_CHKSUM="Alias-${ALIAS_RELEASE}-${GIT_COMMIT}-Ubuntu-20-04.sha256" +ENV CHKSUM_FILE="Checksum-Alias-Ubuntu-20-04.txt" + +WORKDIR /filesToUpload + +RUN mkdir -p /filesToUpload/usr/local/bin + +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet /filesToUpload/usr/local/bin/ +COPY --from=build /alias-wallet/scripts/createChecksums.sh /tmp/ + +RUN tar czf "${ARCHIVE}" . \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE}" \ + --file "/filesToUpload/${ARCHIVE}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && sha256sum "/filesToUpload/${ARCHIVE}" | awk '{ print $1 }' > "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && cat "/filesToUpload/${ARCHIVE_CHKSUM}" \ + && github-release upload \ + --user aliascash \ + --security-token "${GITHUB_CI_TOKEN}" \ + --repo "${ALIAS_REPOSITORY}" \ + --tag "${ALIAS_RELEASE}" \ + --name "${ARCHIVE_CHKSUM}" \ + --file "/filesToUpload/${ARCHIVE_CHKSUM}" \ + ${REPLACE_EXISTING_ARCHIVE} \ + && chmod +x /tmp/createChecksums.sh \ + && sh /tmp/createChecksums.sh "/filesToUpload/${ARCHIVE}" "${CHKSUM_FILE}" \ + && unset GITHUB_CI_TOKEN diff --git a/Docker/Ubuntu/Dockerfile_20_04_noUpload b/Docker/Ubuntu/Dockerfile_20_04_noUpload new file mode 100644 index 0000000000..81ec2736f4 --- /dev/null +++ b/Docker/Ubuntu/Dockerfile_20_04_noUpload @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# ============================================================================= +# Build Alias Wallet (no upload) +# ============================================================================= +FROM aliascash/alias-wallet-builder-ubuntu-20-04:2.6 + +LABEL maintainer="HLXEasy " +LABEL description="Alias Wallet build for Ubuntu 20.04 (no upload)" + +ARG BUILD_THREADS="6" +ENV BUILD_THREADS=${BUILD_THREADS} + +WORKDIR /alias-wallet +COPY . . + +RUN ./scripts/cmake-build.sh -g -o -s -c "${BUILD_THREADS}" \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswalletd \ + && strip /alias-wallet/cmake-build-cmdline/aliaswallet/src/aliaswallet diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 27001594d9..0000000000 --- a/INSTALL +++ /dev/null @@ -1,9 +0,0 @@ -Building ShadowCoin - -See doc/readme-qt.rst for instructions on building ShadowCoin QT, -the intended-for-end-users, nice-graphical-interface, reference -implementation of ShadowCoin. - -See doc/build-*.txt for instructions on building shadowcoind, -the intended-for-services, no-graphical-interface, reference -implementation of ShadowCoin. diff --git a/Jenkinsfile_disabled b/Jenkinsfile_disabled new file mode 100644 index 0000000000..6ec4e7e64b --- /dev/null +++ b/Jenkinsfile_disabled @@ -0,0 +1,987 @@ +#!groovy +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +pipeline { + agent { + label "housekeeping" + } + options { + timestamps() + timeout(time: 4, unit: 'HOURS') + buildDiscarder(logRotator(numToKeepStr: '30', artifactNumToKeepStr: '1')) + disableConcurrentBuilds() + } + environment { + // In case another branch beside master or develop should be deployed, enter it here + BRANCH_TO_DEPLOY = "xyz" + DISCORD_WEBHOOK = credentials('DISCORD_WEBHOOK') + GITHUB_CI_TOKEN = credentials('GITHUB_CI_TOKEN') + CI_URL = credentials('CI_URL') + ACCESS_TOKEN = credentials('ci_read_access') + DEVELOP_TAG = "Build${BUILD_NUMBER}" + RELEASE_TAG = sh( + script: "printf \$(grep CLIENT_VERSION_MAJOR CMakeLists.txt | head -n1 | cut -d ' ' -f2 | sed 's/)//g' | tr -d '\\n' | tr -d '\\r').\$(grep CLIENT_VERSION_MINOR CMakeLists.txt | head -n1 | cut -d ' ' -f2 | sed 's/)//g' | tr -d '\\n' | tr -d '\\r').\$(grep CLIENT_VERSION_REVISION CMakeLists.txt | head -n1 | cut -d ' ' -f2 | sed 's/)//g' | tr -d '\\n' | tr -d '\\r') | sed 's/ //g'", + returnStdout: true + ) + GIT_TAG_TO_USE = "${DEVELOP_TAG}" + GIT_COMMIT_SHORT = sh( + script: "printf \$(git rev-parse --short ${GIT_COMMIT})", + returnStdout: true + ) + CURRENT_DATE = sh( + script: "printf \"\$(date '+%F %T')\"", + returnStdout: true + ) + RELEASE_NAME = "Continuous build #${BUILD_NUMBER} (Branch ${GIT_BRANCH})" + RELEASE_DESCRIPTION = "Build ${BUILD_NUMBER} from ${CURRENT_DATE}" + PRERELEASE = "true" + } + stages { + stage('Notification') { + steps { + // Using result state 'ABORTED' to mark the message on discord with a white border. + // Makes it easier to distinguish job-start from job-finished + discordSend( + description: "Started build #$env.BUILD_NUMBER", + image: '', + //link: "$env.BUILD_URL", + successful: true, + result: "ABORTED", + thumbnail: 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png', + title: "$env.JOB_NAME", + webhookURL: DISCORD_WEBHOOK + ) + } + } + stage('Cleanup') { + steps { + sh "git clean -fd" + } + } + stage('Feature branch') { + when { + not { + anyOf { branch 'develop'; branch 'master'; branch "${BRANCH_TO_DEPLOY}" } + } + } + //noinspection GroovyAssignabilityCheck + parallel { + stage('Raspberry Pi Buster arm64') { + agent { + label "raspi" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/RaspberryPi/Dockerfile_Buster_noUpload', + dockerTag: "aliascash/alias-wallet-raspi-buster:${GIT_TAG_TO_USE}", + ) + sh "docker rmi aliascash/alias-wallet-raspi-buster:${GIT_TAG_TO_USE}" + } + } + } + stage('CentOS 8') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/CentOS/Dockerfile_noUpload', + dockerTag: "aliascash/alias-wallet-centos-8:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-centos-8:${GIT_TAG_TO_USE}" + } + } + } + stage('Debian Stretch') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/Debian/Dockerfile_Stretch_noUpload', + dockerTag: "aliascash/alias-wallet-debian-stretch:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-debian-stretch:${GIT_TAG_TO_USE}" + } + } + } + stage('Debian Buster') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/Debian/Dockerfile_Buster_noUpload', + dockerTag: "aliascash/alias-wallet-debian-buster:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-debian-buster:${GIT_TAG_TO_USE}" + } + } + } + stage('Fedora') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/Fedora/Dockerfile_noUpload', + dockerTag: "aliascash/alias-wallet-fedora:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-fedora:${GIT_TAG_TO_USE}" + } + } + } + stage('OpenSUSE') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/OpenSUSE/Dockerfile_noUpload', + dockerTag: "aliascash/alias-wallet-opensuse-tumbleweed:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-opensuse-tumbleweed:${GIT_TAG_TO_USE}" + } + } + } + stage('Ubuntu 18.04') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/Ubuntu/Dockerfile_18_04_noUpload', + dockerTag: "aliascash/alias-wallet-ubuntu-18-04:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-ubuntu-18-04:${GIT_TAG_TO_USE}" + } + } + } + stage('Ubuntu 20.04') { + agent { + label "docker" + } + steps { + script { + buildFeatureBranch( + dockerfile: 'Docker/Ubuntu/Dockerfile_20_04_noUpload', + dockerTag: "aliascash/alias-wallet-ubuntu-20-04:${GIT_TAG_TO_USE}" + ) + sh "docker rmi aliascash/alias-wallet-ubuntu-20-04:${GIT_TAG_TO_USE}" + } + } + } + stage('Mac') { + agent { + label "mac" + } + environment { + BOOST_PATH = "${BOOST_PATH_MAC}" + OPENSSL_PATH = "${OPENSSL_PATH_MAC}" + QT_PATH = "${QT_PATH_MAC_512}" + PATH = "/usr/local/bin:${QT_PATH}/bin:$PATH" + MACOSX_DEPLOYMENT_TARGET = 10.12 + } + steps { + script { + sh( + script: """ + pwd + ./scripts/cmake-build-mac.sh -g + cp ./cmake-build-cmdline-mac/aliaswallet/Alias.dmg Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg + """ + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg" + } + } + } + stage('Windows Qt5.12.x') { + stages { +// stage('Start Windows slave') { +// steps { +// withCredentials([[ +// $class : 'AmazonWebServicesCredentialsBinding', +// credentialsId : '91c4a308-07cd-4468-896c-3d75d086190d', +// accessKeyVariable: 'AWS_ACCESS_KEY_ID', +// secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' +// ]]) { +// sh( +// script: """ +// docker run \ +// --rm \ +// --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ +// --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ +// --env AWS_DEFAULT_REGION=eu-west-1 \ +// garland/aws-cli-docker \ +// aws ec2 start-instances --instance-ids i-06fb7942772e77e55 +// """ +// ) +// } +// } +// } + stage('Win + Qt5.12.x') { + agent { + label "windows" + } + environment { + QTDIR = "${QT_DIR_WIN_512}" + VSDIR = "${VS2019_DIR}" + CMAKEDIR = "${CMAKE_DIR}" + VCPKGDIR = "${VCPKG_DIR}" + } + steps { + script { + bat 'scripts/cmake-build-win.bat' + } + } + } + } + } +// stage('Windows Qt5.15.x') { +// stages { +// stage('Start Windows slave') { +// steps { +// withCredentials([[ +// $class : 'AmazonWebServicesCredentialsBinding', +// credentialsId : '91c4a308-07cd-4468-896c-3d75d086190d', +// accessKeyVariable: 'AWS_ACCESS_KEY_ID', +// secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' +// ]]) { +// sh( +// script: """ +// docker run \ +// --rm \ +// --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ +// --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ +// --env AWS_DEFAULT_REGION=eu-west-1 \ +// garland/aws-cli-docker \ +// aws ec2 start-instances --instance-ids i-06fb7942772e77e55 +// """ +// ) +// } +// } +// } +// stage('Win + Qt5.15.x') { +// agent { +// label "windows2" +// } +// environment { +// QTDIR = "${QT_DIR_WIN}" +// VSDIR = "${VS2019_DIR}" +// CMAKEDIR = "${CMAKE_DIR}" +// VCPKGDIR = "${VCPKG_DIR}" +// } +// steps { +// script { +// bat 'scripts/cmake-build-win.bat' +// } +// } +// } +// } +// } + } + } + stage('Prepare master branch build') { + when { + branch 'master' + } + stages { + stage('Setup env vars to use') { + steps { + script { + GIT_TAG_TO_USE = "${RELEASE_TAG}" + RELEASE_NAME = "Release ${GIT_TAG_TO_USE}" + RELEASE_DESCRIPTION = "${WORKSPACE}/ReleaseNotes.md" + PRERELEASE = "false" + } + } + } + } + } + stage('Git tag handling') { + when { + anyOf { branch 'master'; branch 'develop'; branch "${BRANCH_TO_DEPLOY}" } + } + stages { + stage('Create Git tag') { + steps { + sshagent(credentials: ['Github-SSH-Login']) { + createTag( + tag: "${GIT_TAG_TO_USE}", + commit: "${GIT_COMMIT_SHORT}", + comment: "Created tag ${GIT_TAG_TO_USE}" + ) + } + } + } + stage('Remove Github release if already existing') { + when { + expression { + return isReleaseExisting( + githubCIToken: GITHUB_CI_TOKEN, + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}" + ) ==~ true + } + } + steps { + script { + removeRelease( + githubCIToken: GITHUB_CI_TOKEN, + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}" + ) + } + } + } + stage('Create Github release') { + when { + expression { + return isReleaseExisting( + githubCIToken: GITHUB_CI_TOKEN, + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}" + ) ==~ false + } + } + steps { + script { + createRelease( + githubCIToken: GITHUB_CI_TOKEN, + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}", + name: "${RELEASE_NAME}", + description: "${RELEASE_DESCRIPTION}", + preRelease: "${PRERELEASE}" + ) + } + } + } + } + } + stage('Develop/Master') { + when { + anyOf { branch 'master'; branch 'develop'; branch "${BRANCH_TO_DEPLOY}" } + } + //noinspection GroovyAssignabilityCheck + parallel { + stage('Raspberry Pi Buster') { + agent { + label "raspi" + } + stages { + stage('Raspberry Pi Buster') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/RaspberryPi/Dockerfile_Buster', + dockerTag: "aliascash/alias-wallet-raspi-buster:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-raspi-buster:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-RaspberryPi-Buster-aarch64.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-RaspberryPi-Buster-aarch64.txt" + sh "docker rmi aliascash/alias-wallet-raspi-buster:${GIT_TAG_TO_USE}" + } + } + } + stage('Trigger image build') { + steps { + build( + job: 'Alias/pi-gen/alias_arm64', + parameters: [ + string( + name: 'ALIAS_RELEASE', + value: "${GIT_TAG_TO_USE}" + ), + string( + name: 'GIT_COMMIT_SHORT', + value: "${GIT_COMMIT_SHORT}" + ) + ], + wait: false + ) + } + } + } + } + stage('CentOS 8') { + agent { + label "docker" + } + stages { + stage('CentOS 8') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/CentOS/Dockerfile', + dockerTag: "aliascash/alias-wallet-centos-8:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-centos-8:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-CentOS-8.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-CentOS-8.txt" + sh "docker rmi aliascash/alias-wallet-centos-8:${GIT_TAG_TO_USE}" + } + } + } + } + } + stage('Debian Stretch') { + agent { + label "docker" + } + stages { + stage('Debian Stretch') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/Debian/Dockerfile_Stretch', + dockerTag: "aliascash/alias-wallet-debian-stretch:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-debian-stretch:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-Debian-Stretch.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-Debian-Stretch.txt" + sh "docker rmi aliascash/alias-wallet-debian-stretch:${GIT_TAG_TO_USE}" + } + } + } + } + } + stage('Debian Buster') { + agent { + label "docker" + } + stages { + stage('Debian Buster') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/Debian/Dockerfile_Buster', + dockerTag: "aliascash/alias-wallet-debian-buster:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-debian-buster:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-Debian-Buster.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-Debian-Buster.txt" + sh "docker rmi aliascash/alias-wallet-debian-buster:${GIT_TAG_TO_USE}" + } + } + } + } + } + stage('Fedora') { + agent { + label "docker" + } + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/Fedora/Dockerfile', + dockerTag: "aliascash/alias-wallet-fedora:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-fedora:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-Fedora.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-Fedora.txt" + sh "docker rmi aliascash/alias-wallet-fedora:${GIT_TAG_TO_USE}" + } + } + } + stage('OpenSUSE') { + agent { + label "docker" + } + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/OpenSUSE/Dockerfile', + dockerTag: "aliascash/alias-wallet-opensuse-tumbleweed:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-opensuse-tumbleweed:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-OpenSUSE-Tumbleweed.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-OpenSUSE-Tumbleweed.txt" + sh "docker rmi aliascash/alias-wallet-opensuse-tumbleweed:${GIT_TAG_TO_USE}" + } + } + } + stage('Ubuntu 18.04') { + agent { + label "docker" + } + stages { + stage('Ubuntu 18.04') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/Ubuntu/Dockerfile_18_04', + dockerTag: "aliascash/alias-wallet-ubuntu-18-04:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-ubuntu-18-04:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-Ubuntu-18-04.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-Ubuntu-18-04.txt" + sh "docker rmi aliascash/alias-wallet-ubuntu-18-04:${GIT_TAG_TO_USE}" + } + } + } + } + } + stage('Ubuntu 20.04') { + agent { + label "docker" + } + stages { + stage('Ubuntu 20.04') { + steps { + script { + buildBranch( + githubCIToken: GITHUB_CI_TOKEN, + dockerfile: 'Docker/Ubuntu/Dockerfile_20_04', + dockerTag: "aliascash/alias-wallet-ubuntu-20-04:${GIT_TAG_TO_USE}", + gitTag: "${GIT_TAG_TO_USE}", + gitCommit: "${GIT_COMMIT_SHORT}" + ) + getChecksumfileFromImage( + dockerTag: "aliascash/alias-wallet-ubuntu-20-04:${GIT_TAG_TO_USE}", + checksumfile: "Checksum-Alias-Ubuntu-20-04.txt" + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Checksum-Alias-Ubuntu-20-04.txt" + sh "docker rmi aliascash/alias-wallet-ubuntu-20-04:${GIT_TAG_TO_USE}" + } + } + } + stage('Trigger Docker image build') { + steps { + build( + job: "Alias/docker-aliaswalletd/${GIT_BRANCH}", + parameters: [ + string( + name: 'ALIAS_RELEASE', + value: "${GIT_TAG_TO_USE}" + ), + string( + name: 'GIT_COMMIT_SHORT', + value: "${GIT_COMMIT_SHORT}" + ) + ], + wait: false + ) + } + } + } + } + stage('Mac') { + agent { + label "mac" + } + environment { + BOOST_PATH = "${BOOST_PATH_MAC}" + OPENSSL_PATH = "${OPENSSL_PATH_MAC}" + QT_PATH = "${QT_PATH_MAC_512}" + PATH = "/usr/local/bin:${QT_PATH}/bin:$PATH" + MACOSX_DEPLOYMENT_TARGET = 10.12 + } + stages { + stage('MacOS build') { + steps { + script { + sh( + script: """ + pwd + ./scripts/cmake-build-mac.sh -g + cp ./cmake-build-cmdline-mac/aliaswallet/Alias.dmg Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg + """ + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg" + } + } + } + stage('Upload deliveries') { + agent { + label "housekeeping" + } + steps { + script { + sh( + script: """ + rm -f Alias*.dmg* + curl -L \ + --user "${ACCESS_TOKEN}" \ + ${CI_URL}/job/Alias/job/alias-wallet/job/${GIT_BRANCH}/${BUILD_NUMBER}/artifact/Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg \ + --output Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg || true + """ + ) + uploadArtifactToGitHub( + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}", + artifactNameRemote: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg", + ) + createAndArchiveChecksumFile( + filename: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Mac.dmg", + checksumfile: "Checksum-Alias-Mac.txt" + ) + sh "rm -f Alias*.dmg* Checksum-Alias*" + } + } + } + } + } + stage('Windows Qt5.12.x') { + stages { +// stage('Start Windows slave') { +// steps { +// withCredentials([[ +// $class : 'AmazonWebServicesCredentialsBinding', +// credentialsId : '91c4a308-07cd-4468-896c-3d75d086190d', +// accessKeyVariable: 'AWS_ACCESS_KEY_ID', +// secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' +// ]]) { +// sh( +// script: """ +// docker run \ +// --rm \ +// --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ +// --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ +// --env AWS_DEFAULT_REGION=eu-west-1 \ +// garland/aws-cli-docker \ +// aws ec2 start-instances --instance-ids i-06fb7942772e77e55 +// """ +// ) +// } +// } +// } + stage('Win + Qt5.12.x') { + agent { + label "windows" + } + environment { + QTDIR = "${QT_DIR_WIN_512}" + VSDIR = "${VS2019_DIR}" + CMAKEDIR = "${CMAKE_DIR}" + VCPKGDIR = "${VCPKG_DIR}" + } + steps { + script { + bat( + script: """ + if exist build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip del build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip + scripts/cmake-build-win.bat + """ + ) + zip( + zipFile: "${WORKSPACE}/build/Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip", + dir: "${WORKSPACE}/build", + glob: "Alias/**" + ) + bat( + script: """ + if exist build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip copy build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip + """ + ) + archiveArtifacts allowEmptyArchive: true, artifacts: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip" + build( + job: 'Alias/installer/master', + parameters: [ + string( + name: 'ARCHIVE_LOCATION', + value: "${WORKSPACE}/build" + ), + string( + name: 'ARCHIVE_NAME', + value: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64-Qt5.12.zip" + ), + string( + name: 'GIT_TAG_TO_USE', + value: "${GIT_TAG_TO_USE}" + ), + string( + name: 'GIT_COMMIT_SHORT', + value: "${GIT_COMMIT_SHORT}" + ) + ], + wait: false + ) + } + } + } + stage('Upload deliveries') { + steps { + uploadDeliveries("-Qt5.12") + } + } + } + } +// stage('Windows Qt5.15.x') { +// stages { +// stage('Start Windows slave') { +// steps { +// withCredentials([[ +// $class : 'AmazonWebServicesCredentialsBinding', +// credentialsId : '91c4a308-07cd-4468-896c-3d75d086190d', +// accessKeyVariable: 'AWS_ACCESS_KEY_ID', +// secretKeyVariable: 'AWS_SECRET_ACCESS_KEY' +// ]]) { +// sh( +// script: """ +// docker run \ +// --rm \ +// --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \ +// --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \ +// --env AWS_DEFAULT_REGION=eu-west-1 \ +// garland/aws-cli-docker \ +// aws ec2 start-instances --instance-ids i-06fb7942772e77e55 +// """ +// ) +// } +// } +// } +// stage('Win + Qt5.15.x') { +// agent { +// label "windows2" +// } +// environment { +// QTDIR = "${QT_DIR_WIN}" +// VSDIR = "${VS2019_DIR}" +// CMAKEDIR = "${CMAKE_DIR}" +// VCPKGDIR = "${VCPKG_DIR}" +// } +// steps { +// script { +// bat( +// script: """ +// if exist build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip del build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip +// scripts/cmake-build-win.bat +// """ +// ) +// zip( +// zipFile: "${WORKSPACE}/build/Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip", +// dir: "${WORKSPACE}/build", +// glob: "Alias/**" +// ) +// bat( +// script: """ +// if exist build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip copy build\\Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip +// """ +// ) +// archiveArtifacts allowEmptyArchive: true, artifacts: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64.zip" +// } +// } +// } +// stage('Upload deliveries') { +// steps { +// uploadDeliveries("") +// } +// } +// } +// } + } + post { + always { + script { + sh( + script: """ + ${WORKSPACE}/scripts/createChecksumSummary.sh \ + "${RELEASE_DESCRIPTION}" \ + "${WORKSPACE}" \ + "${CI_URL}/job/Alias/job/alias-wallet/job/${GIT_BRANCH}/${BUILD_NUMBER}" \ + "${ACCESS_TOKEN}" + """ + ) + editRelease( + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}", + name: "${RELEASE_NAME}", + description: "${WORKSPACE}/releaseNotesToDeploy.txt", + preRelease: "${PRERELEASE}" + ) + uploadArtifactToGitHub( + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}", + artifactNameLocal: "releaseNotesToDeploy.txt", + artifactNameRemote: "RELEASENOTES.txt", + ) + } + } + } + } + stage('Update download links') { + when { + branch 'master' + } + steps { + echo "Update of download links currently disabled" +// build( +// job: 'updateDownloadURLs', +// parameters: [ +// string( +// name: 'RELEASE_VERSION', +// value: "${GIT_TAG_TO_USE}" +// ), +// string( +// name: 'GIT_COMMIT_SHORT', +// value: "${GIT_COMMIT_SHORT}" +// ) +// ], +// wait: false +// ) + } + } + } + post { + success { + script { + if (!hudson.model.Result.SUCCESS.equals(currentBuild.getPreviousBuild()?.getResult())) { + emailext( + subject: "GREEN: '${env.JOB_NAME} [${env.BUILD_NUMBER}]'", + body: '${JELLY_SCRIPT,template="html"}', + recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], +// to: "to@be.defined", +// replyTo: "to@be.defined" + ) + } + discordSend( + description: "Build #$env.BUILD_NUMBER finished successfully", + image: '', + //link: "$env.BUILD_URL", + successful: true, + thumbnail: 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png', + title: "$env.JOB_NAME", + webhookURL: DISCORD_WEBHOOK + ) + } + } + unstable { + emailext( + subject: "YELLOW: '${env.JOB_NAME} [${env.BUILD_NUMBER}]'", + body: '${JELLY_SCRIPT,template="html"}', + recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], +// to: "to@be.defined", +// replyTo: "to@be.defined" + ) + discordSend( + description: "Build #$env.BUILD_NUMBER finished unstable", + image: '', + //link: "$env.BUILD_URL", + successful: true, + result: "UNSTABLE", + thumbnail: 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png', + title: "$env.JOB_NAME", + webhookURL: DISCORD_WEBHOOK + ) + } + failure { + emailext( + subject: "RED: '${env.JOB_NAME} [${env.BUILD_NUMBER}]'", + body: '${JELLY_SCRIPT,template="html"}', + recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], +// to: "to@be.defined", +// replyTo: "to@be.defined" + ) + discordSend( + description: "Build #$env.BUILD_NUMBER failed!", + image: '', + //link: "$env.BUILD_URL", + successful: false, + thumbnail: 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png', + title: "$env.JOB_NAME", + webhookURL: DISCORD_WEBHOOK + ) + } + aborted { + discordSend( + description: "Build #$env.BUILD_NUMBER was aborted", + image: '', + //link: "$env.BUILD_URL", + successful: true, + result: "ABORTED", + thumbnail: 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png', + title: "$env.JOB_NAME", + webhookURL: DISCORD_WEBHOOK + ) + } + } +} + +def buildWindows(def suffix) { + prepareWindowsBuild() + bat 'scripts\\win-genbuild.bat' + bat 'scripts\\win-build.bat' + createWindowsDelivery( + version: "${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}", + suffix: "${suffix}" + ) +} + +def uploadDeliveries(def suffix) { + script { + sh( + script: """ + rm -f Alias-*-Win64${suffix}.zip + curl -L \\ + --user "${ACCESS_TOKEN}" \\ + ${CI_URL}/job/Alias/job/alias-wallet/job/${GIT_BRANCH}/${BUILD_NUMBER}/artifact/Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64${suffix}.zip \\ + --output Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64${suffix}.zip || true + """ + ) + uploadArtifactToGitHub( + user: 'aliascash', + repository: 'alias-wallet', + tag: "${GIT_TAG_TO_USE}", + artifactNameRemote: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64${suffix}.zip", + ) + createAndArchiveChecksumFile( + filename: "Alias-${GIT_TAG_TO_USE}-${GIT_COMMIT_SHORT}-Win64${suffix}.zip", + checksumfile: "Checksum-Alias-Win64${suffix}.txt" + ) + sh "rm -f Alias-*-Win64${suffix}.zip Checksum-Alias-Win64${suffix}.txt" + } +} \ No newline at end of file diff --git a/LICENSES/BSD-2-Clause.txt b/LICENSES/BSD-2-Clause.txt new file mode 100644 index 0000000000..b566df3035 --- /dev/null +++ b/LICENSES/BSD-2-Clause.txt @@ -0,0 +1,24 @@ +LZ4 Library +Copyright (c) 2011-2014, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. \ No newline at end of file diff --git a/LICENSES/BSD-4-Clause.txt b/LICENSES/BSD-4-Clause.txt new file mode 100644 index 0000000000..67dea8b275 --- /dev/null +++ b/LICENSES/BSD-4-Clause.txt @@ -0,0 +1,10 @@ +Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, . 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. All advertising materials mentioning features or use of this software must display the following acknowledgement: +This product includes software developed by the organization. +4. Neither the name of the copyright holder 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 COPYRIGHT HOLDER "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 COPYRIGHT HOLDER 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. \ No newline at end of file diff --git a/LICENSES/BSL-1.0.txt b/LICENSES/BSL-1.0.txt new file mode 100644 index 0000000000..f52b77a2e1 --- /dev/null +++ b/LICENSES/BSL-1.0.txt @@ -0,0 +1,7 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/LICENSES/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt new file mode 100644 index 0000000000..c43ce7174c --- /dev/null +++ b/LICENSES/CC-BY-4.0.txt @@ -0,0 +1,99 @@ +Creative Commons Attribution 4.0 International + +Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. + +Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors + +Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public : wiki.creativecommons.org/Considerations_for_licensees + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. + +Section 1 – Definitions. + +a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. +b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. +c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. +d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. +e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. +f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. +g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. +h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. +i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. +j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. +k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. +Section 2 – Scope. + +a. License grant. +1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: +A. reproduce and Share the Licensed Material, in whole or in part; and +B. produce, reproduce, and Share Adapted Material. +2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. +3. Term. The term of this Public License is specified in Section 6(a). +4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. +5. Downstream recipients. +A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. +B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. +6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). +b. Other rights. +1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. +2. Patent and trademark rights are not licensed under this Public License. +3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + +a. Attribution. +1. If You Share the Licensed Material (including in modified form), You must: +A. retain the following if it is supplied by the Licensor with the Licensed Material: +i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); +ii. a copyright notice; +iii. a notice that refers to this Public License; +iv. a notice that refers to the disclaimer of warranties; +v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; +B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and +C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. +2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. +3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. +4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + +a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; +b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and +c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + +a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. +b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. +c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. +Section 6 – Term and Termination. + +a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. +b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: +1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or +2. upon express reinstatement by the Licensor. +c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. +d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. +e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. +Section 7 – Other Terms and Conditions. + +a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. +b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. +Section 8 – Interpretation. + +a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. +b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. +c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. +d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. +Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSES/GPL-2.0-or-later.txt b/LICENSES/GPL-2.0-or-later.txt new file mode 100644 index 0000000000..7c11a6acc4 --- /dev/null +++ b/LICENSES/GPL-2.0-or-later.txt @@ -0,0 +1,71 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 100644 index 0000000000..6f248655f4 --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1,200 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. +"This License" refers to version 3 of the GNU General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based on the Program. + +To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. +A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: +a) The work must carry prominent notices stating that you modified it, and giving a relevant date. +b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". +c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. +d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: +a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. +b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. +c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. +d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. +e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +7. Additional Terms. +"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or +b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or +c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or +d) Limiting the use for publicity purposes of names of licensors or authors of the material; or +e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or +f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. +All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. +An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +11. Patents. +A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". +A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + +Copyright (C) + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) +This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". + +You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . \ No newline at end of file diff --git a/LICENSES/ISC.txt b/LICENSES/ISC.txt new file mode 100644 index 0000000000..96720afb3c --- /dev/null +++ b/LICENSES/ISC.txt @@ -0,0 +1,8 @@ +ISC License + +Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") +Copyright (c) 1995-2003 by Internet Software Consortium + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/COPYING b/LICENSES/MIT.txt similarity index 79% rename from COPYING rename to LICENSES/MIT.txt index 3db8df0dd4..d43f871e3c 100644 --- a/COPYING +++ b/LICENSES/MIT.txt @@ -1,8 +1,11 @@ -Copyright (c) 2014-2015 ShadowCoin Developers +Copyright (c) 2025 ALIAS Developers +Copyright (c) 2020 Alias Developers +Copyright (c) 2016 SpectreCoin Developers +Copyright (c) 2014 ShadowCoin Developers Copyright (c) 2014 BlackCoin Developers -Copyright (c) 2013-2014 NovaCoin Developers -Copyright (c) 2011-2012 PPCoin Developers -Copyright (c) 2009-2014 Bitcoin Developers +Copyright (c) 2013 NovaCoin Developers +Copyright (c) 2011 PPCoin Developers +Copyright (c) 2009 Bitcoin Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSES/OFL-1.1.txt b/LICENSES/OFL-1.1.txt new file mode 100644 index 0000000000..131165ec60 --- /dev/null +++ b/LICENSES/OFL-1.1.txt @@ -0,0 +1,45 @@ +Copyright (c) , (), +with Reserved Font Name . + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE + +Version 1.1 - 26 February 2007 + +PREAMBLE + +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS + +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. +TERMINATION + +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/LICENSES/Unlicense.txt b/LICENSES/Unlicense.txt new file mode 100644 index 0000000000..fdcbed0835 --- /dev/null +++ b/LICENSES/Unlicense.txt @@ -0,0 +1,10 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. + +In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000000..08ee085bd4 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +ACLOCAL_AMFLAGS = -I m4 + +if OS_WINDOWS_CROSSCOMPILE +# for leveldb +AM_MAKEFLAGS = TARGET_OS=OS_WINDOWS_CROSSCOMPILE +endif + +export CC CXX AR LD +SUBDIRS = db4.8/build_unix leveldb src + +Aliaswallet.app: all-am + mkdir -p Aliaswallet.app/Contents/{MacOS,Resources} + cp Info.plist Aliaswallet.app/Contents + cp aliaswallet.icns Aliaswallet.app/Contents/Resources + cp src/aliaswallet Aliaswallet.app/Contents/MacOS/Aliaswallet + echo "APPL????" > Aliaswallet.app/Contents/PkgInfo + @MACDEPLOYQT@ Aliaswallet.app @MACDEPLOYQT_LIBPATH@ + +.PHONY: Aliaswallet.app diff --git a/README b/README deleted file mode 120000 index 42061c01a1..0000000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -README.md \ No newline at end of file diff --git a/README.md b/README.md index 6043f395c1..83c9bbf60a 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,80 @@ -![ShadowCash Logo](https://i.imgur.com/ovemJA3.png) - -[![Slack](https://slack.shadowproject.io/badge.svg)](https://slack.shadowproject.io/) -[![Gitter](https://badges.gitter.im/shadowproject/shadow.svg)](https://gitter.im/shadowproject/shadow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [![Build Status](https://travis-ci.org/shadowproject/shadow.svg?branch=master)](https://travis-ci.org/shadowproject/shadow) [![Code Climate](https://codeclimate.com/github/shadowproject/shadow/badges/gpa.svg)](https://codeclimate.com/github/shadowproject/shadow) [![Test Coverage](https://codeclimate.com/github/shadowproject/shadow/badges/coverage.svg)](https://codeclimate.com/github/shadowproject/shadow/coverage) [![Issue Count](https://codeclimate.com/github/shadowproject/shadow/badges/issue_count.svg)](https://codeclimate.com/github/shadowproject/shadow) - -Introduction -=========================== - -The Shadow Project is a decentralized peer-to-peer platform, created under an open source license, featuring a built-in cryptocurrency, end-to-end encrypted messaging and decentralized marketplace. The decentralized network aims to provide anonymity and privacy for everyone through a simple user-friendly interface by taking care of all the advanced cryptography in the background. - -* [Website](https://shadowproject.io/) -* [Blog](https://blog.shadowproject.io/) -* [Documentation](https://doc.shadowproject.io/) -* [Forum](https://talk.shadowproject.io/) - -"They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety." - -Releases -=========================== -[Click on this link to go to the latest release - 1.4.0.3](https://github.com/shadowproject/shadow/releases/latest) - -Supported Operating Systems: -* Linux (64 bit) -* ~~Linux (32 bit)~~ -* Windows (32 bit) -* Windows (64 bit) -* OSX - - -Linux releases will not work out of the box on the Raspberry Pi, you'll have to compile from source. - -Development process -=========================== - -Developers work in their own trees, then submit pull requests when -they think their feature or bug fix is ready. - -The patch will be accepted if there is broad consensus that it is a -good thing. Developers should expect to rework and resubmit patches -if they don't match the project's coding conventions (see coding.txt) -or are controversial. - -The master branch is regularly built and tested, but is not guaranteed -to be completely stable. Tags are regularly created to indicate new -stable release versions of ShadowCash. - -Feature branches are created when there are major new features being -worked on by several people. - -From time to time a pull request will become outdated. If this occurs, and -the pull is no longer automatically mergeable; a comment on the pull will -be used to issue a warning of closure. The pull will be closed 15 days -after the warning if action is not taken by the author. Pull requests closed -in this manner will have their corresponding issue labeled 'stagnant'. - -Issues with no commits will be given a similar warning, and closed after -15 days from their last activity. Issues closed in this manner will be -labeled 'stale'. - -Building Shadow -=========================== - -See [doc/readme-qt.rst](https://github.com/shadowproject/shadow/blob/master/doc/readme-qt.rst) for instructions on building **ShadowCoin QT** | *the intended-for-end-users, nice-graphical-interface, reference implementation of ShadowCash.* - -See [doc/build-msw.txt](https://github.com/shadowproject/shadow/blob/master/doc/build-msw.txt) for instructions on building **shadowcoind (Windows)** | *the intended-for-services, no-graphical-interface, reference implementation of ShadowCash.* - -See [doc/build-osx.txt](https://github.com/shadowproject/shadow/blob/master/doc/build-osx.txt) for instructions on building **shadowcoind (Mac)** - -See [doc/build-unix.txt](https://github.com/shadowproject/shadow/blob/master/doc/build-unix.txt) for instructions on building **shadowcoind (UNIX)** - - -> For guides and technical documentation please refer to [doc.shadowproject.io (en)](https://shadowproject.io/en/documentation) +# Alias +[![Latest release](https://img.shields.io/github/v/release/aliascash/alias-wallet?label=Release&color=%2300bf00)](https://github.com/aliascash/alias-wallet/releases/latest) +[![Latest develop build](https://img.shields.io/github/v/release/aliascash/alias-wallet?include_prereleases&label=Develop-Build)](https://github.com/aliascash/alias-wallet/releases) +[![Discord](https://img.shields.io/discord/426769724018524161?logo=discord)](https://discord.gg/ckkrb8m) +[![Reddit](https://img.shields.io/badge/reddit-join-orange?logo=reddit)](https://www.reddit.com/r/AliasCash/) +[![Build Status Master](https://github.com/aliascash/alias-wallet/actions/workflows/build-master.yml/badge.svg)](https://github.com/aliascash/alias-wallet/actions) +[![Build Status Develop](https://github.com/aliascash/alias-wallet/actions/workflows/build-develop.yml/badge.svg)](https://github.com/aliascash/alias-wallet/actions) + +Alias is a Secure Proof-of-Stake (PoSv3) Network with Anonymous Transaction Capability. + +Alias utilizes a range of proven cryptographic techniques to achieve un-linkable, +un-traceable and anonymous transactions on its underlaying blockchain and also protects +the users identity by running all the network nodes as Tor hidden services. + +# Licensing + +- SPDX-FileCopyrightText: © 2025 ALIAS Developers +- SPDX-FileCopyrightText: © 2020 Alias Developers +- SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +- SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +- SPDX-FileCopyrightText: © 2014 BlackCoin Developers +- SPDX-FileCopyrightText: © 2013 NovaCoin Developers +- SPDX-FileCopyrightText: © 2011 PPCoin Developers +- SPDX-FileCopyrightText: © 2009 Bitcoin Developers + +SPDX-License-Identifier: MIT + +# Social +- Visit our website [Alias](https://alias.cash/) (ALIAS) +- Please join us on our [Discord](https://discord.gg/ckkrb8m) server +- Read the latest [News](https://alias.cash/news/) +- Visit our thread at [BitcoinTalk](https://bitcointalk.org/index.php?topic=2103301.0) + +## Key Privacy Technology + +Anonymous token creation: Through the use of dual key stealth technology, Alias provides +the ability to generate ‘private coins’ by consuming 'public coins'. Private coins can then be +sent through an implementation of ring signatures based on the Cryptonote protocol +to eliminate any transaction history. The wallet offers the opportunity to transfer your +balance between public coins and private coins. We are currently working +on improving this technology for better functionality and privacy. + +Built in Tor: The Alias software offers a full integration of [Tor](https://www.torproject.org/) +so that the Alias client runs exclusively as a Tor hidden service using a .onion +address to connect to other clients in the network. Your real IP address is +therefore protected at all times. + +## Basic Coin Specs V3/V4 + + + + + + + + + + + + +
AlgoPoSv3/PoAS
Block Time96 Seconds
Difficulty RetargetingEvery Block (Moving average of last 24 hours)
Initial Coin Supply20,000,000 ALIAS
Funding Coin Supply3,000,000 ALIAS
Max Coin Supply (PoS Phase)3 private or 2 public coins reward per block, depending on what you're staking
Min Stake Maturity450 blocks (~12 hours)
Min ALIAS Confirmations10 blocks
Base Fee0.0001 ALIAS
Max Anon Output1000
Ring Sizefix 10
+ +## Further documentation + +For detailed description and further documentation have a look at our [Wiki](https://github.com/aliascash/documentation/wiki). + + Like to build from source? Go straight to these pages there: +* Build on and for [Windows](https://github.com/aliascash/documentation/wiki/Build-Windows) +* Build on and for [Mac](https://github.com/aliascash/documentation/wiki/Build-Mac) +* Separate pages for different flavours of Linux are also available there + +#### UI development + +The following files where maintained on the separate Git repository +[alias-wallet-ui](https://github.com/aliascash/alias-wallet-ui): +* src/qt/res/assets/* +* src/qt/res/index.html +* spectre.qrc + +**Do not modify them here!** diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 0000000000..e27da5e276 --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,174 @@ +## Alias V4 + +> By downloading and using this software, you agree that 1/6 of the staking +> rewards are contributed to a development fund. The development fund aims +> to support the long term development and value of Alias. The fund is managed +> by the Alias core team. + +This is a major release and a **MANDATORY** update to the Alias software! +This update involves consensus changes (_details below_) and **you MUST +update** your wallet software before: + +2019-09-27 (_27th September 2019_) @ 2000 hours (GMT) + +If you do not update your wallet software you will no longer be able to connect +to the Alias network and you will no longer be able to conduct transactions on +the network and you will no longer be able to deposit or withdraw your funds +(public a/o private ALIAS) from the exchanges. + +### Development Contribution Blocks (DCB) +After 21/08/2018 @ 2200 hours (GMT) one in six (1 in 6) block rewards will be +a designated DCB and will be sent to the Alias team development fund wallet. +This fund will ensure a future for Alias and will enable us to pay for certain +services, to hire contractors and to pay Alias core team members in ALIAS +to enable them to work full time on the project. The further development +depend on a source of steady funding. We believe this will give us the opportunity +to produce better software and will create value for investors. We currently +have some very skilled developers working for us and we want to keep it that way. + +### Replay Protection +We have implemented a check for DCBs and we have implemented a replay protection +mechanism. This means that after 17/05/2019 @ 2000 hours (GMT) any wallets not +updated will not be able to create transactions on the Alias V3 network. + +### Licensing + +- SPDX-FileCopyrightText: © 2025 ALIAS Developers +- SPDX-FileCopyrightText: © 2020 Alias Developers +- SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +- SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +- SPDX-FileCopyrightText: © 2014 BlackCoin Developers +- SPDX-FileCopyrightText: © 2013 NovaCoin Developers +- SPDX-FileCopyrightText: © 2011 PPCoin Developers +- SPDX-FileCopyrightText: © 2009 Bitcoin Developers + +SPDX-License-Identifier: MIT + +### Changelog +## 4.4.0 (released 2021-08-25) +- [#14](https://github.com/aliascash/alias-wallet-archive/issues/14) Localization of main wallet +- Localization of Windows installer and Shell-UI +- [#280](https://github.com/aliascash/alias-wallet-archive/issues/280) Fixed cmdline option `-help` (`-h`) +- Update of Fedora build to Fedora 33 +- Update of minimal Mac version to 10.14 (Mojave) +- Update used Boost version to 1.75.0 +- Replaced old Tor v2 seednode addresses with new v3 addresses. For details see [v2 deprecation timeline](https://blog.torproject.org/v2-deprecation-timeline). +- [#3](https://github.com/aliascash/alias-wallet/issues/3) 32Bit Windows (x86) version available now +- [#27](https://github.com/aliascash/alias-wallet/issues/27) Fixed thread safety issue which leads to wallet crash during heavy load on the RPC interface. Thx @Gandalf for the finding! + +## 4.3.1 (released 2020-12-08) +- Update to Qt 5.12.10 (Mac) +- [#227](https://github.com/aliascash/alias-wallet-archive/issues/227) On startup, always require password if wallet is encrypted. +- SetupWalletWizard + - Encryption of wallet.dat is now part of the wizard and mandatory. + - [#248](https://github.com/aliascash/alias-wallet-archive/issues/248) Added password verification field next to password. +- RPC method `listsinceblock`: add attribute `vout` for public outputs +- UI changes: + - Increase icon size of buttons in send page. + - Default select first address in addressbook and receive addresses. + (Fixes invalid QR code.) + - Fix: make sure address is selected when clicking in detail row. + (Ensure right address is picked for QR code.) + - Fix: address lookup in addressbook on address paste. +- Refactored the whole build to CMake as basement. + - For all supported operating systems, there are corresponding helper + scripts on `scripts/cmake-build*`. + - All Linux binaries now have Tor and Qt as the only dependencies. All + other components are compiled right into the binaries. +- Added build for OpenSUSE Tumbleweed +- Switched to ARMv8 on Raspberry Pi binaries. That means Raspberry Pi is + migrated from 32Bit to 64Bit, which also means a complete new setup of + the Raspberry Pi is required. + +## 4.3.0 (released 2020-10-01) +- Update to Qt 5.12.9 (Windows / Mac) +- Streamlined licensing headers a.s.o. to make the whole project compliant to [REUSE Software](https://reuse.software/) +- Refactored overall namings according to project rebranding +- Refactored naming of some RPC methods according to project rebranding: + - `sendspectoanon` > `sendpublictoprivate` + - `sendanontoanon` > `sendprivate` + - `sendanontospec` > `sendprivatetopublic` + - `estimateanonfee` > `estimateprivatefee` +- Renamed some fields on RPC results: + - `anonbalance` > `balance_private` + - `spectrestake` > `stake_private` + - `spectrestakeweight` > `stakeweight_private` + - `unconfirmedanonbalance` > `unconfirmedbalance_private` + - `spectrestakeweight` > `stakeweight_private` + - `anonsupply` > `moneysupply_private` +- Added new fields to RPC results: + - `balance_public` + - `stake_public` + - `stakeweight_public` + - `unconfirmedbalance_public` + - `stakeweight_public` + - `moneysupply_public` +- Complete UI revision based on new style and with many UX improvements +- Fix: private transaction did cost twice as much fee as effectivly required and shown in confirmation dialog +- Updated Fedora build to Fedora 32 +- Added build for Ubuntu 20.04 +- Wipe out build for Ubuntu 19.x as it's EOL + +## 4.2.0 (released 2020-05-02) +- Update to Qt 5.12.8 +- Replace QtWebEngine with QtWebView to support mobile platforms. +- Open 'Unlock Wallet' Dialog on incoming anon staking reward with unknown sender. +- Allow to select parts of the transaction detail dialog text. +- Improve staking indicator tooltip: + - 'Not staking, staking is disabled' was never shown. + - 'Initializing staking...' is now shown instead 'Not staking because you don't have mature coins' during staker thread initialization +- Improve synchronization tooltip: blockchain synchronization state is now updated every 500ms. (Tooltips in general are now updated when open and underlying data changes) +- Improve splash screen with progress messages to reduce UI freezes during startup. +- [#183](https://github.com/aliascash/alias-wallet-archive/issues/183) Reduce UI freezes during blockchain sync. + +## 4.1.0 (released 2019-10-13) +- [#82](https://github.com/aliascash/alias-wallet-archive/issues/82) Wallet.dat creation with mnemonic seed words (BIP39). + If no `wallet.dat` file was detected during startup, the wallet opens a wizard with these three options: + - Create new `wallet.dat` file based on mnemonic seed words. + - Restore `wallet.dat` from mnemonic seed words. + - Import existing `wallet.dat` file. + + For further details see [here](https://medium.com/coinmonks/mnemonic-generation-bip39-simply-explained-e9ac18db9477). + Duplicated by [#115](https://github.com/aliascash/alias-wallet-archive/issues/115) + +- [#214](https://github.com/aliascash/alias-wallet-archive/issues/214) Migrate Debian/Raspbian build to Buster. + Binaries for both Stretch and Buster will be provided. + +- [#216](https://github.com/aliascash/alias-wallet-archive/issues/216) Tor Hidden Service v3 implementation + minor Tor improvements. + - Implementation of Tor Hidden Service v3. + - Creation of launch argument `-onionv2`, allowing the usage of legacy v2 addresses. + - Creation of an torrc-defaults file on Linux. + - By default, Tor will now use hardware crypto acceleration if available, only connect to Hidden Services, + and will write to disk less frequently, preserving the lifespan of SD cards on Raspbian. + +- [#218](https://github.com/aliascash/alias-wallet-archive/issues/218) Provide binaries for Ubuntu 19.04. + Binaries for both Ubuntu 18.04 and 19.04 will be provided. + +- Updated packaged Tor for MacOS and Windows to 0.4.1.5 + +## 4.0.0 (released 2019-09-08) +**V4 blockchain fork consensus changes / Fork time is GMT: Friday, 27. September 2019 20:00:00 (1569614400 unix epoch time)** +- One-time 3'000'000 XSPEC staking reward for foundation address SSGCEMb6xESgmuGXkx7yozGDxhVSXzBP3a + +## 3.x release notes + +See [ReleaseNotes for Pre-4.x](./ReleaseNotes_Pre4.0.md) + +## 2.x release notes + +See [ReleaseNotes for Pre-3.x](./ReleaseNotes_Pre3.0.md) + +# Checksums +## Verify MacOS +``` +openssl sha -sha256 +``` +## Verify Windows +``` +certUtil -hashfile "" SHA256 +``` +## Verify Linux +``` +sha256sum +``` +## List of sha256 checksums diff --git a/Spectre.pro b/Spectre.pro new file mode 100644 index 0000000000..5f1e7edd5f --- /dev/null +++ b/Spectre.pro @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +TEMPLATE = app +TARGET = spectre +#find . -type d +QT += testlib webenginewidgets webchannel + +TEMPLATE = subdirs + +macx { +SUBDIRS = \ + src \ # sub-project names +} + +win32 { +SUBDIRS = \ + tor \ # sub-project names + leveldb \ # sub-project names + db4.8 \ # sub-project names + src \ # sub-project names + +src.depends = tor leveldb db4.8 +} diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000000..63a2eaa16d --- /dev/null +++ b/autogen.sh @@ -0,0 +1,22 @@ +#!/bin/bash -e +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# =========================================================================== + +ownLocation="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "${ownLocation}" + +echo +echo "Nothing to prepare at this stage." +echo +echo "To build, just run one of the cmake-build* scripts on the scripts folder:" +echo +ls -1 scripts/cmake-build* +echo +echo "Use option -h to see their possibilities" +echo diff --git a/cmake/CMakeLists_db5.x.txt b/cmake/CMakeLists_db5.x.txt new file mode 100644 index 0000000000..21f87ea9e1 --- /dev/null +++ b/cmake/CMakeLists_db5.x.txt @@ -0,0 +1,231 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# CMakeLists_db5.x.txt +# ===================== +# Modern CMake configuration for building Berkeley DB 5.x from source. +# +# This file creates a target-based library build using modern CMake practices: +# - Uses CMAKE_CURRENT_SOURCE_DIR for source-relative paths +# - Uses CMAKE_CURRENT_BINARY_DIR for build-relative paths +# - Uses target-based commands (target_include_directories, target_sources) +# - Creates the db5x target for linking +# +# Usage: Include this file in your CMakeLists.txt to build Berkeley DB 5.x + +############################################################################## +##### Some helper stuff to build BerkeleyDB 5.0.32 ########################### + +# Create dummy file since we want an empty shared library before linking +# Use CMAKE_CURRENT_BINARY_DIR for build directory-specific paths +set(DUMMY_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/dummy.c") +file(WRITE "${DUMMY_SOURCE}" "") + + + +############################################################################## +##### Setup library build #################################################### + +# Create the library target using modern CMake practices +add_library(db5x ${DUMMY_SOURCE}) + +# Set up include directories using generator expressions for proper scoping +target_include_directories(db5x + SYSTEM PUBLIC + $ + $ + ) + +# Note: Compile options commented out - can be enabled if needed +# Using target_compile_options would be more modern than setting CMAKE_C_FLAGS globally +#target_compile_options(db5x PRIVATE +# $<$,$,$>: +# -Wno-error=error-implicit-function-declaration> +# $<$: +# -W4> +# ) +if(Android) + # TODO: Consider using target_compile_options instead of global CMAKE_C_FLAGS + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=error-implicit-function-declaration") +endif() + +target_sources(db5x + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/dbinc/mutex_int.h + + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_compact.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_compare.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_compress.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_conv.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_curadj.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_cursor.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_delete.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_open.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_put.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_rec.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_reclaim.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_recno.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_rsearch.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_search.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_split.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/bt_upgrade.c + ${CMAKE_CURRENT_SOURCE_DIR}/btree/btree_auto.c + ${CMAKE_CURRENT_SOURCE_DIR}/clib/rand.c + ${CMAKE_CURRENT_SOURCE_DIR}/clib/snprintf.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/clock.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/crypto_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_byteorder.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_compint.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_err.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_getlong.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_idspace.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_log2.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/db_shash.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/dbt.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/mkpath.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/os_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/common/zerofill.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/crdel_auto.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/crdel_rec.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_am.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_auto.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_cam.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_cds.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_compact.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_conv.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_dispatch.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_dup.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_iface.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_join.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_meta.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_open.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_overflow.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_pr.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_rec.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_reclaim.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_remove.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_rename.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_ret.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_setid.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_setlsn.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_sort_multiple.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_stati.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_truncate.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_upg.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_upg_opd.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/db_vrfy_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/db/partition.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_alloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_failchk.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_globals.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_name.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_open.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_recover.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_region.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_register.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_sig.c + ${CMAKE_CURRENT_SOURCE_DIR}/env/env_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/fileops/fileops_auto.c + ${CMAKE_CURRENT_SOURCE_DIR}/fileops/fop_basic.c + ${CMAKE_CURRENT_SOURCE_DIR}/fileops/fop_rec.c + ${CMAKE_CURRENT_SOURCE_DIR}/fileops/fop_util.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash/hash_func.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash/hash_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/hmac/hmac.c + ${CMAKE_CURRENT_SOURCE_DIR}/hmac/sha1.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_deadlock.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_failchk.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_id.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_list.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_region.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_timer.c + ${CMAKE_CURRENT_SOURCE_DIR}/lock/lock_util.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_archive.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_compare.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_debug.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_get.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_print.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_put.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/log/log_verify_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_alloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_bh.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_fget.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_fmethod.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_fopen.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_fput.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_fset.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_mvcc.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_region.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_register.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_resize.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_sync.c + ${CMAKE_CURRENT_SOURCE_DIR}/mp/mp_trickle.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_alloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_failchk.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_region.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/mutex/mut_tas.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_abort.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_abs.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_alloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_clock.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_cpu.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_ctime.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_dir.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_errno.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_fid.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_flock.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_fsync.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_getenv.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_handle.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_map.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_mkdir.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_open.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_pid.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_rename.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_root.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_rpath.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_rw.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_seek.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_stack.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_tmpdir.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_truncate.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_uid.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_unlink.c + ${CMAKE_CURRENT_SOURCE_DIR}/os/os_yield.c + ${CMAKE_CURRENT_SOURCE_DIR}/qam/qam_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/rep/rep_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/repmgr/repmgr_stub.c + ${CMAKE_CURRENT_SOURCE_DIR}/sequence/seq_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/sequence/sequence.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_auto.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_chkpt.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_failchk.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_method.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_rec.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_recover.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_region.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_stat.c + ${CMAKE_CURRENT_SOURCE_DIR}/txn/txn_util.c + ) diff --git a/cmake/DownloadFile.cmake b/cmake/DownloadFile.cmake new file mode 100644 index 0000000000..9b658f4603 --- /dev/null +++ b/cmake/DownloadFile.cmake @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# DownloadFile.cmake +# =================== +# Modern CMake function to download a file with hash verification. +# +# Usage: +# download_file( ) +# +# Parameters: +# url - URL of the file to download +# filename - Local path where the file will be saved +# hash_type - Hash algorithm (e.g., SHA256, MD5) +# hash - Expected hash value for verification +# +# The function will skip downloading if the file already exists. +# Uses TLS verification for secure downloads. + +function(download_file url filename hash_type hash) + if(NOT EXISTS "${filename}") + file(DOWNLOAD "${url}" "${filename}" + TIMEOUT 60 # seconds + EXPECTED_HASH ${hash_type}=${hash} + TLS_VERIFY ON) + endif() +endfunction() diff --git a/cmake/FindBerkeleyDB.cmake b/cmake/FindBerkeleyDB.cmake new file mode 100644 index 0000000000..1c569b58af --- /dev/null +++ b/cmake/FindBerkeleyDB.cmake @@ -0,0 +1,202 @@ +# Author: sum01 +# Git: https://github.com/sum01/FindBerkeleyDB +# Read the README.md for the full info. +# +# SPDX-FileCopyrightText: © 2018 +# SPDX-License-Identifier: Unlicense +# +# FindBerkeleyDB.cmake +# ==================== +# Modern CMake find module for Berkeley DB library. +# +# This module provides: +# - BerkeleyDB_FOUND: Boolean indicating if Berkeley DB was found +# - BerkeleyDB_INCLUDE_DIRS: Include directories for Berkeley DB +# - BerkeleyDB_LIBRARIES: List of library files +# - BerkeleyDB_VERSION: Version string (e.g., "6.2.32") +# - Oracle::BerkeleyDB: Imported target for modern CMake usage +# +# Usage: +# find_package(BerkeleyDB REQUIRED) +# target_link_libraries(my_target PRIVATE Oracle::BerkeleyDB) +# +# NOTE: If Berkeley DB ever gets a Pkg-config ".pc" file, add pkg_check_modules() here + +# Checks if environment paths are empty, set them if they aren't +if(NOT "$ENV{BERKELEYDB_ROOT}" STREQUAL "") + set(_BERKELEYDB_HINTS "$ENV{BERKELEYDB_ROOT}") +elseif(NOT "$ENV{Berkeleydb_ROOT}" STREQUAL "") + set(_BERKELEYDB_HINTS "$ENV{Berkeleydb_ROOT}") +elseif(NOT "$ENV{BERKELEYDBROOT}" STREQUAL "") + set(_BERKELEYDB_HINTS "$ENV{BERKELEYDBROOT}") +else() + # Set just in case, as it's used regardless if it's empty or not + set(_BERKELEYDB_HINTS "") +endif() + +if(NOT "$ENV{BerkeleyDB_ROOT_DIR}" STREQUAL "") + set(BerkeleyDB_ROOT_DIR "$ENV{BerkeleyDB_ROOT_DIR}") +endif() + +# Allow user to pass a path instead of guessing +if(BerkeleyDB_ROOT_DIR) + set(_BERKELEYDB_PATHS "${BerkeleyDB_ROOT_DIR}") +elseif(CMAKE_SYSTEM_NAME MATCHES ".*[wW]indows.*") + # MATCHES is used to work on any devies with windows in the name + # Shameless copy-paste from FindOpenSSL.cmake v3.8 + file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles) + list(APPEND _BERKELEYDB_HINTS "${_programfiles}") + + # There's actually production release and version numbers in the file path. + # For example, if they're on v6.2.32: C:/Program Files/Oracle/Berkeley DB 12cR1 6.2.32/ + # But this still works to find it, so I'm guessing it can accept partial path matches. + + foreach(_TARGET_BERKELEYDB_PATH "Oracle/Berkeley DB" "Berkeley DB") + list(APPEND _BERKELEYDB_PATHS + "${_programfiles}/${_TARGET_BERKELEYDB_PATH}" + "C:/Program Files (x86)/${_TARGET_BERKELEYDB_PATH}" + "C:/Program Files/${_TARGET_BERKELEYDB_PATH}" + "C:/${_TARGET_BERKELEYDB_PATH}" + ) + endforeach() +else() + # Paths for anything other than Windows + # Cellar/berkeley-db is for macOS from homebrew installation + list(APPEND _BERKELEYDB_PATHS + "/usr" + "/usr/local" + "/usr/local/Cellar/berkeley-db" + "/opt" + "/opt/local" + ) +endif() + +# Find includes path +find_path(BerkeleyDB_INCLUDE_DIRS + NAMES "db_cxx.h" + HINTS ${_BERKELEYDB_HINTS} + PATH_SUFFIXES "include" "includes" + PATHS ${_BERKELEYDB_PATHS} + ) + +# Checks if the version file exists, save the version file to a var, and fail if there's no version file +if(BerkeleyDB_INCLUDE_DIRS) + # Read the version file db.h into a variable + file(READ "${BerkeleyDB_INCLUDE_DIRS}/db.h" _BERKELEYDB_DB_HEADER) + # Parse the DB version into variables to be used in the lib names + string(REGEX REPLACE ".*DB_VERSION_MAJOR ([0-9]+).*" "\\1" BerkeleyDB_VERSION_MAJOR "${_BERKELEYDB_DB_HEADER}") + string(REGEX REPLACE ".*DB_VERSION_MINOR ([0-9]+).*" "\\1" BerkeleyDB_VERSION_MINOR "${_BERKELEYDB_DB_HEADER}") + # Patch version example on non-crypto installs: x.x.xNC + string(REGEX REPLACE ".*DB_VERSION_PATCH ([0-9]+(NC)?).*" "\\1" BerkeleyDB_VERSION_PATCH "${_BERKELEYDB_DB_HEADER}") +else() + if(BerkeleyDB_FIND_REQUIRED) + # If the find_package(BerkeleyDB REQUIRED) was used, fail since we couldn't find the header + message(FATAL_ERROR "Failed to find Berkeley DB's header file \"db.h\"! Try setting \"BerkeleyDB_ROOT_DIR\" when initiating Cmake.") + elseif(NOT BerkeleyDB_FIND_QUIETLY) + message(WARNING "Failed to find Berkeley DB's header file \"db.h\"! Try setting \"BerkeleyDB_ROOT_DIR\" when initiating Cmake.") + endif() + # Set some garbage values to the versions since we didn't find a file to read + set(BerkeleyDB_VERSION_MAJOR "0") + set(BerkeleyDB_VERSION_MINOR "0") + set(BerkeleyDB_VERSION_PATCH "0") +endif() + +# The actual returned/output version variable (the others can be used if needed) +set(BerkeleyDB_VERSION "${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}.${BerkeleyDB_VERSION_PATCH}") + +# Finds the target library for berkeley db, since they all follow the same naming conventions +macro(_berkeleydb_get_lib _BERKELEYDB_OUTPUT_VARNAME _TARGET_BERKELEYDB_LIB) + # Different systems sometimes have a version in the lib name... + # and some have a dash or underscore before the versions. + # CMake recommends to put unversioned names before versioned names + find_library(${_BERKELEYDB_OUTPUT_VARNAME} + NAMES + "${_TARGET_BERKELEYDB_LIB}" + "lib${_TARGET_BERKELEYDB_LIB}" + "lib${_TARGET_BERKELEYDB_LIB}${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}-${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}_${BerkeleyDB_VERSION_MAJOR}.${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}${BerkeleyDB_VERSION_MAJOR}${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}-${BerkeleyDB_VERSION_MAJOR}${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}_${BerkeleyDB_VERSION_MAJOR}${BerkeleyDB_VERSION_MINOR}" + "lib${_TARGET_BERKELEYDB_LIB}${BerkeleyDB_VERSION_MAJOR}" + "lib${_TARGET_BERKELEYDB_LIB}-${BerkeleyDB_VERSION_MAJOR}" + "lib${_TARGET_BERKELEYDB_LIB}_${BerkeleyDB_VERSION_MAJOR}" + HINTS ${_BERKELEYDB_HINTS} + PATH_SUFFIXES + "lib" + "lib64" + "libs" + "libs64" + PATHS ${_BERKELEYDB_PATHS} + ) + # If the library was found, add it to our list of libraries + if(${_BERKELEYDB_OUTPUT_VARNAME}) + # If found, append to our libraries variable + # The ${{}} is because the first expands to target the real variable, the second expands the variable's contents... + # and the real variable's contents is the path to the lib. Thus, it appends the path of the lib to BerkeleyDB_LIBRARIES. + list(APPEND BerkeleyDB_LIBRARIES "${${_BERKELEYDB_OUTPUT_VARNAME}}") + endif() +endmacro() + +if (WIN32) + set(LIB_EXTENSION "") +else() + set(LIB_EXTENSION ".a") +endif() + +# Find and set the paths of the specific library to the variable +_berkeleydb_get_lib(BerkeleyDB_LIBRARY "db${LIB_EXTENSION}") +# NOTE: Windows doesn't have a db_cxx lib, but instead compiles the cxx code into the "db" lib +_berkeleydb_get_lib(BerkeleyDB_Cxx_LIBRARY "db_cxx${LIB_EXTENSION}") +# NOTE: I don't think Linux/Unix gets an SQL lib +_berkeleydb_get_lib(BerkeleyDB_Sql_LIBRARY "db_sql") +_berkeleydb_get_lib(BerkeleyDB_Stl_LIBRARY "db_stl") + +# Needed for find_package_handle_standard_args() +include(FindPackageHandleStandardArgs) +# Fails if required vars aren't found, or if the version doesn't meet specifications. +find_package_handle_standard_args(BerkeleyDB + FOUND_VAR BerkeleyDB_FOUND + REQUIRED_VARS + BerkeleyDB_INCLUDE_DIRS + BerkeleyDB_LIBRARY + BerkeleyDB_LIBRARIES + VERSION_VAR BerkeleyDB_VERSION + ) + +# Only show the variables in the GUI if they click "advanced". +# Does nothing when using the CLI +mark_as_advanced(FORCE + BerkeleyDB_FOUND + BerkeleyDB_INCLUDE_DIRS + BerkeleyDB_LIBRARIES + BerkeleyDB_VERSION + BerkeleyDB_VERSION_MAJOR + BerkeleyDB_VERSION_MINOR + BerkeleyDB_VERSION_PATCH + BerkeleyDB_LIBRARY + BerkeleyDB_Cxx_LIBRARY + BerkeleyDB_Stl_LIBRARY + BerkeleyDB_Sql_LIBRARY + ) + +# Create an imported target for easy linking by external projects +# This follows modern CMake practices by providing a target-based interface +if(BerkeleyDB_FOUND AND BerkeleyDB_LIBRARIES) + if(NOT TARGET Oracle::BerkeleyDB) + add_library(Oracle::BerkeleyDB UNKNOWN IMPORTED) + set_target_properties(Oracle::BerkeleyDB PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${BerkeleyDB_INCLUDE_DIRS}" + IMPORTED_LOCATION "${BerkeleyDB_LIBRARY}" + INTERFACE_LINK_LIBRARIES "${BerkeleyDB_LIBRARIES}" + ) + endif() +endif() + +include(FindPackageMessage) +# A message that tells the user what includes/libs were found, and obeys the QUIET command. +find_package_message(BerkeleyDB + "Found BerkeleyDB libraries: ${BerkeleyDB_LIBRARIES}" + "[${BerkeleyDB_LIBRARIES}[${BerkeleyDB_INCLUDE_DIRS}]]" + ) diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 0000000000..505c263b3b --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,181 @@ +# SPDX-FileCopyrightText: © 2009 Iowa State University +# +# SPDX-License-Identifier: BSL-1.0 +# +# GetGitRevisionDescription.cmake +# ================================ +# Modern CMake module for extracting Git revision information. +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# Functions provided: +# get_git_head_revision( ) +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Note: This module uses CMAKE_CURRENT_SOURCE_DIR to work correctly when +# included from subdirectories, following modern CMake practices. +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +# Get the Git head revision information +# Uses CMAKE_CURRENT_SOURCE_DIR to work correctly from any subdirectory +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +# Get Git describe output for the current HEAD +# Uses CMAKE_CURRENT_SOURCE_DIR to ensure correct working directory +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +# Get exact Git tag if HEAD points to a tag +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +# Check if there are local uncommitted changes +# Uses CMAKE_CURRENT_SOURCE_DIR to check the correct directory +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + diff-index --quiet HEAD -- + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} "CLEAN" PARENT_SCOPE) + else() + set(${_var} "DIRTY" PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 0000000000..76c2b5926f --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: © 2009 Iowa State University +# +# SPDX-License-Identifier: BSL-1.0 +# +# GetGitRevisionDescription.cmake.in +# =================================== +# Internal template file for GetGitRevisionDescription.cmake +# This file is configured at CMake time to extract Git revision information. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000000..ffe7c7a105 --- /dev/null +++ b/configure.ac @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +AC_INIT([aliaswalletd], [1.4.1]) +AC_CONFIG_SRCDIR([src/main.cpp]) +AC_CONFIG_AUX_DIR([.]) +AM_INIT_AUTOMAKE([foreign 1.13 subdir-objects -Wall -Werror -Wno-portability]) +AC_CONFIG_MACRO_DIRS([m4]) +AM_PROG_AS +AM_PROG_AR +AC_PROG_MKDIR_P +AC_PROG_CC +AC_PROG_CXX +AC_PROG_OBJCXX +AC_PROG_LIBTOOL +AC_CANONICAL_HOST +build_linux=no +build_windows=no +build_mac=no +case "${host_os}" in + linux*) + build_linux=yes + ;; + cygwin*|mingw*) + build_windows=yes + ;; + darwin*) + build_mac=yes + ;; + *) + AC_MSG_ERROR(["OS $host_os is not supported"]) + ;; +esac +AM_CONDITIONAL([OS_LINUX], [test "$build_linux" = "yes"]) +AM_CONDITIONAL([OS_WINDOWS_CROSSCOMPILE], [test "$build_windows" = "yes"]) +AM_CONDITIONAL([OS_MACOS], [test "$build_mac" = "yes"]) +AX_CXX_COMPILE_STDCXX(17, noext, mandatory) +AC_CONFIG_FILES([Makefile src/Makefile]) +PKG_PROG_PKG_CONFIG +PKG_CHECK_MODULES(OPENSSL, [openssl >= 1.1], [], [AC_MSG_ERROR([OpenSSL 1.1 not found])]) +PKG_CHECK_MODULES(LIBEVENT, [libevent], [], [AC_MSG_ERROR([libevent not found])]) +#AX_SUBDIRS_CONFIGURE([tor], [[--disable-unittests], [--disable-system-torrc], [--disable-systemd], [--disable-asciidoc], [--with-openssl-dir=$($PKG_CONFIG --variable=libdir openssl)], [CFLAGS=$($PKG_CONFIG --cflags openssl) -O2]]) +if test "x$build_windows" = "xyes" ; then + AX_SUBDIRS_CONFIGURE([db4.8/build_unix], [[--disable-cryptography], [--disable-partition], [--disable-compression], [--disable-replication], [--enable-cxx], [--enable-static], [--disable-shared], [--enable-mingw], [CFLAGS=-fPIC -fstack-protector -O2 -D_FORTIFY_SOURCE=1], [CPPFLAGS=-fPIC -fstack-protector -O2 -D_FORTIFY_SOURCE=1]]) +else + AX_SUBDIRS_CONFIGURE([db4.8/build_unix], [[--disable-cryptography], [--disable-partition], [--disable-compression], [--disable-replication], [--enable-cxx], [--enable-static], [--disable-shared], [CFLAGS=-fPIC -fstack-protector -O2 -D_FORTIFY_SOURCE=1], [CPPFLAGS=-fPIC -fstack-protector -O2 -D_FORTIFY_SOURCE=1]]) +fi +PKG_CHECK_MODULES(ZLIB, [zlib], [], [AC_MSG_ERROR([zlib not found])]) +PKG_CHECK_MODULES(ZSTD, [libzstd], [], [AC_MSG_NOTICE([libzstd not found])]) +PKG_CHECK_MODULES(LZMA, [liblzma], [], [AC_MSG_NOTICE([liblzma not found])]) +AC_CHECK_LIB([snappy], [main], , [AC_MSG_NOTICE([snappy not found])]) +AC_CHECK_LIB([pthread], [pthread_self], , [AC_MSG_ERROR([libpthread not found])]) +AC_LANG_CPLUSPLUS +# TODO investigate whether earlier Boost versions will still work. +BOOST_REQUIRE([1.62]) +BOOST_SYSTEM([mt]) +BOOST_CHRONO([mt]) +BOOST_FILESYSTEM([mt]) +BOOST_PROGRAM_OPTIONS([mt]) +BOOST_THREAD([mt]) +BOOST_ASIO +BOOST_DATE_TIME([mt]) +BOOST_IOSTREAMS([mt]) +MACOS_RPATH="" +AC_ARG_ENABLE([gui], [AS_HELP_STRING([--enable-gui], [Build the Qt GUI wallet])]) +if test "x$enable_gui" = "xyes" ; then + AC_ARG_WITH([qt5], [AS_HELP_STRING([--with-qt5], [Manually specify the path to a stand-alone Qt5 installation (pkg-config will be used if not set). This has no effect if --enable-gui is not also specified.])], [ + if test "x$build_mac" = "xyes" ; then + QT5_LIBDIR="$with_qt5/lib" + MACOS_RPATH="-Wl,-rpath,$QT5_LIBDIR" + QT5_LDFLAGS="-F$QT5_LIBDIR" + QT5_CFLAGS="$QT5_LDFLAGS -I$QT5_LIBDIR/QtCore.framework/Headers -I$QT5_LIBDIR/QtGui.framework/Headers -I$QT5_LIBDIR/QtWidgets.framework/Headers -I$QT5_LIBDIR/QtNetwork.framework/Headers -I$QT5_LIBDIR/QtWebChannel.framework/Headers -I$QT5_LIBDIR/QtQuick.framework/Headers -I$QT5_LIBDIR/QtQuickWidgets.framework/Headers -I$QT5_LIBDIR/QtWebView.framework/Headers -I$QT5_LIBDIR/QtWebSockets.framework/Headers -I$QT5_LIBDIR/QtSvg.framework/Headers" + QT5_LIBS="-framework QtCore -framework QtGui -framework QtWidgets -framework QtNetwork -framework QtWebChannel -framework QtQuick -framework QtQuickWidgets -framework QtWebView -framework QtWebSockets -framework QtSvg" + + MACDEPLOYQT="$with_qt5/bin/macdeployqt" + AC_SUBST([MACDEPLOYQT]) + else + QT5_CFLAGS="-I$with_qt5 -I$with_qt5/QtGui -I$with_qt5/QtWidgets -I$with_qt5/QtCore -I$with_qt5/QtWebChannel -I$with_qt5/QtNetwork -I$with_qt5/QtQuick -I$with_qt5/QtQuickWidgets -I$with_qt5/QtWebView -I$with_qt5/QtWebSockets -I$with_qt5/QtSvg" + QT5_LDFLAGS="-L$with_qt5/lib" + QT5_LIBS="-lQt5Core -lQt5Gui -lQt5Widgets -lQt5Network -lQt5WebChannel -lQt5Quick -lQt5QuickWidgets -lQt5WebView -lQt5WebSockets -lQt5Svg" + fi + AC_SUBST([QT5_CFLAGS]) + AC_SUBST([QT5_LDFLAGS]) + AC_SUBST([QT5_LIBS]) + MOC="${with_qt5//\/include\//\/lib\//}/bin/moc" + UIC="${with_qt5//\/include\//\/lib\//}/bin/uic" + RCC="${with_qt5//\/include\//\/lib\//}/bin/rcc" + LRELEASE="${with_qt5//\/include\//\/lib\//}/bin/lrelease" + AC_SUBST([MOC]) + AC_SUBST([UIC]) + AC_SUBST([RCC]) + AC_SUBST([LRELEASE]) + AC_MSG_NOTICE([Using Qt5 at $with_qt5]) + ], [ + PKG_CHECK_MODULES(QT5, [Qt5Core Qt5Gui Qt5Widgets Qt5Network Qt5WebChannel Qt5Quick Qt5QuickWidgets Qt5WebView Qt5WebSockets Qt5Svg], [AC_MSG_NOTICE([Found Qt5 using pkg-config.])], [ + PKG_CHECK_MODULES(QT5, [QtCore >= 5 QtGui >= 5 QtWidgets >= 5 QtNetwork >= 5 QtWebChannel >= 5 QtQuick >= 5 QtQuickWidgets >= 5 QtWebView >= 5 QtWebSockets >= 5 QtSvg >= 5], [AC_MSG_NOTICE([Found Qt >= 5 using pkg-config.])], [ + AC_MSG_ERROR([Qt5 not found.]) + ]) + ]) + ]) + MACDEPLOYQT_LIBPATH="" + AC_SUBST([MACDEPLOYQT_LIBPATH]) + notbeginswith() { case $2 in "$1"*) true;; *) false;; esac; } + if test "x$MOC" = "x" ; then + AC_CHECK_TOOLS(MOC, [moc-qt5 moc]) + fi + if notbeginswith "$($MOC -v)" "$MOC 5." ; then + AC_MSG_ERROR([Cannot find Qt5 tool "moc" - please install the Qt5 development tools.]) + fi + if test "x$UIC" = "x" ; then + AC_CHECK_TOOLS(UIC, [uic-qt5 uic]) + fi + if notbeginswith "$($UIC -v)" "$UIC 5." ; then + AC_MSG_ERROR([Cannot find Qt5 tool "uic" - please install the Qt5 development tools.]) + fi + if test "x$RCC" = "x" ; then + AC_CHECK_TOOLS(RCC, [rcc-qt5 rcc]) + fi + if notbeginswith "$($RCC -v)" "$RCC 5." ; then + AC_MSG_ERROR([Cannot find Qt5 tool "rcc" - please install the Qt5 development tools.]) + fi + if test "x$LRELEASE" = "x" ; then + AC_CHECK_TOOLS(LRELEASE, [lrelease-qt5 lrelease]) + fi + if notbeginswith "$($LRELEASE -version)" "lrelease version 5." ; then + AC_MSG_ERROR([Cannot find Qt5 tool "lrelease" - please install the Qt5 translation tools.]) + fi + if test "x$build_mac" = "xyes" ; then + if test "x$MACDEPLOYQT" = "x" ; then + AC_CHECK_TOOLS(MACDEPLOYQT, [macdeployqt-qt5 macdeployqt]) + fi + fi +fi +CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO" +AC_SUBST([MACOS_RPATH]) +AM_CONDITIONAL([ENABLE_GUI], [test "$enable_gui" = "yes"]) +AC_OUTPUT diff --git a/contrib/bip39/chinese_simplified.txt b/contrib/bip39/chinese_simplified.txt deleted file mode 100644 index b90f1ed85b..0000000000 --- a/contrib/bip39/chinese_simplified.txt +++ /dev/null @@ -1,2048 +0,0 @@ -的 -一 -是 -在 -不 -了 -有 -和 -人 -这 -中 -大 -为 -上 -个 -国 -我 -以 -要 -他 -时 -来 -用 -们 -生 -到 -作 -地 -于 -出 -就 -分 -对 -成 -会 -可 -主 -发 -年 -动 -同 -工 -也 -能 -下 -过 -子 -说 -产 -种 -面 -而 -方 -后 -多 -定 -行 -学 -法 -所 -民 -得 -经 -十 -三 -之 -进 -着 -等 -部 -度 -家 -电 -力 -里 -如 -水 -化 -高 -自 -二 -理 -起 -小 -物 -现 -实 -加 -量 -都 -两 -体 -制 -机 -当 -使 -点 -从 -业 -本 -去 -把 -性 -好 -应 -开 -它 -合 -还 -因 -由 -其 -些 -然 -前 -外 -天 -政 -四 -日 -那 -社 -义 -事 -平 -形 -相 -全 -表 -间 -样 -与 -关 -各 -重 -新 -线 -内 -数 -正 -心 -反 -你 -明 -看 -原 -又 -么 -利 -比 -或 -但 -质 -气 -第 -向 -道 -命 -此 -变 -条 -只 -没 -结 -解 -问 -意 -建 -月 -公 -无 -系 -军 -很 -情 -者 -最 -立 -代 -想 -已 -通 -并 -提 -直 -题 -党 -程 -展 -五 -果 -料 -象 -员 -革 -位 -入 -常 -文 -总 -次 -品 -式 -活 -设 -及 -管 -特 -件 -长 -求 -老 -头 -基 -资 -边 -流 -路 -级 -少 -图 -山 -统 -接 -知 -较 -将 -组 -见 -计 -别 -她 -手 -角 -期 -根 -论 -运 -农 -指 -几 -九 -区 -强 -放 -决 -西 -被 -干 -做 -必 -战 -先 -回 -则 -任 -取 -据 -处 -队 -南 -给 -色 -光 -门 -即 -保 -治 -北 -造 -百 -规 -热 -领 -七 -海 -口 -东 -导 -器 -压 -志 -世 -金 -增 -争 -济 -阶 -油 -思 -术 -极 -交 -受 -联 -什 -认 -六 -共 -权 -收 -证 -改 -清 -美 -再 -采 -转 -更 -单 -风 -切 -打 -白 -教 -速 -花 -带 -安 -场 -身 -车 -例 -真 -务 -具 -万 -每 -目 -至 -达 -走 -积 -示 -议 -声 -报 -斗 -完 -类 -八 -离 -华 -名 -确 -才 -科 -张 -信 -马 -节 -话 -米 -整 -空 -元 -况 -今 -集 -温 -传 -土 -许 -步 -群 -广 -石 -记 -需 -段 -研 -界 -拉 -林 -律 -叫 -且 -究 -观 -越 -织 -装 -影 -算 -低 -持 -音 -众 -书 -布 -复 -容 -儿 -须 -际 -商 -非 -验 -连 -断 -深 -难 -近 -矿 -千 -周 -委 -素 -技 -备 -半 -办 -青 -省 -列 -习 -响 -约 -支 -般 -史 -感 -劳 -便 -团 -往 -酸 -历 -市 -克 -何 -除 -消 -构 -府 -称 -太 -准 -精 -值 -号 -率 -族 -维 -划 -选 -标 -写 -存 -候 -毛 -亲 -快 -效 -斯 -院 -查 -江 -型 -眼 -王 -按 -格 -养 -易 -置 -派 -层 -片 -始 -却 -专 -状 -育 -厂 -京 -识 -适 -属 -圆 -包 -火 -住 -调 -满 -县 -局 -照 -参 -红 -细 -引 -听 -该 -铁 -价 -严 -首 -底 -液 -官 -德 -随 -病 -苏 -失 -尔 -死 -讲 -配 -女 -黄 -推 -显 -谈 -罪 -神 -艺 -呢 -席 -含 -企 -望 -密 -批 -营 -项 -防 -举 -球 -英 -氧 -势 -告 -李 -台 -落 -木 -帮 -轮 -破 -亚 -师 -围 -注 -远 -字 -材 -排 -供 -河 -态 -封 -另 -施 -减 -树 -溶 -怎 -止 -案 -言 -士 -均 -武 -固 -叶 -鱼 -波 -视 -仅 -费 -紧 -爱 -左 -章 -早 -朝 -害 -续 -轻 -服 -试 -食 -充 -兵 -源 -判 -护 -司 -足 -某 -练 -差 -致 -板 -田 -降 -黑 -犯 -负 -击 -范 -继 -兴 -似 -余 -坚 -曲 -输 -修 -故 -城 -夫 -够 -送 -笔 -船 -占 -右 -财 -吃 -富 -春 -职 -觉 -汉 -画 -功 -巴 -跟 -虽 -杂 -飞 -检 -吸 -助 -升 -阳 -互 -初 -创 -抗 -考 -投 -坏 -策 -古 -径 -换 -未 -跑 -留 -钢 -曾 -端 -责 -站 -简 -述 -钱 -副 -尽 -帝 -射 -草 -冲 -承 -独 -令 -限 -阿 -宣 -环 -双 -请 -超 -微 -让 -控 -州 -良 -轴 -找 -否 -纪 -益 -依 -优 -顶 -础 -载 -倒 -房 -突 -坐 -粉 -敌 -略 -客 -袁 -冷 -胜 -绝 -析 -块 -剂 -测 -丝 -协 -诉 -念 -陈 -仍 -罗 -盐 -友 -洋 -错 -苦 -夜 -刑 -移 -频 -逐 -靠 -混 -母 -短 -皮 -终 -聚 -汽 -村 -云 -哪 -既 -距 -卫 -停 -烈 -央 -察 -烧 -迅 -境 -若 -印 -洲 -刻 -括 -激 -孔 -搞 -甚 -室 -待 -核 -校 -散 -侵 -吧 -甲 -游 -久 -菜 -味 -旧 -模 -湖 -货 -损 -预 -阻 -毫 -普 -稳 -乙 -妈 -植 -息 -扩 -银 -语 -挥 -酒 -守 -拿 -序 -纸 -医 -缺 -雨 -吗 -针 -刘 -啊 -急 -唱 -误 -训 -愿 -审 -附 -获 -茶 -鲜 -粮 -斤 -孩 -脱 -硫 -肥 -善 -龙 -演 -父 -渐 -血 -欢 -械 -掌 -歌 -沙 -刚 -攻 -谓 -盾 -讨 -晚 -粒 -乱 -燃 -矛 -乎 -杀 -药 -宁 -鲁 -贵 -钟 -煤 -读 -班 -伯 -香 -介 -迫 -句 -丰 -培 -握 -兰 -担 -弦 -蛋 -沉 -假 -穿 -执 -答 -乐 -谁 -顺 -烟 -缩 -征 -脸 -喜 -松 -脚 -困 -异 -免 -背 -星 -福 -买 -染 -井 -概 -慢 -怕 -磁 -倍 -祖 -皇 -促 -静 -补 -评 -翻 -肉 -践 -尼 -衣 -宽 -扬 -棉 -希 -伤 -操 -垂 -秋 -宜 -氢 -套 -督 -振 -架 -亮 -末 -宪 -庆 -编 -牛 -触 -映 -雷 -销 -诗 -座 -居 -抓 -裂 -胞 -呼 -娘 -景 -威 -绿 -晶 -厚 -盟 -衡 -鸡 -孙 -延 -危 -胶 -屋 -乡 -临 -陆 -顾 -掉 -呀 -灯 -岁 -措 -束 -耐 -剧 -玉 -赵 -跳 -哥 -季 -课 -凯 -胡 -额 -款 -绍 -卷 -齐 -伟 -蒸 -殖 -永 -宗 -苗 -川 -炉 -岩 -弱 -零 -杨 -奏 -沿 -露 -杆 -探 -滑 -镇 -饭 -浓 -航 -怀 -赶 -库 -夺 -伊 -灵 -税 -途 -灭 -赛 -归 -召 -鼓 -播 -盘 -裁 -险 -康 -唯 -录 -菌 -纯 -借 -糖 -盖 -横 -符 -私 -努 -堂 -域 -枪 -润 -幅 -哈 -竟 -熟 -虫 -泽 -脑 -壤 -碳 -欧 -遍 -侧 -寨 -敢 -彻 -虑 -斜 -薄 -庭 -纳 -弹 -饲 -伸 -折 -麦 -湿 -暗 -荷 -瓦 -塞 -床 -筑 -恶 -户 -访 -塔 -奇 -透 -梁 -刀 -旋 -迹 -卡 -氯 -遇 -份 -毒 -泥 -退 -洗 -摆 -灰 -彩 -卖 -耗 -夏 -择 -忙 -铜 -献 -硬 -予 -繁 -圈 -雪 -函 -亦 -抽 -篇 -阵 -阴 -丁 -尺 -追 -堆 -雄 -迎 -泛 -爸 -楼 -避 -谋 -吨 -野 -猪 -旗 -累 -偏 -典 -馆 -索 -秦 -脂 -潮 -爷 -豆 -忽 -托 -惊 -塑 -遗 -愈 -朱 -替 -纤 -粗 -倾 -尚 -痛 -楚 -谢 -奋 -购 -磨 -君 -池 -旁 -碎 -骨 -监 -捕 -弟 -暴 -割 -贯 -殊 -释 -词 -亡 -壁 -顿 -宝 -午 -尘 -闻 -揭 -炮 -残 -冬 -桥 -妇 -警 -综 -招 -吴 -付 -浮 -遭 -徐 -您 -摇 -谷 -赞 -箱 -隔 -订 -男 -吹 -园 -纷 -唐 -败 -宋 -玻 -巨 -耕 -坦 -荣 -闭 -湾 -键 -凡 -驻 -锅 -救 -恩 -剥 -凝 -碱 -齿 -截 -炼 -麻 -纺 -禁 -废 -盛 -版 -缓 -净 -睛 -昌 -婚 -涉 -筒 -嘴 -插 -岸 -朗 -庄 -街 -藏 -姑 -贸 -腐 -奴 -啦 -惯 -乘 -伙 -恢 -匀 -纱 -扎 -辩 -耳 -彪 -臣 -亿 -璃 -抵 -脉 -秀 -萨 -俄 -网 -舞 -店 -喷 -纵 -寸 -汗 -挂 -洪 -贺 -闪 -柬 -爆 -烯 -津 -稻 -墙 -软 -勇 -像 -滚 -厘 -蒙 -芳 -肯 -坡 -柱 -荡 -腿 -仪 -旅 -尾 -轧 -冰 -贡 -登 -黎 -削 -钻 -勒 -逃 -障 -氨 -郭 -峰 -币 -港 -伏 -轨 -亩 -毕 -擦 -莫 -刺 -浪 -秘 -援 -株 -健 -售 -股 -岛 -甘 -泡 -睡 -童 -铸 -汤 -阀 -休 -汇 -舍 -牧 -绕 -炸 -哲 -磷 -绩 -朋 -淡 -尖 -启 -陷 -柴 -呈 -徒 -颜 -泪 -稍 -忘 -泵 -蓝 -拖 -洞 -授 -镜 -辛 -壮 -锋 -贫 -虚 -弯 -摩 -泰 -幼 -廷 -尊 -窗 -纲 -弄 -隶 -疑 -氏 -宫 -姐 -震 -瑞 -怪 -尤 -琴 -循 -描 -膜 -违 -夹 -腰 -缘 -珠 -穷 -森 -枝 -竹 -沟 -催 -绳 -忆 -邦 -剩 -幸 -浆 -栏 -拥 -牙 -贮 -礼 -滤 -钠 -纹 -罢 -拍 -咱 -喊 -袖 -埃 -勤 -罚 -焦 -潜 -伍 -墨 -欲 -缝 -姓 -刊 -饱 -仿 -奖 -铝 -鬼 -丽 -跨 -默 -挖 -链 -扫 -喝 -袋 -炭 -污 -幕 -诸 -弧 -励 -梅 -奶 -洁 -灾 -舟 -鉴 -苯 -讼 -抱 -毁 -懂 -寒 -智 -埔 -寄 -届 -跃 -渡 -挑 -丹 -艰 -贝 -碰 -拔 -爹 -戴 -码 -梦 -芽 -熔 -赤 -渔 -哭 -敬 -颗 -奔 -铅 -仲 -虎 -稀 -妹 -乏 -珍 -申 -桌 -遵 -允 -隆 -螺 -仓 -魏 -锐 -晓 -氮 -兼 -隐 -碍 -赫 -拨 -忠 -肃 -缸 -牵 -抢 -博 -巧 -壳 -兄 -杜 -讯 -诚 -碧 -祥 -柯 -页 -巡 -矩 -悲 -灌 -龄 -伦 -票 -寻 -桂 -铺 -圣 -恐 -恰 -郑 -趣 -抬 -荒 -腾 -贴 -柔 -滴 -猛 -阔 -辆 -妻 -填 -撤 -储 -签 -闹 -扰 -紫 -砂 -递 -戏 -吊 -陶 -伐 -喂 -疗 -瓶 -婆 -抚 -臂 -摸 -忍 -虾 -蜡 -邻 -胸 -巩 -挤 -偶 -弃 -槽 -劲 -乳 -邓 -吉 -仁 -烂 -砖 -租 -乌 -舰 -伴 -瓜 -浅 -丙 -暂 -燥 -橡 -柳 -迷 -暖 -牌 -秧 -胆 -详 -簧 -踏 -瓷 -谱 -呆 -宾 -糊 -洛 -辉 -愤 -竞 -隙 -怒 -粘 -乃 -绪 -肩 -籍 -敏 -涂 -熙 -皆 -侦 -悬 -掘 -享 -纠 -醒 -狂 -锁 -淀 -恨 -牲 -霸 -爬 -赏 -逆 -玩 -陵 -祝 -秒 -浙 -貌 -役 -彼 -悉 -鸭 -趋 -凤 -晨 -畜 -辈 -秩 -卵 -署 -梯 -炎 -滩 -棋 -驱 -筛 -峡 -冒 -啥 -寿 -译 -浸 -泉 -帽 -迟 -硅 -疆 -贷 -漏 -稿 -冠 -嫩 -胁 -芯 -牢 -叛 -蚀 -奥 -鸣 -岭 -羊 -凭 -串 -塘 -绘 -酵 -融 -盆 -锡 -庙 -筹 -冻 -辅 -摄 -袭 -筋 -拒 -僚 -旱 -钾 -鸟 -漆 -沈 -眉 -疏 -添 -棒 -穗 -硝 -韩 -逼 -扭 -侨 -凉 -挺 -碗 -栽 -炒 -杯 -患 -馏 -劝 -豪 -辽 -勃 -鸿 -旦 -吏 -拜 -狗 -埋 -辊 -掩 -饮 -搬 -骂 -辞 -勾 -扣 -估 -蒋 -绒 -雾 -丈 -朵 -姆 -拟 -宇 -辑 -陕 -雕 -偿 -蓄 -崇 -剪 -倡 -厅 -咬 -驶 -薯 -刷 -斥 -番 -赋 -奉 -佛 -浇 -漫 -曼 -扇 -钙 -桃 -扶 -仔 -返 -俗 -亏 -腔 -鞋 -棱 -覆 -框 -悄 -叔 -撞 -骗 -勘 -旺 -沸 -孤 -吐 -孟 -渠 -屈 -疾 -妙 -惜 -仰 -狠 -胀 -谐 -抛 -霉 -桑 -岗 -嘛 -衰 -盗 -渗 -脏 -赖 -涌 -甜 -曹 -阅 -肌 -哩 -厉 -烃 -纬 -毅 -昨 -伪 -症 -煮 -叹 -钉 -搭 -茎 -笼 -酷 -偷 -弓 -锥 -恒 -杰 -坑 -鼻 -翼 -纶 -叙 -狱 -逮 -罐 -络 -棚 -抑 -膨 -蔬 -寺 -骤 -穆 -冶 -枯 -册 -尸 -凸 -绅 -坯 -牺 -焰 -轰 -欣 -晋 -瘦 -御 -锭 -锦 -丧 -旬 -锻 -垄 -搜 -扑 -邀 -亭 -酯 -迈 -舒 -脆 -酶 -闲 -忧 -酚 -顽 -羽 -涨 -卸 -仗 -陪 -辟 -惩 -杭 -姚 -肚 -捉 -飘 -漂 -昆 -欺 -吾 -郎 -烷 -汁 -呵 -饰 -萧 -雅 -邮 -迁 -燕 -撒 -姻 -赴 -宴 -烦 -债 -帐 -斑 -铃 -旨 -醇 -董 -饼 -雏 -姿 -拌 -傅 -腹 -妥 -揉 -贤 -拆 -歪 -葡 -胺 -丢 -浩 -徽 -昂 -垫 -挡 -览 -贪 -慰 -缴 -汪 -慌 -冯 -诺 -姜 -谊 -凶 -劣 -诬 -耀 -昏 -躺 -盈 -骑 -乔 -溪 -丛 -卢 -抹 -闷 -咨 -刮 -驾 -缆 -悟 -摘 -铒 -掷 -颇 -幻 -柄 -惠 -惨 -佳 -仇 -腊 -窝 -涤 -剑 -瞧 -堡 -泼 -葱 -罩 -霍 -捞 -胎 -苍 -滨 -俩 -捅 -湘 -砍 -霞 -邵 -萄 -疯 -淮 -遂 -熊 -粪 -烘 -宿 -档 -戈 -驳 -嫂 -裕 -徙 -箭 -捐 -肠 -撑 -晒 -辨 -殿 -莲 -摊 -搅 -酱 -屏 -疫 -哀 -蔡 -堵 -沫 -皱 -畅 -叠 -阁 -莱 -敲 -辖 -钩 -痕 -坝 -巷 -饿 -祸 -丘 -玄 -溜 -曰 -逻 -彭 -尝 -卿 -妨 -艇 -吞 -韦 -怨 -矮 -歇 diff --git a/contrib/bip39/chinese_traditional.txt b/contrib/bip39/chinese_traditional.txt deleted file mode 100644 index 9b02047921..0000000000 --- a/contrib/bip39/chinese_traditional.txt +++ /dev/null @@ -1,2048 +0,0 @@ -的 -一 -是 -在 -不 -了 -有 -和 -人 -這 -中 -大 -為 -上 -個 -國 -我 -以 -要 -他 -時 -來 -用 -們 -生 -到 -作 -地 -於 -出 -就 -分 -對 -成 -會 -可 -主 -發 -年 -動 -同 -工 -也 -能 -下 -過 -子 -說 -產 -種 -面 -而 -方 -後 -多 -定 -行 -學 -法 -所 -民 -得 -經 -十 -三 -之 -進 -著 -等 -部 -度 -家 -電 -力 -裡 -如 -水 -化 -高 -自 -二 -理 -起 -小 -物 -現 -實 -加 -量 -都 -兩 -體 -制 -機 -當 -使 -點 -從 -業 -本 -去 -把 -性 -好 -應 -開 -它 -合 -還 -因 -由 -其 -些 -然 -前 -外 -天 -政 -四 -日 -那 -社 -義 -事 -平 -形 -相 -全 -表 -間 -樣 -與 -關 -各 -重 -新 -線 -內 -數 -正 -心 -反 -你 -明 -看 -原 -又 -麼 -利 -比 -或 -但 -質 -氣 -第 -向 -道 -命 -此 -變 -條 -只 -沒 -結 -解 -問 -意 -建 -月 -公 -無 -系 -軍 -很 -情 -者 -最 -立 -代 -想 -已 -通 -並 -提 -直 -題 -黨 -程 -展 -五 -果 -料 -象 -員 -革 -位 -入 -常 -文 -總 -次 -品 -式 -活 -設 -及 -管 -特 -件 -長 -求 -老 -頭 -基 -資 -邊 -流 -路 -級 -少 -圖 -山 -統 -接 -知 -較 -將 -組 -見 -計 -別 -她 -手 -角 -期 -根 -論 -運 -農 -指 -幾 -九 -區 -強 -放 -決 -西 -被 -幹 -做 -必 -戰 -先 -回 -則 -任 -取 -據 -處 -隊 -南 -給 -色 -光 -門 -即 -保 -治 -北 -造 -百 -規 -熱 -領 -七 -海 -口 -東 -導 -器 -壓 -志 -世 -金 -增 -爭 -濟 -階 -油 -思 -術 -極 -交 -受 -聯 -什 -認 -六 -共 -權 -收 -證 -改 -清 -美 -再 -採 -轉 -更 -單 -風 -切 -打 -白 -教 -速 -花 -帶 -安 -場 -身 -車 -例 -真 -務 -具 -萬 -每 -目 -至 -達 -走 -積 -示 -議 -聲 -報 -鬥 -完 -類 -八 -離 -華 -名 -確 -才 -科 -張 -信 -馬 -節 -話 -米 -整 -空 -元 -況 -今 -集 -溫 -傳 -土 -許 -步 -群 -廣 -石 -記 -需 -段 -研 -界 -拉 -林 -律 -叫 -且 -究 -觀 -越 -織 -裝 -影 -算 -低 -持 -音 -眾 -書 -布 -复 -容 -兒 -須 -際 -商 -非 -驗 -連 -斷 -深 -難 -近 -礦 -千 -週 -委 -素 -技 -備 -半 -辦 -青 -省 -列 -習 -響 -約 -支 -般 -史 -感 -勞 -便 -團 -往 -酸 -歷 -市 -克 -何 -除 -消 -構 -府 -稱 -太 -準 -精 -值 -號 -率 -族 -維 -劃 -選 -標 -寫 -存 -候 -毛 -親 -快 -效 -斯 -院 -查 -江 -型 -眼 -王 -按 -格 -養 -易 -置 -派 -層 -片 -始 -卻 -專 -狀 -育 -廠 -京 -識 -適 -屬 -圓 -包 -火 -住 -調 -滿 -縣 -局 -照 -參 -紅 -細 -引 -聽 -該 -鐵 -價 -嚴 -首 -底 -液 -官 -德 -隨 -病 -蘇 -失 -爾 -死 -講 -配 -女 -黃 -推 -顯 -談 -罪 -神 -藝 -呢 -席 -含 -企 -望 -密 -批 -營 -項 -防 -舉 -球 -英 -氧 -勢 -告 -李 -台 -落 -木 -幫 -輪 -破 -亞 -師 -圍 -注 -遠 -字 -材 -排 -供 -河 -態 -封 -另 -施 -減 -樹 -溶 -怎 -止 -案 -言 -士 -均 -武 -固 -葉 -魚 -波 -視 -僅 -費 -緊 -愛 -左 -章 -早 -朝 -害 -續 -輕 -服 -試 -食 -充 -兵 -源 -判 -護 -司 -足 -某 -練 -差 -致 -板 -田 -降 -黑 -犯 -負 -擊 -范 -繼 -興 -似 -餘 -堅 -曲 -輸 -修 -故 -城 -夫 -夠 -送 -筆 -船 -佔 -右 -財 -吃 -富 -春 -職 -覺 -漢 -畫 -功 -巴 -跟 -雖 -雜 -飛 -檢 -吸 -助 -昇 -陽 -互 -初 -創 -抗 -考 -投 -壞 -策 -古 -徑 -換 -未 -跑 -留 -鋼 -曾 -端 -責 -站 -簡 -述 -錢 -副 -盡 -帝 -射 -草 -衝 -承 -獨 -令 -限 -阿 -宣 -環 -雙 -請 -超 -微 -讓 -控 -州 -良 -軸 -找 -否 -紀 -益 -依 -優 -頂 -礎 -載 -倒 -房 -突 -坐 -粉 -敵 -略 -客 -袁 -冷 -勝 -絕 -析 -塊 -劑 -測 -絲 -協 -訴 -念 -陳 -仍 -羅 -鹽 -友 -洋 -錯 -苦 -夜 -刑 -移 -頻 -逐 -靠 -混 -母 -短 -皮 -終 -聚 -汽 -村 -雲 -哪 -既 -距 -衛 -停 -烈 -央 -察 -燒 -迅 -境 -若 -印 -洲 -刻 -括 -激 -孔 -搞 -甚 -室 -待 -核 -校 -散 -侵 -吧 -甲 -遊 -久 -菜 -味 -舊 -模 -湖 -貨 -損 -預 -阻 -毫 -普 -穩 -乙 -媽 -植 -息 -擴 -銀 -語 -揮 -酒 -守 -拿 -序 -紙 -醫 -缺 -雨 -嗎 -針 -劉 -啊 -急 -唱 -誤 -訓 -願 -審 -附 -獲 -茶 -鮮 -糧 -斤 -孩 -脫 -硫 -肥 -善 -龍 -演 -父 -漸 -血 -歡 -械 -掌 -歌 -沙 -剛 -攻 -謂 -盾 -討 -晚 -粒 -亂 -燃 -矛 -乎 -殺 -藥 -寧 -魯 -貴 -鐘 -煤 -讀 -班 -伯 -香 -介 -迫 -句 -豐 -培 -握 -蘭 -擔 -弦 -蛋 -沉 -假 -穿 -執 -答 -樂 -誰 -順 -煙 -縮 -徵 -臉 -喜 -松 -腳 -困 -異 -免 -背 -星 -福 -買 -染 -井 -概 -慢 -怕 -磁 -倍 -祖 -皇 -促 -靜 -補 -評 -翻 -肉 -踐 -尼 -衣 -寬 -揚 -棉 -希 -傷 -操 -垂 -秋 -宜 -氫 -套 -督 -振 -架 -亮 -末 -憲 -慶 -編 -牛 -觸 -映 -雷 -銷 -詩 -座 -居 -抓 -裂 -胞 -呼 -娘 -景 -威 -綠 -晶 -厚 -盟 -衡 -雞 -孫 -延 -危 -膠 -屋 -鄉 -臨 -陸 -顧 -掉 -呀 -燈 -歲 -措 -束 -耐 -劇 -玉 -趙 -跳 -哥 -季 -課 -凱 -胡 -額 -款 -紹 -卷 -齊 -偉 -蒸 -殖 -永 -宗 -苗 -川 -爐 -岩 -弱 -零 -楊 -奏 -沿 -露 -桿 -探 -滑 -鎮 -飯 -濃 -航 -懷 -趕 -庫 -奪 -伊 -靈 -稅 -途 -滅 -賽 -歸 -召 -鼓 -播 -盤 -裁 -險 -康 -唯 -錄 -菌 -純 -借 -糖 -蓋 -橫 -符 -私 -努 -堂 -域 -槍 -潤 -幅 -哈 -竟 -熟 -蟲 -澤 -腦 -壤 -碳 -歐 -遍 -側 -寨 -敢 -徹 -慮 -斜 -薄 -庭 -納 -彈 -飼 -伸 -折 -麥 -濕 -暗 -荷 -瓦 -塞 -床 -築 -惡 -戶 -訪 -塔 -奇 -透 -梁 -刀 -旋 -跡 -卡 -氯 -遇 -份 -毒 -泥 -退 -洗 -擺 -灰 -彩 -賣 -耗 -夏 -擇 -忙 -銅 -獻 -硬 -予 -繁 -圈 -雪 -函 -亦 -抽 -篇 -陣 -陰 -丁 -尺 -追 -堆 -雄 -迎 -泛 -爸 -樓 -避 -謀 -噸 -野 -豬 -旗 -累 -偏 -典 -館 -索 -秦 -脂 -潮 -爺 -豆 -忽 -托 -驚 -塑 -遺 -愈 -朱 -替 -纖 -粗 -傾 -尚 -痛 -楚 -謝 -奮 -購 -磨 -君 -池 -旁 -碎 -骨 -監 -捕 -弟 -暴 -割 -貫 -殊 -釋 -詞 -亡 -壁 -頓 -寶 -午 -塵 -聞 -揭 -炮 -殘 -冬 -橋 -婦 -警 -綜 -招 -吳 -付 -浮 -遭 -徐 -您 -搖 -谷 -贊 -箱 -隔 -訂 -男 -吹 -園 -紛 -唐 -敗 -宋 -玻 -巨 -耕 -坦 -榮 -閉 -灣 -鍵 -凡 -駐 -鍋 -救 -恩 -剝 -凝 -鹼 -齒 -截 -煉 -麻 -紡 -禁 -廢 -盛 -版 -緩 -淨 -睛 -昌 -婚 -涉 -筒 -嘴 -插 -岸 -朗 -莊 -街 -藏 -姑 -貿 -腐 -奴 -啦 -慣 -乘 -夥 -恢 -勻 -紗 -扎 -辯 -耳 -彪 -臣 -億 -璃 -抵 -脈 -秀 -薩 -俄 -網 -舞 -店 -噴 -縱 -寸 -汗 -掛 -洪 -賀 -閃 -柬 -爆 -烯 -津 -稻 -牆 -軟 -勇 -像 -滾 -厘 -蒙 -芳 -肯 -坡 -柱 -盪 -腿 -儀 -旅 -尾 -軋 -冰 -貢 -登 -黎 -削 -鑽 -勒 -逃 -障 -氨 -郭 -峰 -幣 -港 -伏 -軌 -畝 -畢 -擦 -莫 -刺 -浪 -秘 -援 -株 -健 -售 -股 -島 -甘 -泡 -睡 -童 -鑄 -湯 -閥 -休 -匯 -舍 -牧 -繞 -炸 -哲 -磷 -績 -朋 -淡 -尖 -啟 -陷 -柴 -呈 -徒 -顏 -淚 -稍 -忘 -泵 -藍 -拖 -洞 -授 -鏡 -辛 -壯 -鋒 -貧 -虛 -彎 -摩 -泰 -幼 -廷 -尊 -窗 -綱 -弄 -隸 -疑 -氏 -宮 -姐 -震 -瑞 -怪 -尤 -琴 -循 -描 -膜 -違 -夾 -腰 -緣 -珠 -窮 -森 -枝 -竹 -溝 -催 -繩 -憶 -邦 -剩 -幸 -漿 -欄 -擁 -牙 -貯 -禮 -濾 -鈉 -紋 -罷 -拍 -咱 -喊 -袖 -埃 -勤 -罰 -焦 -潛 -伍 -墨 -欲 -縫 -姓 -刊 -飽 -仿 -獎 -鋁 -鬼 -麗 -跨 -默 -挖 -鏈 -掃 -喝 -袋 -炭 -污 -幕 -諸 -弧 -勵 -梅 -奶 -潔 -災 -舟 -鑑 -苯 -訟 -抱 -毀 -懂 -寒 -智 -埔 -寄 -屆 -躍 -渡 -挑 -丹 -艱 -貝 -碰 -拔 -爹 -戴 -碼 -夢 -芽 -熔 -赤 -漁 -哭 -敬 -顆 -奔 -鉛 -仲 -虎 -稀 -妹 -乏 -珍 -申 -桌 -遵 -允 -隆 -螺 -倉 -魏 -銳 -曉 -氮 -兼 -隱 -礙 -赫 -撥 -忠 -肅 -缸 -牽 -搶 -博 -巧 -殼 -兄 -杜 -訊 -誠 -碧 -祥 -柯 -頁 -巡 -矩 -悲 -灌 -齡 -倫 -票 -尋 -桂 -鋪 -聖 -恐 -恰 -鄭 -趣 -抬 -荒 -騰 -貼 -柔 -滴 -猛 -闊 -輛 -妻 -填 -撤 -儲 -簽 -鬧 -擾 -紫 -砂 -遞 -戲 -吊 -陶 -伐 -餵 -療 -瓶 -婆 -撫 -臂 -摸 -忍 -蝦 -蠟 -鄰 -胸 -鞏 -擠 -偶 -棄 -槽 -勁 -乳 -鄧 -吉 -仁 -爛 -磚 -租 -烏 -艦 -伴 -瓜 -淺 -丙 -暫 -燥 -橡 -柳 -迷 -暖 -牌 -秧 -膽 -詳 -簧 -踏 -瓷 -譜 -呆 -賓 -糊 -洛 -輝 -憤 -競 -隙 -怒 -粘 -乃 -緒 -肩 -籍 -敏 -塗 -熙 -皆 -偵 -懸 -掘 -享 -糾 -醒 -狂 -鎖 -淀 -恨 -牲 -霸 -爬 -賞 -逆 -玩 -陵 -祝 -秒 -浙 -貌 -役 -彼 -悉 -鴨 -趨 -鳳 -晨 -畜 -輩 -秩 -卵 -署 -梯 -炎 -灘 -棋 -驅 -篩 -峽 -冒 -啥 -壽 -譯 -浸 -泉 -帽 -遲 -矽 -疆 -貸 -漏 -稿 -冠 -嫩 -脅 -芯 -牢 -叛 -蝕 -奧 -鳴 -嶺 -羊 -憑 -串 -塘 -繪 -酵 -融 -盆 -錫 -廟 -籌 -凍 -輔 -攝 -襲 -筋 -拒 -僚 -旱 -鉀 -鳥 -漆 -沈 -眉 -疏 -添 -棒 -穗 -硝 -韓 -逼 -扭 -僑 -涼 -挺 -碗 -栽 -炒 -杯 -患 -餾 -勸 -豪 -遼 -勃 -鴻 -旦 -吏 -拜 -狗 -埋 -輥 -掩 -飲 -搬 -罵 -辭 -勾 -扣 -估 -蔣 -絨 -霧 -丈 -朵 -姆 -擬 -宇 -輯 -陝 -雕 -償 -蓄 -崇 -剪 -倡 -廳 -咬 -駛 -薯 -刷 -斥 -番 -賦 -奉 -佛 -澆 -漫 -曼 -扇 -鈣 -桃 -扶 -仔 -返 -俗 -虧 -腔 -鞋 -棱 -覆 -框 -悄 -叔 -撞 -騙 -勘 -旺 -沸 -孤 -吐 -孟 -渠 -屈 -疾 -妙 -惜 -仰 -狠 -脹 -諧 -拋 -黴 -桑 -崗 -嘛 -衰 -盜 -滲 -臟 -賴 -湧 -甜 -曹 -閱 -肌 -哩 -厲 -烴 -緯 -毅 -昨 -偽 -症 -煮 -嘆 -釘 -搭 -莖 -籠 -酷 -偷 -弓 -錐 -恆 -傑 -坑 -鼻 -翼 -綸 -敘 -獄 -逮 -罐 -絡 -棚 -抑 -膨 -蔬 -寺 -驟 -穆 -冶 -枯 -冊 -屍 -凸 -紳 -坯 -犧 -焰 -轟 -欣 -晉 -瘦 -禦 -錠 -錦 -喪 -旬 -鍛 -壟 -搜 -撲 -邀 -亭 -酯 -邁 -舒 -脆 -酶 -閒 -憂 -酚 -頑 -羽 -漲 -卸 -仗 -陪 -闢 -懲 -杭 -姚 -肚 -捉 -飄 -漂 -昆 -欺 -吾 -郎 -烷 -汁 -呵 -飾 -蕭 -雅 -郵 -遷 -燕 -撒 -姻 -赴 -宴 -煩 -債 -帳 -斑 -鈴 -旨 -醇 -董 -餅 -雛 -姿 -拌 -傅 -腹 -妥 -揉 -賢 -拆 -歪 -葡 -胺 -丟 -浩 -徽 -昂 -墊 -擋 -覽 -貪 -慰 -繳 -汪 -慌 -馮 -諾 -姜 -誼 -兇 -劣 -誣 -耀 -昏 -躺 -盈 -騎 -喬 -溪 -叢 -盧 -抹 -悶 -諮 -刮 -駕 -纜 -悟 -摘 -鉺 -擲 -頗 -幻 -柄 -惠 -慘 -佳 -仇 -臘 -窩 -滌 -劍 -瞧 -堡 -潑 -蔥 -罩 -霍 -撈 -胎 -蒼 -濱 -倆 -捅 -湘 -砍 -霞 -邵 -萄 -瘋 -淮 -遂 -熊 -糞 -烘 -宿 -檔 -戈 -駁 -嫂 -裕 -徙 -箭 -捐 -腸 -撐 -曬 -辨 -殿 -蓮 -攤 -攪 -醬 -屏 -疫 -哀 -蔡 -堵 -沫 -皺 -暢 -疊 -閣 -萊 -敲 -轄 -鉤 -痕 -壩 -巷 -餓 -禍 -丘 -玄 -溜 -曰 -邏 -彭 -嘗 -卿 -妨 -艇 -吞 -韋 -怨 -矮 -歇 diff --git a/contrib/bip39/english.txt b/contrib/bip39/english.txt deleted file mode 100644 index 942040ed50..0000000000 --- a/contrib/bip39/english.txt +++ /dev/null @@ -1,2048 +0,0 @@ -abandon -ability -able -about -above -absent -absorb -abstract -absurd -abuse -access -accident -account -accuse -achieve -acid -acoustic -acquire -across -act -action -actor -actress -actual -adapt -add -addict -address -adjust -admit -adult -advance -advice -aerobic -affair -afford -afraid -again -age -agent -agree -ahead -aim -air -airport -aisle -alarm -album -alcohol -alert -alien -all -alley -allow -almost -alone -alpha -already -also -alter -always -amateur -amazing -among -amount -amused -analyst -anchor -ancient -anger -angle -angry -animal -ankle -announce -annual -another -answer -antenna -antique -anxiety -any -apart -apology -appear -apple -approve -april -arch -arctic -area -arena -argue -arm -armed -armor -army -around -arrange -arrest -arrive -arrow -art -artefact -artist -artwork -ask -aspect -assault -asset -assist -assume -asthma -athlete -atom -attack -attend -attitude -attract -auction -audit -august -aunt -author -auto -autumn -average -avocado -avoid -awake -aware -away -awesome -awful -awkward -axis -baby -bachelor -bacon -badge -bag -balance -balcony -ball -bamboo -banana -banner -bar -barely -bargain -barrel -base -basic -basket -battle -beach -bean -beauty -because -become -beef -before -begin -behave -behind -believe -below -belt -bench -benefit -best -betray -better -between -beyond -bicycle -bid -bike -bind -biology -bird -birth -bitter -black -blade -blame -blanket -blast -bleak -bless -blind -blood -blossom -blouse -blue -blur -blush -board -boat -body -boil -bomb -bone -bonus -book -boost -border -boring -borrow -boss -bottom -bounce -box -boy -bracket -brain -brand -brass -brave -bread -breeze -brick -bridge -brief -bright -bring -brisk -broccoli -broken -bronze -broom -brother -brown -brush -bubble -buddy -budget -buffalo -build -bulb -bulk -bullet -bundle -bunker -burden -burger -burst -bus -business -busy -butter -buyer -buzz -cabbage -cabin -cable -cactus -cage -cake -call -calm -camera -camp -can -canal -cancel -candy -cannon -canoe -canvas -canyon -capable -capital -captain -car -carbon -card -cargo -carpet -carry -cart -case -cash -casino -castle -casual -cat -catalog -catch -category -cattle -caught -cause -caution -cave -ceiling -celery -cement -census -century -cereal -certain -chair -chalk -champion -change -chaos -chapter -charge -chase -chat -cheap -check -cheese -chef -cherry -chest -chicken -chief -child -chimney -choice -choose -chronic -chuckle -chunk -churn -cigar -cinnamon -circle -citizen -city -civil -claim -clap -clarify -claw -clay -clean -clerk -clever -click -client -cliff -climb -clinic -clip -clock -clog -close -cloth -cloud -clown -club -clump -cluster -clutch -coach -coast -coconut -code -coffee -coil -coin -collect -color -column -combine -come -comfort -comic -common -company -concert -conduct -confirm -congress -connect -consider -control -convince -cook -cool -copper -copy -coral -core -corn -correct -cost -cotton -couch -country -couple -course -cousin -cover -coyote -crack -cradle -craft -cram -crane -crash -crater -crawl -crazy -cream -credit -creek -crew -cricket -crime -crisp -critic -crop -cross -crouch -crowd -crucial -cruel -cruise -crumble -crunch -crush -cry -crystal -cube -culture -cup -cupboard -curious -current -curtain -curve -cushion -custom -cute -cycle -dad -damage -damp -dance -danger -daring -dash -daughter -dawn -day -deal -debate -debris -decade -december -decide -decline -decorate -decrease -deer -defense -define -defy -degree -delay -deliver -demand -demise -denial -dentist -deny -depart -depend -deposit -depth -deputy -derive -describe -desert -design -desk -despair -destroy -detail -detect -develop -device -devote -diagram -dial -diamond -diary -dice -diesel -diet -differ -digital -dignity -dilemma -dinner -dinosaur -direct -dirt -disagree -discover -disease -dish -dismiss -disorder -display -distance -divert -divide -divorce -dizzy -doctor -document -dog -doll -dolphin -domain -donate -donkey -donor -door -dose -double -dove -draft -dragon -drama -drastic -draw -dream -dress -drift -drill -drink -drip -drive -drop -drum -dry -duck -dumb -dune -during -dust -dutch -duty -dwarf -dynamic -eager -eagle -early -earn -earth -easily -east -easy -echo -ecology -economy -edge -edit -educate -effort -egg -eight -either -elbow -elder -electric -elegant -element -elephant -elevator -elite -else -embark -embody -embrace -emerge -emotion -employ -empower -empty -enable -enact -end -endless -endorse -enemy -energy -enforce -engage -engine -enhance -enjoy -enlist -enough -enrich -enroll -ensure -enter -entire -entry -envelope -episode -equal -equip -era -erase -erode -erosion -error -erupt -escape -essay -essence -estate -eternal -ethics -evidence -evil -evoke -evolve -exact -example -excess -exchange -excite -exclude -excuse -execute -exercise -exhaust -exhibit -exile -exist -exit -exotic -expand -expect -expire -explain -expose -express -extend -extra -eye -eyebrow -fabric -face -faculty -fade -faint -faith -fall -false -fame -family -famous -fan -fancy -fantasy -farm -fashion -fat -fatal -father -fatigue -fault -favorite -feature -february -federal -fee -feed -feel -female -fence -festival -fetch -fever -few -fiber -fiction -field -figure -file -film -filter -final -find -fine -finger -finish -fire -firm -first -fiscal -fish -fit -fitness -fix -flag -flame -flash -flat -flavor -flee -flight -flip -float -flock -floor -flower -fluid -flush -fly -foam -focus -fog -foil -fold -follow -food -foot -force -forest -forget -fork -fortune -forum -forward -fossil -foster -found -fox -fragile -frame -frequent -fresh -friend -fringe -frog -front -frost -frown -frozen -fruit -fuel -fun -funny -furnace -fury -future -gadget -gain -galaxy -gallery -game -gap -garage -garbage -garden -garlic -garment -gas -gasp -gate -gather -gauge -gaze -general -genius -genre -gentle -genuine -gesture -ghost -giant -gift -giggle -ginger -giraffe -girl -give -glad -glance -glare -glass -glide -glimpse -globe -gloom -glory -glove -glow -glue -goat -goddess -gold -good -goose -gorilla -gospel -gossip -govern -gown -grab -grace -grain -grant -grape -grass -gravity -great -green -grid -grief -grit -grocery -group -grow -grunt -guard -guess -guide -guilt -guitar -gun -gym -habit -hair -half -hammer -hamster -hand -happy -harbor -hard -harsh -harvest -hat -have -hawk -hazard -head -health -heart -heavy -hedgehog -height -hello -helmet -help -hen -hero -hidden -high -hill -hint -hip -hire -history -hobby -hockey -hold -hole -holiday -hollow -home -honey -hood -hope -horn -horror -horse -hospital -host -hotel -hour -hover -hub -huge -human -humble -humor -hundred -hungry -hunt -hurdle -hurry -hurt -husband -hybrid -ice -icon -idea -identify -idle -ignore -ill -illegal -illness -image -imitate -immense -immune -impact -impose -improve -impulse -inch -include -income -increase -index -indicate -indoor -industry -infant -inflict -inform -inhale -inherit -initial -inject -injury -inmate -inner -innocent -input -inquiry -insane -insect -inside -inspire -install -intact -interest -into -invest -invite -involve -iron -island -isolate -issue -item -ivory -jacket -jaguar -jar -jazz -jealous -jeans -jelly -jewel -job -join -joke -journey -joy -judge -juice -jump -jungle -junior -junk -just -kangaroo -keen -keep -ketchup -key -kick -kid -kidney -kind -kingdom -kiss -kit -kitchen -kite -kitten -kiwi -knee -knife -knock -know -lab -label -labor -ladder -lady -lake -lamp -language -laptop -large -later -latin -laugh -laundry -lava -law -lawn -lawsuit -layer -lazy -leader -leaf -learn -leave -lecture -left -leg -legal -legend -leisure -lemon -lend -length -lens -leopard -lesson -letter -level -liar -liberty -library -license -life -lift -light -like -limb -limit -link -lion -liquid -list -little -live -lizard -load -loan -lobster -local -lock -logic -lonely -long -loop -lottery -loud -lounge -love -loyal -lucky -luggage -lumber -lunar -lunch -luxury -lyrics -machine -mad -magic -magnet -maid -mail -main -major -make -mammal -man -manage -mandate -mango -mansion -manual -maple -marble -march -margin -marine -market -marriage -mask -mass -master -match -material -math -matrix -matter -maximum -maze -meadow -mean -measure -meat -mechanic -medal -media -melody -melt -member -memory -mention -menu -mercy -merge -merit -merry -mesh -message -metal -method -middle -midnight -milk -million -mimic -mind -minimum -minor -minute -miracle -mirror -misery -miss -mistake -mix -mixed -mixture -mobile -model -modify -mom -moment -monitor -monkey -monster -month -moon -moral -more -morning -mosquito -mother -motion -motor -mountain -mouse -move -movie -much -muffin -mule -multiply -muscle -museum -mushroom -music -must -mutual -myself -mystery -myth -naive -name -napkin -narrow -nasty -nation -nature -near -neck -need -negative -neglect -neither -nephew -nerve -nest -net -network -neutral -never -news -next -nice -night -noble -noise -nominee -noodle -normal -north -nose -notable -note -nothing -notice -novel -now -nuclear -number -nurse -nut -oak -obey -object -oblige -obscure -observe -obtain -obvious -occur -ocean -october -odor -off -offer -office -often -oil -okay -old -olive -olympic -omit -once -one -onion -online -only -open -opera -opinion -oppose -option -orange -orbit -orchard -order -ordinary -organ -orient -original -orphan -ostrich -other -outdoor -outer -output -outside -oval -oven -over -own -owner -oxygen -oyster -ozone -pact -paddle -page -pair -palace -palm -panda -panel -panic -panther -paper -parade -parent -park -parrot -party -pass -patch -path -patient -patrol -pattern -pause -pave -payment -peace -peanut -pear -peasant -pelican -pen -penalty -pencil -people -pepper -perfect -permit -person -pet -phone -photo -phrase -physical -piano -picnic -picture -piece -pig -pigeon -pill -pilot -pink -pioneer -pipe -pistol -pitch -pizza -place -planet -plastic -plate -play -please -pledge -pluck -plug -plunge -poem -poet -point -polar -pole -police -pond -pony -pool -popular -portion -position -possible -post -potato -pottery -poverty -powder -power -practice -praise -predict -prefer -prepare -present -pretty -prevent -price -pride -primary -print -priority -prison -private -prize -problem -process -produce -profit -program -project -promote -proof -property -prosper -protect -proud -provide -public -pudding -pull -pulp -pulse -pumpkin -punch -pupil -puppy -purchase -purity -purpose -purse -push -put -puzzle -pyramid -quality -quantum -quarter -question -quick -quit -quiz -quote -rabbit -raccoon -race -rack -radar -radio -rail -rain -raise -rally -ramp -ranch -random -range -rapid -rare -rate -rather -raven -raw -razor -ready -real -reason -rebel -rebuild -recall -receive -recipe -record -recycle -reduce -reflect -reform -refuse -region -regret -regular -reject -relax -release -relief -rely -remain -remember -remind -remove -render -renew -rent -reopen -repair -repeat -replace -report -require -rescue -resemble -resist -resource -response -result -retire -retreat -return -reunion -reveal -review -reward -rhythm -rib -ribbon -rice -rich -ride -ridge -rifle -right -rigid -ring -riot -ripple -risk -ritual -rival -river -road -roast -robot -robust -rocket -romance -roof -rookie -room -rose -rotate -rough -round -route -royal -rubber -rude -rug -rule -run -runway -rural -sad -saddle -sadness -safe -sail -salad -salmon -salon -salt -salute -same -sample -sand -satisfy -satoshi -sauce -sausage -save -say -scale -scan -scare -scatter -scene -scheme -school -science -scissors -scorpion -scout -scrap -screen -script -scrub -sea -search -season -seat -second -secret -section -security -seed -seek -segment -select -sell -seminar -senior -sense -sentence -series -service -session -settle -setup -seven -shadow -shaft -shallow -share -shed -shell -sheriff -shield -shift -shine -ship -shiver -shock -shoe -shoot -shop -short -shoulder -shove -shrimp -shrug -shuffle -shy -sibling -sick -side -siege -sight -sign -silent -silk -silly -silver -similar -simple -since -sing -siren -sister -situate -six -size -skate -sketch -ski -skill -skin -skirt -skull -slab -slam -sleep -slender -slice -slide -slight -slim -slogan -slot -slow -slush -small -smart -smile -smoke -smooth -snack -snake -snap -sniff -snow -soap -soccer -social -sock -soda -soft -solar -soldier -solid -solution -solve -someone -song -soon -sorry -sort -soul -sound -soup -source -south -space -spare -spatial -spawn -speak -special -speed -spell -spend -sphere -spice -spider -spike -spin -spirit -split -spoil -sponsor -spoon -sport -spot -spray -spread -spring -spy -square -squeeze -squirrel -stable -stadium -staff -stage -stairs -stamp -stand -start -state -stay -steak -steel -stem -step -stereo -stick -still -sting -stock -stomach -stone -stool -story -stove -strategy -street -strike -strong -struggle -student -stuff -stumble -style -subject -submit -subway -success -such -sudden -suffer -sugar -suggest -suit -summer -sun -sunny -sunset -super -supply -supreme -sure -surface -surge -surprise -surround -survey -suspect -sustain -swallow -swamp -swap -swarm -swear -sweet -swift -swim -swing -switch -sword -symbol -symptom -syrup -system -table -tackle -tag -tail -talent -talk -tank -tape -target -task -taste -tattoo -taxi -teach -team -tell -ten -tenant -tennis -tent -term -test -text -thank -that -theme -then -theory -there -they -thing -this -thought -three -thrive -throw -thumb -thunder -ticket -tide -tiger -tilt -timber -time -tiny -tip -tired -tissue -title -toast -tobacco -today -toddler -toe -together -toilet -token -tomato -tomorrow -tone -tongue -tonight -tool -tooth -top -topic -topple -torch -tornado -tortoise -toss -total -tourist -toward -tower -town -toy -track -trade -traffic -tragic -train -transfer -trap -trash -travel -tray -treat -tree -trend -trial -tribe -trick -trigger -trim -trip -trophy -trouble -truck -true -truly -trumpet -trust -truth -try -tube -tuition -tumble -tuna -tunnel -turkey -turn -turtle -twelve -twenty -twice -twin -twist -two -type -typical -ugly -umbrella -unable -unaware -uncle -uncover -under -undo -unfair -unfold -unhappy -uniform -unique -unit -universe -unknown -unlock -until -unusual -unveil -update -upgrade -uphold -upon -upper -upset -urban -urge -usage -use -used -useful -useless -usual -utility -vacant -vacuum -vague -valid -valley -valve -van -vanish -vapor -various -vast -vault -vehicle -velvet -vendor -venture -venue -verb -verify -version -very -vessel -veteran -viable -vibrant -vicious -victory -video -view -village -vintage -violin -virtual -virus -visa -visit -visual -vital -vivid -vocal -voice -void -volcano -volume -vote -voyage -wage -wagon -wait -walk -wall -walnut -want -warfare -warm -warrior -wash -wasp -waste -water -wave -way -wealth -weapon -wear -weasel -weather -web -wedding -weekend -weird -welcome -west -wet -whale -what -wheat -wheel -when -where -whip -whisper -wide -width -wife -wild -will -win -window -wine -wing -wink -winner -winter -wire -wisdom -wise -wish -witness -wolf -woman -wonder -wood -wool -word -work -world -worry -worth -wrap -wreck -wrestle -wrist -write -wrong -yard -year -yellow -you -young -youth -zebra -zero -zone -zoo diff --git a/contrib/bip39/french.txt b/contrib/bip39/french.txt deleted file mode 100644 index 8600949dda..0000000000 --- a/contrib/bip39/french.txt +++ /dev/null @@ -1,2048 +0,0 @@ -abaisser -abandon -abdiquer -abeille -abolir -aborder -aboutir -aboyer -abrasif -abreuver -abriter -abroger -abrupt -absence -absolu -absurde -abusif -abyssal -académie -acajou -acarien -accabler -accepter -acclamer -accolade -accroche -accuser -acerbe -achat -acheter -aciduler -acier -acompte -acquérir -acronyme -acteur -actif -actuel -adepte -adéquat -adhésif -adjectif -adjuger -admettre -admirer -adopter -adorer -adoucir -adresse -adroit -adulte -adverbe -aérer -aéronef -affaire -affecter -affiche -affreux -affubler -agacer -agencer -agile -agiter -agrafer -agréable -agrume -aider -aiguille -ailier -aimable -aisance -ajouter -ajuster -alarmer -alchimie -alerte -algèbre -algue -aliéner -aliment -alléger -alliage -allouer -allumer -alourdir -alpaga -altesse -alvéole -amateur -ambigu -ambre -aménager -amertume -amidon -amiral -amorcer -amour -amovible -amphibie -ampleur -amusant -analyse -anaphore -anarchie -anatomie -ancien -anéantir -angle -angoisse -anguleux -animal -annexer -annonce -annuel -anodin -anomalie -anonyme -anormal -antenne -antidote -anxieux -apaiser -apéritif -aplanir -apologie -appareil -appeler -apporter -appuyer -aquarium -aqueduc -arbitre -arbuste -ardeur -ardoise -argent -arlequin -armature -armement -armoire -armure -arpenter -arracher -arriver -arroser -arsenic -artériel -article -aspect -asphalte -aspirer -assaut -asservir -assiette -associer -assurer -asticot -astre -astuce -atelier -atome -atrium -atroce -attaque -attentif -attirer -attraper -aubaine -auberge -audace -audible -augurer -aurore -automne -autruche -avaler -avancer -avarice -avenir -averse -aveugle -aviateur -avide -avion -aviser -avoine -avouer -avril -axial -axiome -badge -bafouer -bagage -baguette -baignade -balancer -balcon -baleine -balisage -bambin -bancaire -bandage -banlieue -bannière -banquier -barbier -baril -baron -barque -barrage -bassin -bastion -bataille -bateau -batterie -baudrier -bavarder -belette -bélier -belote -bénéfice -berceau -berger -berline -bermuda -besace -besogne -bétail -beurre -biberon -bicycle -bidule -bijou -bilan -bilingue -billard -binaire -biologie -biopsie -biotype -biscuit -bison -bistouri -bitume -bizarre -blafard -blague -blanchir -blessant -blinder -blond -bloquer -blouson -bobard -bobine -boire -boiser -bolide -bonbon -bondir -bonheur -bonifier -bonus -bordure -borne -botte -boucle -boueux -bougie -boulon -bouquin -bourse -boussole -boutique -boxeur -branche -brasier -brave -brebis -brèche -breuvage -bricoler -brigade -brillant -brioche -brique -brochure -broder -bronzer -brousse -broyeur -brume -brusque -brutal -bruyant -buffle -buisson -bulletin -bureau -burin -bustier -butiner -butoir -buvable -buvette -cabanon -cabine -cachette -cadeau -cadre -caféine -caillou -caisson -calculer -calepin -calibre -calmer -calomnie -calvaire -camarade -caméra -camion -campagne -canal -caneton -canon -cantine -canular -capable -caporal -caprice -capsule -capter -capuche -carabine -carbone -caresser -caribou -carnage -carotte -carreau -carton -cascade -casier -casque -cassure -causer -caution -cavalier -caverne -caviar -cédille -ceinture -céleste -cellule -cendrier -censurer -central -cercle -cérébral -cerise -cerner -cerveau -cesser -chagrin -chaise -chaleur -chambre -chance -chapitre -charbon -chasseur -chaton -chausson -chavirer -chemise -chenille -chéquier -chercher -cheval -chien -chiffre -chignon -chimère -chiot -chlorure -chocolat -choisir -chose -chouette -chrome -chute -cigare -cigogne -cimenter -cinéma -cintrer -circuler -cirer -cirque -citerne -citoyen -citron -civil -clairon -clameur -claquer -classe -clavier -client -cligner -climat -clivage -cloche -clonage -cloporte -cobalt -cobra -cocasse -cocotier -coder -codifier -coffre -cogner -cohésion -coiffer -coincer -colère -colibri -colline -colmater -colonel -combat -comédie -commande -compact -concert -conduire -confier -congeler -connoter -consonne -contact -convexe -copain -copie -corail -corbeau -cordage -corniche -corpus -correct -cortège -cosmique -costume -coton -coude -coupure -courage -couteau -couvrir -coyote -crabe -crainte -cravate -crayon -créature -créditer -crémeux -creuser -crevette -cribler -crier -cristal -critère -croire -croquer -crotale -crucial -cruel -crypter -cubique -cueillir -cuillère -cuisine -cuivre -culminer -cultiver -cumuler -cupide -curatif -curseur -cyanure -cycle -cylindre -cynique -daigner -damier -danger -danseur -dauphin -débattre -débiter -déborder -débrider -débutant -décaler -décembre -déchirer -décider -déclarer -décorer -décrire -décupler -dédale -déductif -déesse -défensif -défiler -défrayer -dégager -dégivrer -déglutir -dégrafer -déjeuner -délice -déloger -demander -demeurer -démolir -dénicher -dénouer -dentelle -dénuder -départ -dépenser -déphaser -déplacer -déposer -déranger -dérober -désastre -descente -désert -désigner -désobéir -dessiner -destrier -détacher -détester -détourer -détresse -devancer -devenir -deviner -devoir -diable -dialogue -diamant -dicter -différer -digérer -digital -digne -diluer -dimanche -diminuer -dioxyde -directif -diriger -discuter -disposer -dissiper -distance -divertir -diviser -docile -docteur -dogme -doigt -domaine -domicile -dompter -donateur -donjon -donner -dopamine -dortoir -dorure -dosage -doseur -dossier -dotation -douanier -double -douceur -douter -doyen -dragon -draper -dresser -dribbler -droiture -duperie -duplexe -durable -durcir -dynastie -éblouir -écarter -écharpe -échelle -éclairer -éclipse -éclore -écluse -école -économie -écorce -écouter -écraser -écrémer -écrivain -écrou -écume -écureuil -édifier -éduquer -effacer -effectif -effigie -effort -effrayer -effusion -égaliser -égarer -éjecter -élaborer -élargir -électron -élégant -éléphant -élève -éligible -élitisme -éloge -élucider -éluder -emballer -embellir -embryon -émeraude -émission -emmener -émotion -émouvoir -empereur -employer -emporter -emprise -émulsion -encadrer -enchère -enclave -encoche -endiguer -endosser -endroit -enduire -énergie -enfance -enfermer -enfouir -engager -engin -englober -énigme -enjamber -enjeu -enlever -ennemi -ennuyeux -enrichir -enrobage -enseigne -entasser -entendre -entier -entourer -entraver -énumérer -envahir -enviable -envoyer -enzyme -éolien -épaissir -épargne -épatant -épaule -épicerie -épidémie -épier -épilogue -épine -épisode -épitaphe -époque -épreuve -éprouver -épuisant -équerre -équipe -ériger -érosion -erreur -éruption -escalier -espadon -espèce -espiègle -espoir -esprit -esquiver -essayer -essence -essieu -essorer -estime -estomac -estrade -étagère -étaler -étanche -étatique -éteindre -étendoir -éternel -éthanol -éthique -ethnie -étirer -étoffer -étoile -étonnant -étourdir -étrange -étroit -étude -euphorie -évaluer -évasion -éventail -évidence -éviter -évolutif -évoquer -exact -exagérer -exaucer -exceller -excitant -exclusif -excuse -exécuter -exemple -exercer -exhaler -exhorter -exigence -exiler -exister -exotique -expédier -explorer -exposer -exprimer -exquis -extensif -extraire -exulter -fable -fabuleux -facette -facile -facture -faiblir -falaise -fameux -famille -farceur -farfelu -farine -farouche -fasciner -fatal -fatigue -faucon -fautif -faveur -favori -fébrile -féconder -fédérer -félin -femme -fémur -fendoir -féodal -fermer -féroce -ferveur -festival -feuille -feutre -février -fiasco -ficeler -fictif -fidèle -figure -filature -filetage -filière -filleul -filmer -filou -filtrer -financer -finir -fiole -firme -fissure -fixer -flairer -flamme -flasque -flatteur -fléau -flèche -fleur -flexion -flocon -flore -fluctuer -fluide -fluvial -folie -fonderie -fongible -fontaine -forcer -forgeron -formuler -fortune -fossile -foudre -fougère -fouiller -foulure -fourmi -fragile -fraise -franchir -frapper -frayeur -frégate -freiner -frelon -frémir -frénésie -frère -friable -friction -frisson -frivole -froid -fromage -frontal -frotter -fruit -fugitif -fuite -fureur -furieux -furtif -fusion -futur -gagner -galaxie -galerie -gambader -garantir -gardien -garnir -garrigue -gazelle -gazon -géant -gélatine -gélule -gendarme -général -génie -genou -gentil -géologie -géomètre -géranium -germe -gestuel -geyser -gibier -gicler -girafe -givre -glace -glaive -glisser -globe -gloire -glorieux -golfeur -gomme -gonfler -gorge -gorille -goudron -gouffre -goulot -goupille -gourmand -goutte -graduel -graffiti -graine -grand -grappin -gratuit -gravir -grenat -griffure -griller -grimper -grogner -gronder -grotte -groupe -gruger -grutier -gruyère -guépard -guerrier -guide -guimauve -guitare -gustatif -gymnaste -gyrostat -habitude -hachoir -halte -hameau -hangar -hanneton -haricot -harmonie -harpon -hasard -hélium -hématome -herbe -hérisson -hermine -héron -hésiter -heureux -hiberner -hibou -hilarant -histoire -hiver -homard -hommage -homogène -honneur -honorer -honteux -horde -horizon -horloge -hormone -horrible -houleux -housse -hublot -huileux -humain -humble -humide -humour -hurler -hydromel -hygiène -hymne -hypnose -idylle -ignorer -iguane -illicite -illusion -image -imbiber -imiter -immense -immobile -immuable -impact -impérial -implorer -imposer -imprimer -imputer -incarner -incendie -incident -incliner -incolore -indexer -indice -inductif -inédit -ineptie -inexact -infini -infliger -informer -infusion -ingérer -inhaler -inhiber -injecter -injure -innocent -inoculer -inonder -inscrire -insecte -insigne -insolite -inspirer -instinct -insulter -intact -intense -intime -intrigue -intuitif -inutile -invasion -inventer -inviter -invoquer -ironique -irradier -irréel -irriter -isoler -ivoire -ivresse -jaguar -jaillir -jambe -janvier -jardin -jauger -jaune -javelot -jetable -jeton -jeudi -jeunesse -joindre -joncher -jongler -joueur -jouissif -journal -jovial -joyau -joyeux -jubiler -jugement -junior -jupon -juriste -justice -juteux -juvénile -kayak -kimono -kiosque -label -labial -labourer -lacérer -lactose -lagune -laine -laisser -laitier -lambeau -lamelle -lampe -lanceur -langage -lanterne -lapin -largeur -larme -laurier -lavabo -lavoir -lecture -légal -léger -légume -lessive -lettre -levier -lexique -lézard -liasse -libérer -libre -licence -licorne -liège -lièvre -ligature -ligoter -ligue -limer -limite -limonade -limpide -linéaire -lingot -lionceau -liquide -lisière -lister -lithium -litige -littoral -livreur -logique -lointain -loisir -lombric -loterie -louer -lourd -loutre -louve -loyal -lubie -lucide -lucratif -lueur -lugubre -luisant -lumière -lunaire -lundi -luron -lutter -luxueux -machine -magasin -magenta -magique -maigre -maillon -maintien -mairie -maison -majorer -malaxer -maléfice -malheur -malice -mallette -mammouth -mandater -maniable -manquant -manteau -manuel -marathon -marbre -marchand -mardi -maritime -marqueur -marron -marteler -mascotte -massif -matériel -matière -matraque -maudire -maussade -mauve -maximal -méchant -méconnu -médaille -médecin -méditer -méduse -meilleur -mélange -mélodie -membre -mémoire -menacer -mener -menhir -mensonge -mentor -mercredi -mérite -merle -messager -mesure -métal -météore -méthode -métier -meuble -miauler -microbe -miette -mignon -migrer -milieu -million -mimique -mince -minéral -minimal -minorer -minute -miracle -miroiter -missile -mixte -mobile -moderne -moelleux -mondial -moniteur -monnaie -monotone -monstre -montagne -monument -moqueur -morceau -morsure -mortier -moteur -motif -mouche -moufle -moulin -mousson -mouton -mouvant -multiple -munition -muraille -murène -murmure -muscle -muséum -musicien -mutation -muter -mutuel -myriade -myrtille -mystère -mythique -nageur -nappe -narquois -narrer -natation -nation -nature -naufrage -nautique -navire -nébuleux -nectar -néfaste -négation -négliger -négocier -neige -nerveux -nettoyer -neurone -neutron -neveu -niche -nickel -nitrate -niveau -noble -nocif -nocturne -noirceur -noisette -nomade -nombreux -nommer -normatif -notable -notifier -notoire -nourrir -nouveau -novateur -novembre -novice -nuage -nuancer -nuire -nuisible -numéro -nuptial -nuque -nutritif -obéir -objectif -obliger -obscur -observer -obstacle -obtenir -obturer -occasion -occuper -océan -octobre -octroyer -octupler -oculaire -odeur -odorant -offenser -officier -offrir -ogive -oiseau -oisillon -olfactif -olivier -ombrage -omettre -onctueux -onduler -onéreux -onirique -opale -opaque -opérer -opinion -opportun -opprimer -opter -optique -orageux -orange -orbite -ordonner -oreille -organe -orgueil -orifice -ornement -orque -ortie -osciller -osmose -ossature -otarie -ouragan -ourson -outil -outrager -ouvrage -ovation -oxyde -oxygène -ozone -paisible -palace -palmarès -palourde -palper -panache -panda -pangolin -paniquer -panneau -panorama -pantalon -papaye -papier -papoter -papyrus -paradoxe -parcelle -paresse -parfumer -parler -parole -parrain -parsemer -partager -parure -parvenir -passion -pastèque -paternel -patience -patron -pavillon -pavoiser -payer -paysage -peigne -peintre -pelage -pélican -pelle -pelouse -peluche -pendule -pénétrer -pénible -pensif -pénurie -pépite -péplum -perdrix -perforer -période -permuter -perplexe -persil -perte -peser -pétale -petit -pétrir -peuple -pharaon -phobie -phoque -photon -phrase -physique -piano -pictural -pièce -pierre -pieuvre -pilote -pinceau -pipette -piquer -pirogue -piscine -piston -pivoter -pixel -pizza -placard -plafond -plaisir -planer -plaque -plastron -plateau -pleurer -plexus -pliage -plomb -plonger -pluie -plumage -pochette -poésie -poète -pointe -poirier -poisson -poivre -polaire -policier -pollen -polygone -pommade -pompier -ponctuel -pondérer -poney -portique -position -posséder -posture -potager -poteau -potion -pouce -poulain -poumon -pourpre -poussin -pouvoir -prairie -pratique -précieux -prédire -préfixe -prélude -prénom -présence -prétexte -prévoir -primitif -prince -prison -priver -problème -procéder -prodige -profond -progrès -proie -projeter -prologue -promener -propre -prospère -protéger -prouesse -proverbe -prudence -pruneau -psychose -public -puceron -puiser -pulpe -pulsar -punaise -punitif -pupitre -purifier -puzzle -pyramide -quasar -querelle -question -quiétude -quitter -quotient -racine -raconter -radieux -ragondin -raideur -raisin -ralentir -rallonge -ramasser -rapide -rasage -ratisser -ravager -ravin -rayonner -réactif -réagir -réaliser -réanimer -recevoir -réciter -réclamer -récolter -recruter -reculer -recycler -rédiger -redouter -refaire -réflexe -réformer -refrain -refuge -régalien -région -réglage -régulier -réitérer -rejeter -rejouer -relatif -relever -relief -remarque -remède -remise -remonter -remplir -remuer -renard -renfort -renifler -renoncer -rentrer -renvoi -replier -reporter -reprise -reptile -requin -réserve -résineux -résoudre -respect -rester -résultat -rétablir -retenir -réticule -retomber -retracer -réunion -réussir -revanche -revivre -révolte -révulsif -richesse -rideau -rieur -rigide -rigoler -rincer -riposter -risible -risque -rituel -rival -rivière -rocheux -romance -rompre -ronce -rondin -roseau -rosier -rotatif -rotor -rotule -rouge -rouille -rouleau -routine -royaume -ruban -rubis -ruche -ruelle -rugueux -ruiner -ruisseau -ruser -rustique -rythme -sabler -saboter -sabre -sacoche -safari -sagesse -saisir -salade -salive -salon -saluer -samedi -sanction -sanglier -sarcasme -sardine -saturer -saugrenu -saumon -sauter -sauvage -savant -savonner -scalpel -scandale -scélérat -scénario -sceptre -schéma -science -scinder -score -scrutin -sculpter -séance -sécable -sécher -secouer -sécréter -sédatif -séduire -seigneur -séjour -sélectif -semaine -sembler -semence -séminal -sénateur -sensible -sentence -séparer -séquence -serein -sergent -sérieux -serrure -sérum -service -sésame -sévir -sevrage -sextuple -sidéral -siècle -siéger -siffler -sigle -signal -silence -silicium -simple -sincère -sinistre -siphon -sirop -sismique -situer -skier -social -socle -sodium -soigneux -soldat -soleil -solitude -soluble -sombre -sommeil -somnoler -sonde -songeur -sonnette -sonore -sorcier -sortir -sosie -sottise -soucieux -soudure -souffle -soulever -soupape -source -soutirer -souvenir -spacieux -spatial -spécial -sphère -spiral -stable -station -sternum -stimulus -stipuler -strict -studieux -stupeur -styliste -sublime -substrat -subtil -subvenir -succès -sucre -suffixe -suggérer -suiveur -sulfate -superbe -supplier -surface -suricate -surmener -surprise -sursaut -survie -suspect -syllabe -symbole -symétrie -synapse -syntaxe -système -tabac -tablier -tactile -tailler -talent -talisman -talonner -tambour -tamiser -tangible -tapis -taquiner -tarder -tarif -tartine -tasse -tatami -tatouage -taupe -taureau -taxer -témoin -temporel -tenaille -tendre -teneur -tenir -tension -terminer -terne -terrible -tétine -texte -thème -théorie -thérapie -thorax -tibia -tiède -timide -tirelire -tiroir -tissu -titane -titre -tituber -toboggan -tolérant -tomate -tonique -tonneau -toponyme -torche -tordre -tornade -torpille -torrent -torse -tortue -totem -toucher -tournage -tousser -toxine -traction -trafic -tragique -trahir -train -trancher -travail -trèfle -tremper -trésor -treuil -triage -tribunal -tricoter -trilogie -triomphe -tripler -triturer -trivial -trombone -tronc -tropical -troupeau -tuile -tulipe -tumulte -tunnel -turbine -tuteur -tutoyer -tuyau -tympan -typhon -typique -tyran -ubuesque -ultime -ultrason -unanime -unifier -union -unique -unitaire -univers -uranium -urbain -urticant -usage -usine -usuel -usure -utile -utopie -vacarme -vaccin -vagabond -vague -vaillant -vaincre -vaisseau -valable -valise -vallon -valve -vampire -vanille -vapeur -varier -vaseux -vassal -vaste -vecteur -vedette -végétal -véhicule -veinard -véloce -vendredi -vénérer -venger -venimeux -ventouse -verdure -vérin -vernir -verrou -verser -vertu -veston -vétéran -vétuste -vexant -vexer -viaduc -viande -victoire -vidange -vidéo -vignette -vigueur -vilain -village -vinaigre -violon -vipère -virement -virtuose -virus -visage -viseur -vision -visqueux -visuel -vital -vitesse -viticole -vitrine -vivace -vivipare -vocation -voguer -voile -voisin -voiture -volaille -volcan -voltiger -volume -vorace -vortex -voter -vouloir -voyage -voyelle -wagon -xénon -yacht -zèbre -zénith -zeste -zoologie \ No newline at end of file diff --git a/contrib/bip39/japanese.txt b/contrib/bip39/japanese.txt deleted file mode 100644 index fb8501a6ed..0000000000 --- a/contrib/bip39/japanese.txt +++ /dev/null @@ -1,2048 +0,0 @@ -あいこくしん -あいさつ -あいだ -あおぞら -あかちゃん -あきる -あけがた -あける -あこがれる -あさい -あさひ -あしあと -あじわう -あずかる -あずき -あそぶ -あたえる -あたためる -あたりまえ -あたる -あつい -あつかう -あっしゅく -あつまり -あつめる -あてな -あてはまる -あひる -あぶら -あぶる -あふれる -あまい -あまど -あまやかす -あまり -あみもの -あめりか -あやまる -あゆむ -あらいぐま -あらし -あらすじ -あらためる -あらゆる -あらわす -ありがとう -あわせる -あわてる -あんい -あんがい -あんこ -あんぜん -あんてい -あんない -あんまり -いいだす -いおん -いがい -いがく -いきおい -いきなり -いきもの -いきる -いくじ -いくぶん -いけばな -いけん -いこう -いこく -いこつ -いさましい -いさん -いしき -いじゅう -いじょう -いじわる -いずみ -いずれ -いせい -いせえび -いせかい -いせき -いぜん -いそうろう -いそがしい -いだい -いだく -いたずら -いたみ -いたりあ -いちおう -いちじ -いちど -いちば -いちぶ -いちりゅう -いつか -いっしゅん -いっせい -いっそう -いったん -いっち -いってい -いっぽう -いてざ -いてん -いどう -いとこ -いない -いなか -いねむり -いのち -いのる -いはつ -いばる -いはん -いびき -いひん -いふく -いへん -いほう -いみん -いもうと -いもたれ -いもり -いやがる -いやす -いよかん -いよく -いらい -いらすと -いりぐち -いりょう -いれい -いれもの -いれる -いろえんぴつ -いわい -いわう -いわかん -いわば -いわゆる -いんげんまめ -いんさつ -いんしょう -いんよう -うえき -うえる -うおざ -うがい -うかぶ -うかべる -うきわ -うくらいな -うくれれ -うけたまわる -うけつけ -うけとる -うけもつ -うける -うごかす -うごく -うこん -うさぎ -うしなう -うしろがみ -うすい -うすぎ -うすぐらい -うすめる -うせつ -うちあわせ -うちがわ -うちき -うちゅう -うっかり -うつくしい -うったえる -うつる -うどん -うなぎ -うなじ -うなずく -うなる -うねる -うのう -うぶげ -うぶごえ -うまれる -うめる -うもう -うやまう -うよく -うらがえす -うらぐち -うらない -うりあげ -うりきれ -うるさい -うれしい -うれゆき -うれる -うろこ -うわき -うわさ -うんこう -うんちん -うんてん -うんどう -えいえん -えいが -えいきょう -えいご -えいせい -えいぶん -えいよう -えいわ -えおり -えがお -えがく -えきたい -えくせる -えしゃく -えすて -えつらん -えのぐ -えほうまき -えほん -えまき -えもじ -えもの -えらい -えらぶ -えりあ -えんえん -えんかい -えんぎ -えんげき -えんしゅう -えんぜつ -えんそく -えんちょう -えんとつ -おいかける -おいこす -おいしい -おいつく -おうえん -おうさま -おうじ -おうせつ -おうたい -おうふく -おうべい -おうよう -おえる -おおい -おおう -おおどおり -おおや -おおよそ -おかえり -おかず -おがむ -おかわり -おぎなう -おきる -おくさま -おくじょう -おくりがな -おくる -おくれる -おこす -おこなう -おこる -おさえる -おさない -おさめる -おしいれ -おしえる -おじぎ -おじさん -おしゃれ -おそらく -おそわる -おたがい -おたく -おだやか -おちつく -おっと -おつり -おでかけ -おとしもの -おとなしい -おどり -おどろかす -おばさん -おまいり -おめでとう -おもいで -おもう -おもたい -おもちゃ -おやつ -おやゆび -およぼす -おらんだ -おろす -おんがく -おんけい -おんしゃ -おんせん -おんだん -おんちゅう -おんどけい -かあつ -かいが -がいき -がいけん -がいこう -かいさつ -かいしゃ -かいすいよく -かいぜん -かいぞうど -かいつう -かいてん -かいとう -かいふく -がいへき -かいほう -かいよう -がいらい -かいわ -かえる -かおり -かかえる -かがく -かがし -かがみ -かくご -かくとく -かざる -がぞう -かたい -かたち -がちょう -がっきゅう -がっこう -がっさん -がっしょう -かなざわし -かのう -がはく -かぶか -かほう -かほご -かまう -かまぼこ -かめれおん -かゆい -かようび -からい -かるい -かろう -かわく -かわら -がんか -かんけい -かんこう -かんしゃ -かんそう -かんたん -かんち -がんばる -きあい -きあつ -きいろ -ぎいん -きうい -きうん -きえる -きおう -きおく -きおち -きおん -きかい -きかく -きかんしゃ -ききて -きくばり -きくらげ -きけんせい -きこう -きこえる -きこく -きさい -きさく -きさま -きさらぎ -ぎじかがく -ぎしき -ぎじたいけん -ぎじにってい -ぎじゅつしゃ -きすう -きせい -きせき -きせつ -きそう -きぞく -きぞん -きたえる -きちょう -きつえん -ぎっちり -きつつき -きつね -きてい -きどう -きどく -きない -きなが -きなこ -きぬごし -きねん -きのう -きのした -きはく -きびしい -きひん -きふく -きぶん -きぼう -きほん -きまる -きみつ -きむずかしい -きめる -きもだめし -きもち -きもの -きゃく -きやく -ぎゅうにく -きよう -きょうりゅう -きらい -きらく -きりん -きれい -きれつ -きろく -ぎろん -きわめる -ぎんいろ -きんかくじ -きんじょ -きんようび -ぐあい -くいず -くうかん -くうき -くうぐん -くうこう -ぐうせい -くうそう -ぐうたら -くうふく -くうぼ -くかん -くきょう -くげん -ぐこう -くさい -くさき -くさばな -くさる -くしゃみ -くしょう -くすのき -くすりゆび -くせげ -くせん -ぐたいてき -くださる -くたびれる -くちこみ -くちさき -くつした -ぐっすり -くつろぐ -くとうてん -くどく -くなん -くねくね -くのう -くふう -くみあわせ -くみたてる -くめる -くやくしょ -くらす -くらべる -くるま -くれる -くろう -くわしい -ぐんかん -ぐんしょく -ぐんたい -ぐんて -けあな -けいかく -けいけん -けいこ -けいさつ -げいじゅつ -けいたい -げいのうじん -けいれき -けいろ -けおとす -けおりもの -げきか -げきげん -げきだん -げきちん -げきとつ -げきは -げきやく -げこう -げこくじょう -げざい -けさき -げざん -けしき -けしごむ -けしょう -げすと -けたば -けちゃっぷ -けちらす -けつあつ -けつい -けつえき -けっこん -けつじょ -けっせき -けってい -けつまつ -げつようび -げつれい -けつろん -げどく -けとばす -けとる -けなげ -けなす -けなみ -けぬき -げねつ -けねん -けはい -げひん -けぶかい -げぼく -けまり -けみかる -けむし -けむり -けもの -けらい -けろけろ -けわしい -けんい -けんえつ -けんお -けんか -げんき -けんげん -けんこう -けんさく -けんしゅう -けんすう -げんそう -けんちく -けんてい -けんとう -けんない -けんにん -げんぶつ -けんま -けんみん -けんめい -けんらん -けんり -こあくま -こいぬ -こいびと -ごうい -こうえん -こうおん -こうかん -ごうきゅう -ごうけい -こうこう -こうさい -こうじ -こうすい -ごうせい -こうそく -こうたい -こうちゃ -こうつう -こうてい -こうどう -こうない -こうはい -ごうほう -ごうまん -こうもく -こうりつ -こえる -こおり -ごかい -ごがつ -ごかん -こくご -こくさい -こくとう -こくない -こくはく -こぐま -こけい -こける -ここのか -こころ -こさめ -こしつ -こすう -こせい -こせき -こぜん -こそだて -こたい -こたえる -こたつ -こちょう -こっか -こつこつ -こつばん -こつぶ -こてい -こてん -ことがら -ことし -ことば -ことり -こなごな -こねこね -このまま -このみ -このよ -ごはん -こひつじ -こふう -こふん -こぼれる -ごまあぶら -こまかい -ごますり -こまつな -こまる -こむぎこ -こもじ -こもち -こもの -こもん -こやく -こやま -こゆう -こゆび -こよい -こよう -こりる -これくしょん -ころっけ -こわもて -こわれる -こんいん -こんかい -こんき -こんしゅう -こんすい -こんだて -こんとん -こんなん -こんびに -こんぽん -こんまけ -こんや -こんれい -こんわく -ざいえき -さいかい -さいきん -ざいげん -ざいこ -さいしょ -さいせい -ざいたく -ざいちゅう -さいてき -ざいりょう -さうな -さかいし -さがす -さかな -さかみち -さがる -さぎょう -さくし -さくひん -さくら -さこく -さこつ -さずかる -ざせき -さたん -さつえい -ざつおん -ざっか -ざつがく -さっきょく -ざっし -さつじん -ざっそう -さつたば -さつまいも -さてい -さといも -さとう -さとおや -さとし -さとる -さのう -さばく -さびしい -さべつ -さほう -さほど -さます -さみしい -さみだれ -さむけ -さめる -さやえんどう -さゆう -さよう -さよく -さらだ -ざるそば -さわやか -さわる -さんいん -さんか -さんきゃく -さんこう -さんさい -ざんしょ -さんすう -さんせい -さんそ -さんち -さんま -さんみ -さんらん -しあい -しあげ -しあさって -しあわせ -しいく -しいん -しうち -しえい -しおけ -しかい -しかく -じかん -しごと -しすう -じだい -したうけ -したぎ -したて -したみ -しちょう -しちりん -しっかり -しつじ -しつもん -してい -してき -してつ -じてん -じどう -しなぎれ -しなもの -しなん -しねま -しねん -しのぐ -しのぶ -しはい -しばかり -しはつ -しはらい -しはん -しひょう -しふく -じぶん -しへい -しほう -しほん -しまう -しまる -しみん -しむける -じむしょ -しめい -しめる -しもん -しゃいん -しゃうん -しゃおん -じゃがいも -しやくしょ -しゃくほう -しゃけん -しゃこ -しゃざい -しゃしん -しゃせん -しゃそう -しゃたい -しゃちょう -しゃっきん -じゃま -しゃりん -しゃれい -じゆう -じゅうしょ -しゅくはく -じゅしん -しゅっせき -しゅみ -しゅらば -じゅんばん -しょうかい -しょくたく -しょっけん -しょどう -しょもつ -しらせる -しらべる -しんか -しんこう -じんじゃ -しんせいじ -しんちく -しんりん -すあげ -すあし -すあな -ずあん -すいえい -すいか -すいとう -ずいぶん -すいようび -すうがく -すうじつ -すうせん -すおどり -すきま -すくう -すくない -すける -すごい -すこし -ずさん -すずしい -すすむ -すすめる -すっかり -ずっしり -ずっと -すてき -すてる -すねる -すのこ -すはだ -すばらしい -ずひょう -ずぶぬれ -すぶり -すふれ -すべて -すべる -ずほう -すぼん -すまい -すめし -すもう -すやき -すらすら -するめ -すれちがう -すろっと -すわる -すんぜん -すんぽう -せあぶら -せいかつ -せいげん -せいじ -せいよう -せおう -せかいかん -せきにん -せきむ -せきゆ -せきらんうん -せけん -せこう -せすじ -せたい -せたけ -せっかく -せっきゃく -ぜっく -せっけん -せっこつ -せっさたくま -せつぞく -せつだん -せつでん -せっぱん -せつび -せつぶん -せつめい -せつりつ -せなか -せのび -せはば -せびろ -せぼね -せまい -せまる -せめる -せもたれ -せりふ -ぜんあく -せんい -せんえい -せんか -せんきょ -せんく -せんげん -ぜんご -せんさい -せんしゅ -せんすい -せんせい -せんぞ -せんたく -せんちょう -せんてい -せんとう -せんぬき -せんねん -せんぱい -ぜんぶ -ぜんぽう -せんむ -せんめんじょ -せんもん -せんやく -せんゆう -せんよう -ぜんら -ぜんりゃく -せんれい -せんろ -そあく -そいとげる -そいね -そうがんきょう -そうき -そうご -そうしん -そうだん -そうなん -そうび -そうめん -そうり -そえもの -そえん -そがい -そげき -そこう -そこそこ -そざい -そしな -そせい -そせん -そそぐ -そだてる -そつう -そつえん -そっかん -そつぎょう -そっけつ -そっこう -そっせん -そっと -そとがわ -そとづら -そなえる -そなた -そふぼ -そぼく -そぼろ -そまつ -そまる -そむく -そむりえ -そめる -そもそも -そよかぜ -そらまめ -そろう -そんかい -そんけい -そんざい -そんしつ -そんぞく -そんちょう -ぞんび -ぞんぶん -そんみん -たあい -たいいん -たいうん -たいえき -たいおう -だいがく -たいき -たいぐう -たいけん -たいこ -たいざい -だいじょうぶ -だいすき -たいせつ -たいそう -だいたい -たいちょう -たいてい -だいどころ -たいない -たいねつ -たいのう -たいはん -だいひょう -たいふう -たいへん -たいほ -たいまつばな -たいみんぐ -たいむ -たいめん -たいやき -たいよう -たいら -たいりょく -たいる -たいわん -たうえ -たえる -たおす -たおる -たおれる -たかい -たかね -たきび -たくさん -たこく -たこやき -たさい -たしざん -だじゃれ -たすける -たずさわる -たそがれ -たたかう -たたく -ただしい -たたみ -たちばな -だっかい -だっきゃく -だっこ -だっしゅつ -だったい -たてる -たとえる -たなばた -たにん -たぬき -たのしみ -たはつ -たぶん -たべる -たぼう -たまご -たまる -だむる -ためいき -ためす -ためる -たもつ -たやすい -たよる -たらす -たりきほんがん -たりょう -たりる -たると -たれる -たれんと -たろっと -たわむれる -だんあつ -たんい -たんおん -たんか -たんき -たんけん -たんご -たんさん -たんじょうび -だんせい -たんそく -たんたい -だんち -たんてい -たんとう -だんな -たんにん -だんねつ -たんのう -たんぴん -だんぼう -たんまつ -たんめい -だんれつ -だんろ -だんわ -ちあい -ちあん -ちいき -ちいさい -ちえん -ちかい -ちから -ちきゅう -ちきん -ちけいず -ちけん -ちこく -ちさい -ちしき -ちしりょう -ちせい -ちそう -ちたい -ちたん -ちちおや -ちつじょ -ちてき -ちてん -ちぬき -ちぬり -ちのう -ちひょう -ちへいせん -ちほう -ちまた -ちみつ -ちみどろ -ちめいど -ちゃんこなべ -ちゅうい -ちゆりょく -ちょうし -ちょさくけん -ちらし -ちらみ -ちりがみ -ちりょう -ちるど -ちわわ -ちんたい -ちんもく -ついか -ついたち -つうか -つうじょう -つうはん -つうわ -つかう -つかれる -つくね -つくる -つけね -つける -つごう -つたえる -つづく -つつじ -つつむ -つとめる -つながる -つなみ -つねづね -つのる -つぶす -つまらない -つまる -つみき -つめたい -つもり -つもる -つよい -つるぼ -つるみく -つわもの -つわり -てあし -てあて -てあみ -ていおん -ていか -ていき -ていけい -ていこく -ていさつ -ていし -ていせい -ていたい -ていど -ていねい -ていひょう -ていへん -ていぼう -てうち -ておくれ -てきとう -てくび -でこぼこ -てさぎょう -てさげ -てすり -てそう -てちがい -てちょう -てつがく -てつづき -でっぱ -てつぼう -てつや -でぬかえ -てぬき -てぬぐい -てのひら -てはい -てぶくろ -てふだ -てほどき -てほん -てまえ -てまきずし -てみじか -てみやげ -てらす -てれび -てわけ -てわたし -でんあつ -てんいん -てんかい -てんき -てんぐ -てんけん -てんごく -てんさい -てんし -てんすう -でんち -てんてき -てんとう -てんない -てんぷら -てんぼうだい -てんめつ -てんらんかい -でんりょく -でんわ -どあい -といれ -どうかん -とうきゅう -どうぐ -とうし -とうむぎ -とおい -とおか -とおく -とおす -とおる -とかい -とかす -ときおり -ときどき -とくい -とくしゅう -とくてん -とくに -とくべつ -とけい -とける -とこや -とさか -としょかん -とそう -とたん -とちゅう -とっきゅう -とっくん -とつぜん -とつにゅう -とどける -ととのえる -とない -となえる -となり -とのさま -とばす -どぶがわ -とほう -とまる -とめる -ともだち -ともる -どようび -とらえる -とんかつ -どんぶり -ないかく -ないこう -ないしょ -ないす -ないせん -ないそう -なおす -ながい -なくす -なげる -なこうど -なさけ -なたでここ -なっとう -なつやすみ -ななおし -なにごと -なにもの -なにわ -なのか -なふだ -なまいき -なまえ -なまみ -なみだ -なめらか -なめる -なやむ -ならう -ならび -ならぶ -なれる -なわとび -なわばり -にあう -にいがた -にうけ -におい -にかい -にがて -にきび -にくしみ -にくまん -にげる -にさんかたんそ -にしき -にせもの -にちじょう -にちようび -にっか -にっき -にっけい -にっこう -にっさん -にっしょく -にっすう -にっせき -にってい -になう -にほん -にまめ -にもつ -にやり -にゅういん -にりんしゃ -にわとり -にんい -にんか -にんき -にんげん -にんしき -にんずう -にんそう -にんたい -にんち -にんてい -にんにく -にんぷ -にんまり -にんむ -にんめい -にんよう -ぬいくぎ -ぬかす -ぬぐいとる -ぬぐう -ぬくもり -ぬすむ -ぬまえび -ぬめり -ぬらす -ぬんちゃく -ねあげ -ねいき -ねいる -ねいろ -ねぐせ -ねくたい -ねくら -ねこぜ -ねこむ -ねさげ -ねすごす -ねそべる -ねだん -ねつい -ねっしん -ねつぞう -ねったいぎょ -ねぶそく -ねふだ -ねぼう -ねほりはほり -ねまき -ねまわし -ねみみ -ねむい -ねむたい -ねもと -ねらう -ねわざ -ねんいり -ねんおし -ねんかん -ねんきん -ねんぐ -ねんざ -ねんし -ねんちゃく -ねんど -ねんぴ -ねんぶつ -ねんまつ -ねんりょう -ねんれい -のいず -のおづま -のがす -のきなみ -のこぎり -のこす -のこる -のせる -のぞく -のぞむ -のたまう -のちほど -のっく -のばす -のはら -のべる -のぼる -のみもの -のやま -のらいぬ -のらねこ -のりもの -のりゆき -のれん -のんき -ばあい -はあく -ばあさん -ばいか -ばいく -はいけん -はいご -はいしん -はいすい -はいせん -はいそう -はいち -ばいばい -はいれつ -はえる -はおる -はかい -ばかり -はかる -はくしゅ -はけん -はこぶ -はさみ -はさん -はしご -ばしょ -はしる -はせる -ぱそこん -はそん -はたん -はちみつ -はつおん -はっかく -はづき -はっきり -はっくつ -はっけん -はっこう -はっさん -はっしん -はったつ -はっちゅう -はってん -はっぴょう -はっぽう -はなす -はなび -はにかむ -はぶらし -はみがき -はむかう -はめつ -はやい -はやし -はらう -はろうぃん -はわい -はんい -はんえい -はんおん -はんかく -はんきょう -ばんぐみ -はんこ -はんしゃ -はんすう -はんだん -ぱんち -ぱんつ -はんてい -はんとし -はんのう -はんぱ -はんぶん -はんぺん -はんぼうき -はんめい -はんらん -はんろん -ひいき -ひうん -ひえる -ひかく -ひかり -ひかる -ひかん -ひくい -ひけつ -ひこうき -ひこく -ひさい -ひさしぶり -ひさん -びじゅつかん -ひしょ -ひそか -ひそむ -ひたむき -ひだり -ひたる -ひつぎ -ひっこし -ひっし -ひつじゅひん -ひっす -ひつぜん -ぴったり -ぴっちり -ひつよう -ひてい -ひとごみ -ひなまつり -ひなん -ひねる -ひはん -ひびく -ひひょう -ひほう -ひまわり -ひまん -ひみつ -ひめい -ひめじし -ひやけ -ひやす -ひよう -びょうき -ひらがな -ひらく -ひりつ -ひりょう -ひるま -ひるやすみ -ひれい -ひろい -ひろう -ひろき -ひろゆき -ひんかく -ひんけつ -ひんこん -ひんしゅ -ひんそう -ぴんち -ひんぱん -びんぼう -ふあん -ふいうち -ふうけい -ふうせん -ぷうたろう -ふうとう -ふうふ -ふえる -ふおん -ふかい -ふきん -ふくざつ -ふくぶくろ -ふこう -ふさい -ふしぎ -ふじみ -ふすま -ふせい -ふせぐ -ふそく -ぶたにく -ふたん -ふちょう -ふつう -ふつか -ふっかつ -ふっき -ふっこく -ぶどう -ふとる -ふとん -ふのう -ふはい -ふひょう -ふへん -ふまん -ふみん -ふめつ -ふめん -ふよう -ふりこ -ふりる -ふるい -ふんいき -ぶんがく -ぶんぐ -ふんしつ -ぶんせき -ふんそう -ぶんぽう -へいあん -へいおん -へいがい -へいき -へいげん -へいこう -へいさ -へいしゃ -へいせつ -へいそ -へいたく -へいてん -へいねつ -へいわ -へきが -へこむ -べにいろ -べにしょうが -へらす -へんかん -べんきょう -べんごし -へんさい -へんたい -べんり -ほあん -ほいく -ぼうぎょ -ほうこく -ほうそう -ほうほう -ほうもん -ほうりつ -ほえる -ほおん -ほかん -ほきょう -ぼきん -ほくろ -ほけつ -ほけん -ほこう -ほこる -ほしい -ほしつ -ほしゅ -ほしょう -ほせい -ほそい -ほそく -ほたて -ほたる -ぽちぶくろ -ほっきょく -ほっさ -ほったん -ほとんど -ほめる -ほんい -ほんき -ほんけ -ほんしつ -ほんやく -まいにち -まかい -まかせる -まがる -まける -まこと -まさつ -まじめ -ますく -まぜる -まつり -まとめ -まなぶ -まぬけ -まねく -まほう -まもる -まゆげ -まよう -まろやか -まわす -まわり -まわる -まんが -まんきつ -まんぞく -まんなか -みいら -みうち -みえる -みがく -みかた -みかん -みけん -みこん -みじかい -みすい -みすえる -みせる -みっか -みつかる -みつける -みてい -みとめる -みなと -みなみかさい -みねらる -みのう -みのがす -みほん -みもと -みやげ -みらい -みりょく -みわく -みんか -みんぞく -むいか -むえき -むえん -むかい -むかう -むかえ -むかし -むぎちゃ -むける -むげん -むさぼる -むしあつい -むしば -むじゅん -むしろ -むすう -むすこ -むすぶ -むすめ -むせる -むせん -むちゅう -むなしい -むのう -むやみ -むよう -むらさき -むりょう -むろん -めいあん -めいうん -めいえん -めいかく -めいきょく -めいさい -めいし -めいそう -めいぶつ -めいれい -めいわく -めぐまれる -めざす -めした -めずらしい -めだつ -めまい -めやす -めんきょ -めんせき -めんどう -もうしあげる -もうどうけん -もえる -もくし -もくてき -もくようび -もちろん -もどる -もらう -もんく -もんだい -やおや -やける -やさい -やさしい -やすい -やすたろう -やすみ -やせる -やそう -やたい -やちん -やっと -やっぱり -やぶる -やめる -ややこしい -やよい -やわらかい -ゆうき -ゆうびんきょく -ゆうべ -ゆうめい -ゆけつ -ゆしゅつ -ゆせん -ゆそう -ゆたか -ゆちゃく -ゆでる -ゆにゅう -ゆびわ -ゆらい -ゆれる -ようい -ようか -ようきゅう -ようじ -ようす -ようちえん -よかぜ -よかん -よきん -よくせい -よくぼう -よけい -よごれる -よさん -よしゅう -よそう -よそく -よっか -よてい -よどがわく -よねつ -よやく -よゆう -よろこぶ -よろしい -らいう -らくがき -らくご -らくさつ -らくだ -らしんばん -らせん -らぞく -らたい -らっか -られつ -りえき -りかい -りきさく -りきせつ -りくぐん -りくつ -りけん -りこう -りせい -りそう -りそく -りてん -りねん -りゆう -りゅうがく -りよう -りょうり -りょかん -りょくちゃ -りょこう -りりく -りれき -りろん -りんご -るいけい -るいさい -るいじ -るいせき -るすばん -るりがわら -れいかん -れいぎ -れいせい -れいぞうこ -れいとう -れいぼう -れきし -れきだい -れんあい -れんけい -れんこん -れんさい -れんしゅう -れんぞく -れんらく -ろうか -ろうご -ろうじん -ろうそく -ろくが -ろこつ -ろじうら -ろしゅつ -ろせん -ろてん -ろめん -ろれつ -ろんぎ -ろんぱ -ろんぶん -ろんり -わかす -わかめ -わかやま -わかれる -わしつ -わじまし -わすれもの -わらう -われる diff --git a/contrib/bip39/spanish.txt b/contrib/bip39/spanish.txt deleted file mode 100644 index fdbc23c73a..0000000000 --- a/contrib/bip39/spanish.txt +++ /dev/null @@ -1,2048 +0,0 @@ -ábaco -abdomen -abeja -abierto -abogado -abono -aborto -abrazo -abrir -abuelo -abuso -acabar -academia -acceso -acción -aceite -acelga -acento -aceptar -ácido -aclarar -acné -acoger -acoso -activo -acto -actriz -actuar -acudir -acuerdo -acusar -adicto -admitir -adoptar -adorno -aduana -adulto -aéreo -afectar -afición -afinar -afirmar -ágil -agitar -agonía -agosto -agotar -agregar -agrio -agua -agudo -águila -aguja -ahogo -ahorro -aire -aislar -ajedrez -ajeno -ajuste -alacrán -alambre -alarma -alba -álbum -alcalde -aldea -alegre -alejar -alerta -aleta -alfiler -alga -algodón -aliado -aliento -alivio -alma -almeja -almíbar -altar -alteza -altivo -alto -altura -alumno -alzar -amable -amante -amapola -amargo -amasar -ámbar -ámbito -ameno -amigo -amistad -amor -amparo -amplio -ancho -anciano -ancla -andar -andén -anemia -ángulo -anillo -ánimo -anís -anotar -antena -antiguo -antojo -anual -anular -anuncio -añadir -añejo -año -apagar -aparato -apetito -apio -aplicar -apodo -aporte -apoyo -aprender -aprobar -apuesta -apuro -arado -araña -arar -árbitro -árbol -arbusto -archivo -arco -arder -ardilla -arduo -área -árido -aries -armonía -arnés -aroma -arpa -arpón -arreglo -arroz -arruga -arte -artista -asa -asado -asalto -ascenso -asegurar -aseo -asesor -asiento -asilo -asistir -asno -asombro -áspero -astilla -astro -astuto -asumir -asunto -atajo -ataque -atar -atento -ateo -ático -atleta -átomo -atraer -atroz -atún -audaz -audio -auge -aula -aumento -ausente -autor -aval -avance -avaro -ave -avellana -avena -avestruz -avión -aviso -ayer -ayuda -ayuno -azafrán -azar -azote -azúcar -azufre -azul -baba -babor -bache -bahía -baile -bajar -balanza -balcón -balde -bambú -banco -banda -baño -barba -barco -barniz -barro -báscula -bastón -basura -batalla -batería -batir -batuta -baúl -bazar -bebé -bebida -bello -besar -beso -bestia -bicho -bien -bingo -blanco -bloque -blusa -boa -bobina -bobo -boca -bocina -boda -bodega -boina -bola -bolero -bolsa -bomba -bondad -bonito -bono -bonsái -borde -borrar -bosque -bote -botín -bóveda -bozal -bravo -brazo -brecha -breve -brillo -brinco -brisa -broca -broma -bronce -brote -bruja -brusco -bruto -buceo -bucle -bueno -buey -bufanda -bufón -búho -buitre -bulto -burbuja -burla -burro -buscar -butaca -buzón -caballo -cabeza -cabina -cabra -cacao -cadáver -cadena -caer -café -caída -caimán -caja -cajón -cal -calamar -calcio -caldo -calidad -calle -calma -calor -calvo -cama -cambio -camello -camino -campo -cáncer -candil -canela -canguro -canica -canto -caña -cañón -caoba -caos -capaz -capitán -capote -captar -capucha -cara -carbón -cárcel -careta -carga -cariño -carne -carpeta -carro -carta -casa -casco -casero -caspa -castor -catorce -catre -caudal -causa -cazo -cebolla -ceder -cedro -celda -célebre -celoso -célula -cemento -ceniza -centro -cerca -cerdo -cereza -cero -cerrar -certeza -césped -cetro -chacal -chaleco -champú -chancla -chapa -charla -chico -chiste -chivo -choque -choza -chuleta -chupar -ciclón -ciego -cielo -cien -cierto -cifra -cigarro -cima -cinco -cine -cinta -ciprés -circo -ciruela -cisne -cita -ciudad -clamor -clan -claro -clase -clave -cliente -clima -clínica -cobre -cocción -cochino -cocina -coco -código -codo -cofre -coger -cohete -cojín -cojo -cola -colcha -colegio -colgar -colina -collar -colmo -columna -combate -comer -comida -cómodo -compra -conde -conejo -conga -conocer -consejo -contar -copa -copia -corazón -corbata -corcho -cordón -corona -correr -coser -cosmos -costa -cráneo -cráter -crear -crecer -creído -crema -cría -crimen -cripta -crisis -cromo -crónica -croqueta -crudo -cruz -cuadro -cuarto -cuatro -cubo -cubrir -cuchara -cuello -cuento -cuerda -cuesta -cueva -cuidar -culebra -culpa -culto -cumbre -cumplir -cuna -cuneta -cuota -cupón -cúpula -curar -curioso -curso -curva -cutis -dama -danza -dar -dardo -dátil -deber -débil -década -decir -dedo -defensa -definir -dejar -delfín -delgado -delito -demora -denso -dental -deporte -derecho -derrota -desayuno -deseo -desfile -desnudo -destino -desvío -detalle -detener -deuda -día -diablo -diadema -diamante -diana -diario -dibujo -dictar -diente -dieta -diez -difícil -digno -dilema -diluir -dinero -directo -dirigir -disco -diseño -disfraz -diva -divino -doble -doce -dolor -domingo -don -donar -dorado -dormir -dorso -dos -dosis -dragón -droga -ducha -duda -duelo -dueño -dulce -dúo -duque -durar -dureza -duro -ébano -ebrio -echar -eco -ecuador -edad -edición -edificio -editor -educar -efecto -eficaz -eje -ejemplo -elefante -elegir -elemento -elevar -elipse -élite -elixir -elogio -eludir -embudo -emitir -emoción -empate -empeño -empleo -empresa -enano -encargo -enchufe -encía -enemigo -enero -enfado -enfermo -engaño -enigma -enlace -enorme -enredo -ensayo -enseñar -entero -entrar -envase -envío -época -equipo -erizo -escala -escena -escolar -escribir -escudo -esencia -esfera -esfuerzo -espada -espejo -espía -esposa -espuma -esquí -estar -este -estilo -estufa -etapa -eterno -ética -etnia -evadir -evaluar -evento -evitar -exacto -examen -exceso -excusa -exento -exigir -exilio -existir -éxito -experto -explicar -exponer -extremo -fábrica -fábula -fachada -fácil -factor -faena -faja -falda -fallo -falso -faltar -fama -familia -famoso -faraón -farmacia -farol -farsa -fase -fatiga -fauna -favor -fax -febrero -fecha -feliz -feo -feria -feroz -fértil -fervor -festín -fiable -fianza -fiar -fibra -ficción -ficha -fideo -fiebre -fiel -fiera -fiesta -figura -fijar -fijo -fila -filete -filial -filtro -fin -finca -fingir -finito -firma -flaco -flauta -flecha -flor -flota -fluir -flujo -flúor -fobia -foca -fogata -fogón -folio -folleto -fondo -forma -forro -fortuna -forzar -fosa -foto -fracaso -frágil -franja -frase -fraude -freír -freno -fresa -frío -frito -fruta -fuego -fuente -fuerza -fuga -fumar -función -funda -furgón -furia -fusil -fútbol -futuro -gacela -gafas -gaita -gajo -gala -galería -gallo -gamba -ganar -gancho -ganga -ganso -garaje -garza -gasolina -gastar -gato -gavilán -gemelo -gemir -gen -género -genio -gente -geranio -gerente -germen -gesto -gigante -gimnasio -girar -giro -glaciar -globo -gloria -gol -golfo -goloso -golpe -goma -gordo -gorila -gorra -gota -goteo -gozar -grada -gráfico -grano -grasa -gratis -grave -grieta -grillo -gripe -gris -grito -grosor -grúa -grueso -grumo -grupo -guante -guapo -guardia -guerra -guía -guiño -guion -guiso -guitarra -gusano -gustar -haber -hábil -hablar -hacer -hacha -hada -hallar -hamaca -harina -haz -hazaña -hebilla -hebra -hecho -helado -helio -hembra -herir -hermano -héroe -hervir -hielo -hierro -hígado -higiene -hijo -himno -historia -hocico -hogar -hoguera -hoja -hombre -hongo -honor -honra -hora -hormiga -horno -hostil -hoyo -hueco -huelga -huerta -hueso -huevo -huida -huir -humano -húmedo -humilde -humo -hundir -huracán -hurto -icono -ideal -idioma -ídolo -iglesia -iglú -igual -ilegal -ilusión -imagen -imán -imitar -impar -imperio -imponer -impulso -incapaz -índice -inerte -infiel -informe -ingenio -inicio -inmenso -inmune -innato -insecto -instante -interés -íntimo -intuir -inútil -invierno -ira -iris -ironía -isla -islote -jabalí -jabón -jamón -jarabe -jardín -jarra -jaula -jazmín -jefe -jeringa -jinete -jornada -joroba -joven -joya -juerga -jueves -juez -jugador -jugo -juguete -juicio -junco -jungla -junio -juntar -júpiter -jurar -justo -juvenil -juzgar -kilo -koala -labio -lacio -lacra -lado -ladrón -lagarto -lágrima -laguna -laico -lamer -lámina -lámpara -lana -lancha -langosta -lanza -lápiz -largo -larva -lástima -lata -látex -latir -laurel -lavar -lazo -leal -lección -leche -lector -leer -legión -legumbre -lejano -lengua -lento -leña -león -leopardo -lesión -letal -letra -leve -leyenda -libertad -libro -licor -líder -lidiar -lienzo -liga -ligero -lima -límite -limón -limpio -lince -lindo -línea -lingote -lino -linterna -líquido -liso -lista -litera -litio -litro -llaga -llama -llanto -llave -llegar -llenar -llevar -llorar -llover -lluvia -lobo -loción -loco -locura -lógica -logro -lombriz -lomo -lonja -lote -lucha -lucir -lugar -lujo -luna -lunes -lupa -lustro -luto -luz -maceta -macho -madera -madre -maduro -maestro -mafia -magia -mago -maíz -maldad -maleta -malla -malo -mamá -mambo -mamut -manco -mando -manejar -manga -maniquí -manjar -mano -manso -manta -mañana -mapa -máquina -mar -marco -marea -marfil -margen -marido -mármol -marrón -martes -marzo -masa -máscara -masivo -matar -materia -matiz -matriz -máximo -mayor -mazorca -mecha -medalla -medio -médula -mejilla -mejor -melena -melón -memoria -menor -mensaje -mente -menú -mercado -merengue -mérito -mes -mesón -meta -meter -método -metro -mezcla -miedo -miel -miembro -miga -mil -milagro -militar -millón -mimo -mina -minero -mínimo -minuto -miope -mirar -misa -miseria -misil -mismo -mitad -mito -mochila -moción -moda -modelo -moho -mojar -molde -moler -molino -momento -momia -monarca -moneda -monja -monto -moño -morada -morder -moreno -morir -morro -morsa -mortal -mosca -mostrar -motivo -mover -móvil -mozo -mucho -mudar -mueble -muela -muerte -muestra -mugre -mujer -mula -muleta -multa -mundo -muñeca -mural -muro -músculo -museo -musgo -música -muslo -nácar -nación -nadar -naipe -naranja -nariz -narrar -nasal -natal -nativo -natural -náusea -naval -nave -navidad -necio -néctar -negar -negocio -negro -neón -nervio -neto -neutro -nevar -nevera -nicho -nido -niebla -nieto -niñez -niño -nítido -nivel -nobleza -noche -nómina -noria -norma -norte -nota -noticia -novato -novela -novio -nube -nuca -núcleo -nudillo -nudo -nuera -nueve -nuez -nulo -número -nutria -oasis -obeso -obispo -objeto -obra -obrero -observar -obtener -obvio -oca -ocaso -océano -ochenta -ocho -ocio -ocre -octavo -octubre -oculto -ocupar -ocurrir -odiar -odio -odisea -oeste -ofensa -oferta -oficio -ofrecer -ogro -oído -oír -ojo -ola -oleada -olfato -olivo -olla -olmo -olor -olvido -ombligo -onda -onza -opaco -opción -ópera -opinar -oponer -optar -óptica -opuesto -oración -orador -oral -órbita -orca -orden -oreja -órgano -orgía -orgullo -oriente -origen -orilla -oro -orquesta -oruga -osadía -oscuro -osezno -oso -ostra -otoño -otro -oveja -óvulo -óxido -oxígeno -oyente -ozono -pacto -padre -paella -página -pago -país -pájaro -palabra -palco -paleta -pálido -palma -paloma -palpar -pan -panal -pánico -pantera -pañuelo -papá -papel -papilla -paquete -parar -parcela -pared -parir -paro -párpado -parque -párrafo -parte -pasar -paseo -pasión -paso -pasta -pata -patio -patria -pausa -pauta -pavo -payaso -peatón -pecado -pecera -pecho -pedal -pedir -pegar -peine -pelar -peldaño -pelea -peligro -pellejo -pelo -peluca -pena -pensar -peñón -peón -peor -pepino -pequeño -pera -percha -perder -pereza -perfil -perico -perla -permiso -perro -persona -pesa -pesca -pésimo -pestaña -pétalo -petróleo -pez -pezuña -picar -pichón -pie -piedra -pierna -pieza -pijama -pilar -piloto -pimienta -pino -pintor -pinza -piña -piojo -pipa -pirata -pisar -piscina -piso -pista -pitón -pizca -placa -plan -plata -playa -plaza -pleito -pleno -plomo -pluma -plural -pobre -poco -poder -podio -poema -poesía -poeta -polen -policía -pollo -polvo -pomada -pomelo -pomo -pompa -poner -porción -portal -posada -poseer -posible -poste -potencia -potro -pozo -prado -precoz -pregunta -premio -prensa -preso -previo -primo -príncipe -prisión -privar -proa -probar -proceso -producto -proeza -profesor -programa -prole -promesa -pronto -propio -próximo -prueba -público -puchero -pudor -pueblo -puerta -puesto -pulga -pulir -pulmón -pulpo -pulso -puma -punto -puñal -puño -pupa -pupila -puré -quedar -queja -quemar -querer -queso -quieto -química -quince -quitar -rábano -rabia -rabo -ración -radical -raíz -rama -rampa -rancho -rango -rapaz -rápido -rapto -rasgo -raspa -rato -rayo -raza -razón -reacción -realidad -rebaño -rebote -recaer -receta -rechazo -recoger -recreo -recto -recurso -red -redondo -reducir -reflejo -reforma -refrán -refugio -regalo -regir -regla -regreso -rehén -reino -reír -reja -relato -relevo -relieve -relleno -reloj -remar -remedio -remo -rencor -rendir -renta -reparto -repetir -reposo -reptil -res -rescate -resina -respeto -resto -resumen -retiro -retorno -retrato -reunir -revés -revista -rey -rezar -rico -riego -rienda -riesgo -rifa -rígido -rigor -rincón -riñón -río -riqueza -risa -ritmo -rito -rizo -roble -roce -rociar -rodar -rodeo -rodilla -roer -rojizo -rojo -romero -romper -ron -ronco -ronda -ropa -ropero -rosa -rosca -rostro -rotar -rubí -rubor -rudo -rueda -rugir -ruido -ruina -ruleta -rulo -rumbo -rumor -ruptura -ruta -rutina -sábado -saber -sabio -sable -sacar -sagaz -sagrado -sala -saldo -salero -salir -salmón -salón -salsa -salto -salud -salvar -samba -sanción -sandía -sanear -sangre -sanidad -sano -santo -sapo -saque -sardina -sartén -sastre -satán -sauna -saxofón -sección -seco -secreto -secta -sed -seguir -seis -sello -selva -semana -semilla -senda -sensor -señal -señor -separar -sepia -sequía -ser -serie -sermón -servir -sesenta -sesión -seta -setenta -severo -sexo -sexto -sidra -siesta -siete -siglo -signo -sílaba -silbar -silencio -silla -símbolo -simio -sirena -sistema -sitio -situar -sobre -socio -sodio -sol -solapa -soldado -soledad -sólido -soltar -solución -sombra -sondeo -sonido -sonoro -sonrisa -sopa -soplar -soporte -sordo -sorpresa -sorteo -sostén -sótano -suave -subir -suceso -sudor -suegra -suelo -sueño -suerte -sufrir -sujeto -sultán -sumar -superar -suplir -suponer -supremo -sur -surco -sureño -surgir -susto -sutil -tabaco -tabique -tabla -tabú -taco -tacto -tajo -talar -talco -talento -talla -talón -tamaño -tambor -tango -tanque -tapa -tapete -tapia -tapón -taquilla -tarde -tarea -tarifa -tarjeta -tarot -tarro -tarta -tatuaje -tauro -taza -tazón -teatro -techo -tecla -técnica -tejado -tejer -tejido -tela -teléfono -tema -temor -templo -tenaz -tender -tener -tenis -tenso -teoría -terapia -terco -término -ternura -terror -tesis -tesoro -testigo -tetera -texto -tez -tibio -tiburón -tiempo -tienda -tierra -tieso -tigre -tijera -tilde -timbre -tímido -timo -tinta -tío -típico -tipo -tira -tirón -titán -títere -título -tiza -toalla -tobillo -tocar -tocino -todo -toga -toldo -tomar -tono -tonto -topar -tope -toque -tórax -torero -tormenta -torneo -toro -torpedo -torre -torso -tortuga -tos -tosco -toser -tóxico -trabajo -tractor -traer -tráfico -trago -traje -tramo -trance -trato -trauma -trazar -trébol -tregua -treinta -tren -trepar -tres -tribu -trigo -tripa -triste -triunfo -trofeo -trompa -tronco -tropa -trote -trozo -truco -trueno -trufa -tubería -tubo -tuerto -tumba -tumor -túnel -túnica -turbina -turismo -turno -tutor -ubicar -úlcera -umbral -unidad -unir -universo -uno -untar -uña -urbano -urbe -urgente -urna -usar -usuario -útil -utopía -uva -vaca -vacío -vacuna -vagar -vago -vaina -vajilla -vale -válido -valle -valor -válvula -vampiro -vara -variar -varón -vaso -vecino -vector -vehículo -veinte -vejez -vela -velero -veloz -vena -vencer -venda -veneno -vengar -venir -venta -venus -ver -verano -verbo -verde -vereda -verja -verso -verter -vía -viaje -vibrar -vicio -víctima -vida -vídeo -vidrio -viejo -viernes -vigor -vil -villa -vinagre -vino -viñedo -violín -viral -virgo -virtud -visor -víspera -vista -vitamina -viudo -vivaz -vivero -vivir -vivo -volcán -volumen -volver -voraz -votar -voto -voz -vuelo -vulgar -yacer -yate -yegua -yema -yerno -yeso -yodo -yoga -yogur -zafiro -zanja -zapato -zarza -zona -zorro -zumo -zurdo diff --git a/contrib/bitrpc/bitrpc.py b/contrib/bitrpc/bitrpc.py deleted file mode 100644 index b02b299177..0000000000 --- a/contrib/bitrpc/bitrpc.py +++ /dev/null @@ -1,324 +0,0 @@ -from jsonrpc import ServiceProxy -import sys -import string - -# ===== BEGIN USER SETTINGS ===== -# if you do not set these you will be prompted for a password for every command -rpcuser = "" -rpcpass = "" -# ====== END USER SETTINGS ====== - - -if rpcpass == "": - access = ServiceProxy("http://127.0.0.1:8332") -else: - access = ServiceProxy("http://"+rpcuser+":"+rpcpass+"@127.0.0.1:8332") -cmd = sys.argv[1].lower() - -if cmd == "backupwallet": - try: - path = raw_input("Enter destination path/filename: ") - print access.backupwallet(path) - except: - print "\n---An error occurred---\n" - -elif cmd == "getaccount": - try: - addr = raw_input("Enter a Bitcoin address: ") - print access.getaccount(addr) - except: - print "\n---An error occurred---\n" - -elif cmd == "getaccountaddress": - try: - acct = raw_input("Enter an account name: ") - print access.getaccountaddress(acct) - except: - print "\n---An error occurred---\n" - -elif cmd == "getaddressesbyaccount": - try: - acct = raw_input("Enter an account name: ") - print access.getaddressesbyaccount(acct) - except: - print "\n---An error occurred---\n" - -elif cmd == "getbalance": - try: - acct = raw_input("Enter an account (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getbalance(acct, mc) - except: - print access.getbalance() - except: - print "\n---An error occurred---\n" - -elif cmd == "getblockbycount": - try: - height = raw_input("Height: ") - print access.getblockbycount(height) - except: - print "\n---An error occurred---\n" - -elif cmd == "getblockcount": - try: - print access.getblockcount() - except: - print "\n---An error occurred---\n" - -elif cmd == "getblocknumber": - try: - print access.getblocknumber() - except: - print "\n---An error occurred---\n" - -elif cmd == "getconnectioncount": - try: - print access.getconnectioncount() - except: - print "\n---An error occurred---\n" - -elif cmd == "getdifficulty": - try: - print access.getdifficulty() - except: - print "\n---An error occurred---\n" - -elif cmd == "getgenerate": - try: - print access.getgenerate() - except: - print "\n---An error occurred---\n" - -elif cmd == "gethashespersec": - try: - print access.gethashespersec() - except: - print "\n---An error occurred---\n" - -elif cmd == "getinfo": - try: - print access.getinfo() - except: - print "\n---An error occurred---\n" - -elif cmd == "getnewaddress": - try: - acct = raw_input("Enter an account name: ") - try: - print access.getnewaddress(acct) - except: - print access.getnewaddress() - except: - print "\n---An error occurred---\n" - -elif cmd == "getreceivedbyaccount": - try: - acct = raw_input("Enter an account (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getreceivedbyaccount(acct, mc) - except: - print access.getreceivedbyaccount() - except: - print "\n---An error occurred---\n" - -elif cmd == "getreceivedbyaddress": - try: - addr = raw_input("Enter a Bitcoin address (optional): ") - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.getreceivedbyaddress(addr, mc) - except: - print access.getreceivedbyaddress() - except: - print "\n---An error occurred---\n" - -elif cmd == "gettransaction": - try: - txid = raw_input("Enter a transaction ID: ") - print access.gettransaction(txid) - except: - print "\n---An error occurred---\n" - -elif cmd == "getwork": - try: - data = raw_input("Data (optional): ") - try: - print access.gettransaction(data) - except: - print access.gettransaction() - except: - print "\n---An error occurred---\n" - -elif cmd == "help": - try: - cmd = raw_input("Command (optional): ") - try: - print access.help(cmd) - except: - print access.help() - except: - print "\n---An error occurred---\n" - -elif cmd == "listaccounts": - try: - mc = raw_input("Minimum confirmations (optional): ") - try: - print access.listaccounts(mc) - except: - print access.listaccounts() - except: - print "\n---An error occurred---\n" - -elif cmd == "listreceivedbyaccount": - try: - mc = raw_input("Minimum confirmations (optional): ") - incemp = raw_input("Include empty? (true/false, optional): ") - try: - print access.listreceivedbyaccount(mc, incemp) - except: - print access.listreceivedbyaccount() - except: - print "\n---An error occurred---\n" - -elif cmd == "listreceivedbyaddress": - try: - mc = raw_input("Minimum confirmations (optional): ") - incemp = raw_input("Include empty? (true/false, optional): ") - try: - print access.listreceivedbyaddress(mc, incemp) - except: - print access.listreceivedbyaddress() - except: - print "\n---An error occurred---\n" - -elif cmd == "listtransactions": - try: - acct = raw_input("Account (optional): ") - count = raw_input("Number of transactions (optional): ") - frm = raw_input("Skip (optional):") - try: - print access.listtransactions(acct, count, frm) - except: - print access.listtransactions() - except: - print "\n---An error occurred---\n" - -elif cmd == "move": - try: - frm = raw_input("From: ") - to = raw_input("To: ") - amt = raw_input("Amount:") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - try: - print access.move(frm, to, amt, mc, comment) - except: - print access.move(frm, to, amt) - except: - print "\n---An error occurred---\n" - -elif cmd == "sendfrom": - try: - frm = raw_input("From: ") - to = raw_input("To: ") - amt = raw_input("Amount:") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - commentto = raw_input("Comment-to (optional): ") - try: - print access.sendfrom(frm, to, amt, mc, comment, commentto) - except: - print access.sendfrom(frm, to, amt) - except: - print "\n---An error occurred---\n" - -elif cmd == "sendmany": - try: - frm = raw_input("From: ") - to = raw_input("To (in format address1:amount1,address2:amount2,...): ") - mc = raw_input("Minimum confirmations (optional): ") - comment = raw_input("Comment (optional): ") - try: - print access.sendmany(frm,to,mc,comment) - except: - print access.sendmany(frm,to) - except: - print "\n---An error occurred---\n" - -elif cmd == "sendtoaddress": - try: - to = raw_input("To (in format address1:amount1,address2:amount2,...): ") - amt = raw_input("Amount:") - comment = raw_input("Comment (optional): ") - commentto = raw_input("Comment-to (optional): ") - try: - print access.sendtoaddress(to,amt,comment,commentto) - except: - print access.sendtoaddress(to,amt) - except: - print "\n---An error occurred---\n" - -elif cmd == "setaccount": - try: - addr = raw_input("Address: ") - acct = raw_input("Account:") - print access.setaccount(addr,acct) - except: - print "\n---An error occurred---\n" - -elif cmd == "setgenerate": - try: - gen= raw_input("Generate? (true/false): ") - cpus = raw_input("Max processors/cores (-1 for unlimited, optional):") - try: - print access.setgenerate(gen, cpus) - except: - print access.setgenerate(gen) - except: - print "\n---An error occurred---\n" - -elif cmd == "settxfee": - try: - amt = raw_input("Amount:") - print access.settxfee(amt) - except: - print "\n---An error occurred---\n" - -elif cmd == "stop": - try: - print access.stop() - except: - print "\n---An error occurred---\n" - -elif cmd == "validateaddress": - try: - addr = raw_input("Address: ") - print access.validateaddress(addr) - except: - print "\n---An error occurred---\n" - -elif cmd == "walletpassphrase": - try: - pwd = raw_input("Enter wallet passphrase: ") - access.walletpassphrase(pwd, 60) - print "\n---Wallet unlocked---\n" - except: - print "\n---An error occurred---\n" - -elif cmd == "walletpassphrasechange": - try: - pwd = raw_input("Enter old wallet passphrase: ") - pwd2 = raw_input("Enter new wallet passphrase: ") - access.walletpassphrasechange(pwd, pwd2) - print - print "\n---Passphrase changed---\n" - except: - print - print "\n---An error occurred---\n" - print - -else: - print "Command not found or not supported" \ No newline at end of file diff --git a/contrib/debian/bin/novacoin-qt b/contrib/debian/bin/novacoin-qt deleted file mode 100755 index b3bc973501..0000000000 --- a/contrib/debian/bin/novacoin-qt +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -set -e - -umask 077 - -basedir=~/.novacoin -dbfile="$basedir/DB_CONFIG" -cfgfile="$basedir/novacoin.conf" - -[ -e "$basedir" ] || mkdir "$basedir" - -# Novacoin does not clean up DB log files by default -[ -e "$dbfile" ] || echo 'set_flags DB_LOG_AUTOREMOVE' > "$dbfile" - -exec /usr/lib/novacoin/novacoin-qt "$@" diff --git a/contrib/debian/bin/novacoind b/contrib/debian/bin/novacoind deleted file mode 100755 index a4f3fb808b..0000000000 --- a/contrib/debian/bin/novacoind +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -set -e - -umask 077 - -basedir=~/.novacoin -cfgfile="$basedir/novacoin.conf" - -[ -e "$basedir" ] || mkdir "$basedir" - -[ -e "$cfgfile" ] || perl -le 'print"rpcpassword=",map{(a..z,A..Z,0..9)[rand 62]}0..9' > "$cfgfile" - -exec /usr/lib/novacoin/novacoind "$@" diff --git a/contrib/debian/changelog b/contrib/debian/changelog deleted file mode 100644 index 64ceac0046..0000000000 --- a/contrib/debian/changelog +++ /dev/null @@ -1,6 +0,0 @@ -novacoin (0.4.0~dfsg-1) unstable; urgency=low - - [ Balthazar ] - * Initial release. - - -- Balthazar Mon, 15 Apr 2013 22:15:22 +0100 diff --git a/contrib/debian/compat b/contrib/debian/compat deleted file mode 100644 index 7f8f011eb7..0000000000 --- a/contrib/debian/compat +++ /dev/null @@ -1 +0,0 @@ -7 diff --git a/contrib/debian/control b/contrib/debian/control deleted file mode 100644 index 44fa62c826..0000000000 --- a/contrib/debian/control +++ /dev/null @@ -1,59 +0,0 @@ -Source: novacoin -Section: utils -Priority: optional -Maintainer: Jonas Smedegaard -Uploaders: Micah Anderson -Build-Depends: debhelper, - devscripts, - bash-completion, - libboost-system-dev (>> 1.35) | libboost-system1.35-dev, - libdb4.8++-dev, - libssl-dev, - pkg-config, - libminiupnpc8-dev, - libboost-filesystem-dev (>> 1.35) | libboost-filesystem1.35-dev, - libboost-program-options-dev (>> 1.35) | libboost-program-options1.35-dev, - libboost-thread-dev (>> 1.35) | libboost-thread1.35-dev, - libboost-test-dev (>> 1.35) | libboost-test1.35-dev, - qt4-qmake, - libqt4-dev, - libqrencode-dev -Standards-Version: 3.9.2 -Homepage: http://www.novacoin.su/ -Vcs-Git: git://github.com/CryptoManiac/novacoin.git -Vcs-Browser: http://github.com/CryptoManiac/novacoin - -Package: novacoind -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: peer-to-peer network based digital currency - daemon - Novacoin is a free open source peer-to-peer electronic cash system that - is completely decentralized, without the need for a central server or - trusted parties. Users hold the crypto keys to their own money and - transact directly with each other, with the help of a P2P network to - check for double-spending. - . - By default connects to an IRC network to discover other peers. - . - Full transaction history is stored locally at each client. This - requires 2+ GB of space, slowly growing. - . - This package provides novacoind, a combined daemon and CLI tool to - interact with the daemon. - -Package: novacoin-qt -Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} -Description: peer-to-peer network based digital currency - Qt GUI - Novacoin is a free open source peer-to-peer electronic cash system that - is completely decentralized, without the need for a central server or - trusted parties. Users hold the crypto keys to their own money and - transact directly with each other, with the help of a P2P network to - check for double-spending. - . - By default connects to an IRC network to discover other peers. - . - Full transaction history is stored locally at each client. This - requires 2+ GB of space, slowly growing. - . - This package provides Novacoin-Qt, a GUI for Novacoin based on Qt. diff --git a/contrib/debian/copyright b/contrib/debian/copyright deleted file mode 100644 index b99604913c..0000000000 --- a/contrib/debian/copyright +++ /dev/null @@ -1,166 +0,0 @@ -Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=174 -Upstream-Name: Bitcoin -Upstream-Contact: Satoshi Nakamoto - irc://#bitcoin@freenode.net -Source: http://sourceforge.net/projects/bitcoin/files/ - https://github.com/bitcoin/bitcoin - -Files: * -Copyright: 2009-2012, Bitcoin Developers -License: Expat -Comment: The Bitcoin Developers encompasses the current developers listed on bitcoin.org, - as well as the numerous contributors to the project. - -Files: src/json/* -Copyright: 2007-2009, John W. Wilkinson -License: Expat - -Files: src/strlcpy.h -Copyright: 1998, Todd C. Miller -License: ISC - -Files: debian/* -Copyright: 2010-2011, Jonas Smedegaard - 2011, Matt Corallo -License: GPL-2+ - -Files: debian/manpages/* -Copyright: Micah Anderson -License: GPL-3+ - -Files: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png, - src/qt/res/src/*.svg -Copyright: Wladimir van der Laan -License: Expat - -Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, - src/qt/res/icons/history.png, src/qt/res/icons/key.png, - src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, - src/qt/res/icons/receive.png, src/qt/res/icons/send.png, - src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png -Copyright: David Vignoni (david@icon-king.com) - ICON KING - www.icon-king.com -License: LGPL -Comment: NUVOLA ICON THEME for KDE 3.x - Original icons: kaddressbook, klipper_dock, view-list-text, - key-password, encrypted/decrypted, go-home, go-down, - go-next, dialog-ok - Site: http://www.icon-king.com/projects/nuvola/ - -Files: src/qt/res/icons/connect*.png -Copyright: schollidesign -License: GPL-3+ -Comment: Icon Pack: Human-O2 - Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0 - -Files: src/qt/res/icons/transaction*.png -Copyright: md2k7 -License: Expat -Comment: Site: https://bitcointalk.org/index.php?topic=15276.0 - -Files: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png, - src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png, - src/qt/res/icons/add.png, src/qt/res/icons/edit.png, - src/qt/res/icons/remove.png -Copyright: http://www.everaldo.com -License: LGPL -Comment: Icon Pack: Crystal SVG - -Files: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png -Copyright: Bitboy (optimized for 16x16 by Wladimir van der Laan) -License: PUB-DOM -Comment: Site: https://bitcointalk.org/?topic=1756.0 - -Files: scripts/img/reload.xcf, src/qt/res/movies/update_spinner.mng -Copyright: Everaldo (Everaldo Coelho) -License: GPL-3+ -Comment: Icon Pack: Kids - Site: http://findicons.com/icon/17102/reload?id=17102 - -Files: src/qt/res/images/splash2.jpg -License: PUB-DOM -Copyright: Crobbo (forum) -Comment: Site: https://bitcointalk.org/index.php?topic=32273.0 - - -License: Expat - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - . - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -License: ISC - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - . - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR - BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES - OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. - -License: GPL-2+ - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - . - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. -Comment: - On Debian systems the GNU General Public License (GPL) version 2 is - located in '/usr/share/common-licenses/GPL-2'. - . - You should have received a copy of the GNU General Public License along - with this program. If not, see . - -License: GPL-3+ - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU General Public License, Version 3 or any - later version published by the Free Software Foundation. -Comment: - On Debian systems the GNU General Public License (GPL) version 3 is - located in '/usr/share/common-licenses/GPL-3'. - . - You should have received a copy of the GNU General Public License along - with this program. If not, see . - -License: LGPL - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - . - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -Comment: - On Debian systems the GNU Lesser General Public License (LGPL) is - located in '/usr/share/common-licenses/LGPL'. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -License: PUB-DOM - This work is in the public domain. diff --git a/contrib/debian/examples/novacoin.conf b/contrib/debian/examples/novacoin.conf deleted file mode 100644 index ed19aa00ff..0000000000 --- a/contrib/debian/examples/novacoin.conf +++ /dev/null @@ -1,81 +0,0 @@ -# novacoin.conf configuration file. Lines beginning with # are comments. - - -# Network-related settings: - -# Run on the test network instead of the real novacoin network. -#testnet=1 - -# Connect via a socks4 proxy -#proxy=127.0.0.1:9050 - -# Use as many addnode= settings as you like to connect to specific peers -#addnode=188.120.246.137:51737 - -# ... or use as many connect= settings as you like to connect ONLY -# to specific peers: -#connect=188.120.246.137:51737 - -# Do not use Internet Relay Chat (irc.lfnet.org #novacoin channel) to -# find other peers. -#noirc=1 - -# Maximum number of inbound+outbound connections. -#maxconnections= - - -# JSON-RPC options (for controlling a running process) - -# server=1 tells NovaCoin to accept JSON-RPC commands. -#server=1 - -# You must set rpcuser and rpcpassword to secure the JSON-RPC api -#rpcuser=Ulysseys -#rpcpassword=YourSuperGreatPasswordNumber_385593 - -# By default, only RPC connections from localhost are allowed. Specify -# as many rpcallowip= settings as you like to allow connections from -# other hosts (and you may use * as a wildcard character): -#rpcallowip=10.1.1.34 -#rpcallowip=192.168.1.* - -# Listen for RPC connections on this TCP port: -rpcport=8332 - -# You can use NovaCoin or novacoind to send commands to Bitcoin/bitcoindNovaCoin/novacoind -# running on another host using this option: -rpcconnect=127.0.0.1 - -# Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate -# with NovaCoin -server or novacoind -#rpcssl=1 - -# OpenSSL settings used when rpcssl=1 -rpcsslciphers=TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH -rpcsslcertificatechainfile=server.cert -rpcsslprivatekeyfile=server.pem - - -# Miscellaneous options - -# Set gen=1 to attempt to generate novacoins -gen=0 - -# Pre-generate this many public/private key pairs, so wallet backups will be valid for -# both prior transactions and several dozen future transactions. -keypool=100 - -# Pay an optional transaction fee every time you send novacoins. -paytxfee=0.01 - -# Allow direct connections for the 'pay via IP address' feature. -#allowreceivebyip=1 - - -# User interface options - -# Start NovaCoin minimized -#min=1 - -# Minimize to the system tray -#minimizetotray=1 diff --git a/contrib/debian/gbp.conf b/contrib/debian/gbp.conf deleted file mode 100644 index a7281f94b2..0000000000 --- a/contrib/debian/gbp.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Configuration file for git-buildpackage and friends - -[DEFAULT] -pristine-tar = True -sign-tags = True diff --git a/contrib/debian/manpages/novacoin.conf.5 b/contrib/debian/manpages/novacoin.conf.5 deleted file mode 100644 index 1901e16ee5..0000000000 --- a/contrib/debian/manpages/novacoin.conf.5 +++ /dev/null @@ -1,91 +0,0 @@ -.TH NOVACOIN.CONF "8" "April 2013" "novacoin.conf 3.19" -.SH NAME -novacoin.conf \- novacoin configuration file -.SH SYNOPSIS -All command-line options (except for '-datadir' and '-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file. -.TP -The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character. -.TP -The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, novacoind(1) will look for a file named novacoin.conf(5) in the novacoin data directory, but both the data directory and the configuration file path may be changed using the '-datadir' and '-conf' command-line arguments. -.SH LOCATION -novacoin.conf should be located in $HOME/.novacoin -.SH NETWORK-RELATED SETTINGS -.TP -.TP -\fBtestnet=\fR[\fI'1'\fR|\fI'0'\fR] -Enable or disable run on the test network instead of the real *novacoin* network. -.TP -\fBproxy=\fR\fI'127.0.0.1:9050'\fR -Connect via a socks4 proxy. -.TP -\fBaddnode=\fR\fI'10.0.0.2:8333'\fR -Use as many *addnode=* settings as you like to connect to specific peers. -.TP -\fBconnect=\fR\fI'10.0.0.1:8333'\fR -Use as many *connect=* settings as you like to connect ONLY to specific peers. -.TP -\fBnoirc=\fR[\fI'1'\fR|\fI'0'\fR] -Use or Do not use Internet Relay Chat (irc.lfnet.org #novacoin channel) to find other peers. -.TP -\fRmaxconnections=\fR\fI'value'\fR -Maximum number of inbound+outbound connections. -.SH JSON-RPC OPTIONS -.TP -\fBserver=\fR[\fI'1'\fR|\fI'0'\fR] -Tells *novacoin* to accept or not accept JSON-RPC commands. -.TP -\fBrpcuser=\fR\fI'username'\fR -You must set *rpcuser* to secure the JSON-RPC api. -.TP -\fBrpcpassword=\fR\fI'password'\fR -You must set *rpcpassword* to secure the JSON-RPC api. -.TP -\fBrpctimeout=\fR\fI'30'\fR -How many seconds *novacoin* will wait for a complete RPC HTTP request, after the HTTP connection is established. -.TP -\fBrpcallowip=\fR\fI'192.168.1.*'\fR -By default, only RPC connections from localhost are allowed. Specify as many *rpcallowip=* settings as you like to allow connections from other hosts (and you may use * as a wildcard character). -.TP -\fBrpcport=\fR\fI'8332'\fR -Listen for RPC connections on this TCP port. -.TP -\fBrpcconnect=\fR\fI'127.0.0.1'\fR -You can use *novacoin* or *novacoind(1)* to send commands to *novacoin*/*novacoind(1)* running on another host using this option. -.TP -\fBrpcssl=\fR\fI'1'\fR -Use Secure Sockets Layer (also known as TLS or HTTPS) to communicate with *novacoin* '-server' or *novacoind(1)*. Example of OpenSSL settings used when *rpcssl*='1': -.TP -\fBrpcsslciphers=\fR\fI'TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH'\fR -.TP -\fBrpcsslcertificatechainfile=\fR\fI'server.cert'\fR -.TP -\fBrpcsslprivatekeyfile=\fR\fI'server.pem'\fR -.TP -.SH MISCELLANEOUS OPTIONS -.TP -\fBgen=\fR[\fI'0'\fR|\fI'1'\fR] -Enable or disable attempt to generate novacoins. -.TP -\fBkeypool=\fR\fI'100'\fR -Pre-generate this many public/private key pairs, so wallet backups will be valid for both prior transactions and several dozen future transactions. -.TP -\fBpaytxfee=\fR\fI'0.00'\fR -Pay an optional transaction fee every time you send novacoins. Transactions with fees are more likely than free transactions to be included in generated blocks, so may be validated sooner. -.TP -\fBallowreceivebyip=\fR\fI'1'\fR -Allow direct connections for the 'pay via IP address' feature. -.TP -.SH USER INTERFACE OPTIONS -.TP -\fBmin=\fR[\fI'0'\fR|\fI'1'\fR] -Enable or disable start novacoind minimized. -.TP -\fBminimizetotray=\fR[\fI'0'\fR|\fI'1'\fR] -Enable or disable minimize to the system tray. -.SH "SEE ALSO" -novacoind(1) -.SH AUTHOR -This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/manpages/novacoind.1 b/contrib/debian/manpages/novacoind.1 deleted file mode 100644 index b8199c2102..0000000000 --- a/contrib/debian/manpages/novacoind.1 +++ /dev/null @@ -1,206 +0,0 @@ -.TH NOVACOIND "7" "April 2013" "novacoind 3.19" -.SH NAME -novacoind \- peer-to-peer network based digital currency -.SH SYNOPSIS -novacoin [options] [params] -.TP -novacoin [options] help - Get help for a command -.SH DESCRIPTION -This manual page documents the novacoind program. Novacoin is a peer-to-peer digital currency. Peer-to-peer (P2P) means that there is no central authority to issue new money or keep track of transactions. Instead, these tasks are managed collectively by the nodes of the network. Advantages: - -Novacoins can be sent easily through the Internet, without having to trust middlemen. Transactions are designed to be irreversible. Be safe from instability caused by fractional reserve banking and central banks. The limited inflation of the Novacoin system’s money supply is distributed evenly (by CPU power) throughout the network, not monopolized by banks. - -.SH OPTIONS -.TP -\fB\-conf=\fR -Specify configuration file (default: novacoin.conf) -.TP -\fB\-gen\fR -Generate coins -.TP -\fB\-gen\fR=\fI0\fR -Don't generate coins -.TP -\fB\-min\fR -Start minimized -.TP -\fB\-datadir=\fR -Specify data directory -.TP -\fB\-proxy=\fR -Connect through socks4 proxy -.TP -\fB\-addnode=\fR -Add a node to connect to -.TP -\fB\-connect=\fR -Connect only to the specified node -.TP -\fB\-paytxfee=\fR -Fee per KB to add to transactions you send -.TP -\fB\-server\fR -Accept command line and JSON\-RPC commands -.TP -\fB\-daemon\fR -Run in the background as a daemon and accept commands -.TP -\fB\-testnet\fR -Use the test network -.TP -\fB\-rpcuser=\fR -Username for JSON\-RPC connections -.TP -\fB\-rpcpassword=\fR -Password for JSON\-RPC connections -.TP -\fB\-rpcport=\fR -Listen for JSON\-RPC connections on -.TP -\fB\-rpcallowip=\fR -Allow JSON\-RPC connections from specified IP address -.TP -\fB\-rpcconnect=\fR -Send commands to node running on -.PP -SSL options: (see the Bitcoin Wiki for SSL setup instructions) -.TP -\fB\-rpcssl\fR=\fI1\fR -Use OpenSSL (https) for JSON\-RPC connections -.TP -\fB\-rpcsslcertificatchainfile=\fR -Server certificate file (default: server.cert) -.TP -\fB\-rpcsslprivatekeyfile=\fR -Server private key (default: server.pem) -.TP -\fB\-rpcsslciphers=\fR -Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH) -.TP -\-? -This help message -.SH COMMANDS -.TP -\fBbackupwallet 'destination'\fR -Safely copies *wallet.dat* to 'destination', which can be a directory or a path with filename. -.TP -\fBgetaccount 'novacoinaddress'\fR -Returns the account associated with the given address. -.TP -\fBsetaccount 'novacoinaddress' ['account']\fR -Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account']. -.TP -\fBgetaccountaddress 'account'\fR -Returns a new novacoin address for 'account'. -.TP -\fBgetaddressesbyaccount 'account'\fR -Returns the list of addresses associated with the given 'account'. -.TP -\fBgetbalance 'account'\fR -Returns the server's available balance, or the balance for 'account'. -.TP -\fBgetblockcount\fR -Returns the number of blocks in the longest block chain. -.TP -\fBgetblocknumber\fR -Returns the block number of the latest block in the longest block chain. -.TP -\fBgetconnectioncount\fR -Returns the number of connections to other nodes. -.TP -\fBgetdifficulty\fR -Returns the proof-of-work difficulty as a multiple of the minimum difficulty. -.TP -\fBgetgenerate\fR -Returns boolean true if server is trying to generate novacoins, false otherwise. -.TP -\fBsetgenerate 'generate' ['genproclimit']\fR -Generation is limited to ['genproclimit'] processors, -1 is unlimited. -.TP -\fBgethashespersec\fR -Returns a recent hashes per second performance measurement while generating. -.TP -\fBgetinfo\fR -Returns an object containing server information. -.TP -\fBgetnewaddress 'account'\fR -Returns a new novacoin address for receiving payments. If 'account' is specified (recommended), it is added to the address book so payments received with the address will be credited to 'account'. -.TP -\fBgetreceivedbyaccount 'account' ['minconf=1']\fR -Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations. -.TP -\fBgetreceivedbyaddress 'novacoinaddress' ['minconf=1']\fR -Returns the total amount received by 'novacoinaddress' in transactions with at least ['minconf'] confirmations. -.TP -\fBgettransaction 'txid'\fR -Returns information about a specific transaction, given hexadecimal transaction ID. -.TP -\fBgetwork 'data'\fR -If 'data' is specified, tries to solve the block and returns true if it was successful. If 'data' is not specified, returns formatted hash 'data' to work on: - - "midstate" : precomputed hash state after hashing the first half of the data. - "data" : block data. - "hash1" : formatted hash buffer for second hash. - "target" : little endian hash target. -.TP -\fBhelp 'command'\fR -List commands, or get help for a command. -.TP -\fBlistaccounts ['minconf=1']\fR -List accounts and their current balances. -.TP -\fBlistreceivedbyaccount ['minconf=1'] ['includeempty=false']\fR -['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing: - - "account" : the account of the receiving address. - "amount" : total amount received by the address. - "confirmations" : number of confirmations of the most recent transaction included. -.TP -\fBlistreceivedbyaddress ['minconf=1'] ['includeempty=false']\fR -['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing: - - "address" : receiving address. - "account" : the account of the receiving address. - "amount" : total amount received by the address. - "confirmations" : number of confirmations of the most recent transaction included. -.TP -\fBlisttransactions 'account' ['count=10']\fR -Returns a list of the last ['count'] transactions for 'account' - for all accounts if 'account' is not specified or is "*". Each entry in the list may contain: - - "category" : will be generate, send, receive, or move. - "amount" : amount of transaction. - "fee" : Fee (if any) paid (only for send transactions). - "confirmations" : number of confirmations (only for generate/send/receive). - "txid" : transaction ID (only for generate/send/receive). - "otheraccount" : account funds were moved to or from (only for move). - "message" : message associated with transaction (only for send). - "to" : message-to associated with transaction (only for send). -.TP -\fBmove <'fromaccount'> <'toaccount'> <'amount'> ['minconf=1'] ['comment']\fR -Moves funds between accounts. -.TP -\fBsendfrom* <'account'> <'novacoinaddress'> <'amount'> ['minconf=1'] ['comment'] ['comment-to']\fR -Sends amount from account's balance to 'novacoinaddress'. This method will fail if there is less than amount novacoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success. -.TP -\fBsendtoaddress 'novacoinaddress' 'amount' ['comment'] ['comment-to']\fR -Sends amount from the server's available balance to 'novacoinaddress'. amount is a real and is rounded to the nearest 0.01. Returns transaction id on success. -.TP -\fBstop\fR -Stops the novacoin server. -.TP -\fBvalidateaddress 'novacoinaddress'\fR -Checks that 'novacoinaddress' looks like a proper novacoin address. Returns an object containing: - - "isvalid" : true or false. - "ismine" : true if the address is in the server's wallet. - "address" : novacoinaddress. - - *note: ismine and address are only returned if the address is valid. - -.SH "SEE ALSO" -novacoin.conf(5) -.SH AUTHOR -This manual page was written by Micah Anderson for the Debian system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. - -On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. - diff --git a/contrib/debian/novacoin-qt.desktop b/contrib/debian/novacoin-qt.desktop deleted file mode 100644 index a299232d25..0000000000 --- a/contrib/debian/novacoin-qt.desktop +++ /dev/null @@ -1,12 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=NovaCoin -Comment=NovaCoin P2P Cryptocurrency -Comment[fr]=NovaCoin, monnaie virtuelle cryptographique pair à pair -Comment[tr]=NovaCoin, eşten eşe kriptografik sanal para birimi -Exec=/usr/bin/novacoin-qt -Terminal=false -Type=Application -Icon=/usr/share/pixmaps/bitcoin80.xpm -MimeType=x-scheme-handler/novacoin; -Categories=Office; diff --git a/contrib/debian/novacoin-qt.install b/contrib/debian/novacoin-qt.install deleted file mode 100644 index 403fb4e2c4..0000000000 --- a/contrib/debian/novacoin-qt.install +++ /dev/null @@ -1,5 +0,0 @@ -novacoin-qt usr/bin -share/pixmaps/bitcoin32.xpm usr/share/pixmaps -share/pixmaps/bitcoin80.xpm usr/share/pixmaps -debian/novacoin-qt.desktop usr/share/applications -debian/novacoin-qt.protocol usr/share/kde4/services/ diff --git a/contrib/debian/novacoin-qt.lintian-overrides b/contrib/debian/novacoin-qt.lintian-overrides deleted file mode 100644 index 3e159d38fd..0000000000 --- a/contrib/debian/novacoin-qt.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -# Linked code is Expat - only Debian packaging is GPL-2+ -novacoin-qt: possible-gpl-code-linked-with-openssl diff --git a/contrib/debian/novacoin-qt.protocol b/contrib/debian/novacoin-qt.protocol deleted file mode 100644 index 29a45469f4..0000000000 --- a/contrib/debian/novacoin-qt.protocol +++ /dev/null @@ -1,11 +0,0 @@ -[Protocol] -exec=novacoin-qt '%u' -protocol=novacoin -input=none -output=none -helper=true -listing= -reading=false -writing=false -makedir=false -deleting=false diff --git a/contrib/debian/novacoind.examples b/contrib/debian/novacoind.examples deleted file mode 100644 index 3728af9dd7..0000000000 --- a/contrib/debian/novacoind.examples +++ /dev/null @@ -1 +0,0 @@ -debian/examples/novacoin.conf diff --git a/contrib/debian/novacoind.install b/contrib/debian/novacoind.install deleted file mode 100644 index b44acca382..0000000000 --- a/contrib/debian/novacoind.install +++ /dev/null @@ -1,2 +0,0 @@ -debian/bin/novacoind usr/bin -src/novacoind usr/lib/novacoin diff --git a/contrib/debian/novacoind.lintian-overrides b/contrib/debian/novacoind.lintian-overrides deleted file mode 100644 index e44a58f992..0000000000 --- a/contrib/debian/novacoind.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -# Linked code is Expat - only Debian packaging is GPL-2+ -novacoind: possible-gpl-code-linked-with-openssl diff --git a/contrib/debian/novacoind.manpages b/contrib/debian/novacoind.manpages deleted file mode 100644 index 15116c8db6..0000000000 --- a/contrib/debian/novacoind.manpages +++ /dev/null @@ -1,2 +0,0 @@ -debian/manpages/novacoind.1 -debian/manpages/novacoin.conf.5 diff --git a/contrib/debian/patches/README b/contrib/debian/patches/README deleted file mode 100644 index 80c1584376..0000000000 --- a/contrib/debian/patches/README +++ /dev/null @@ -1,3 +0,0 @@ -0xxx: Grabbed from upstream development. -1xxx: Possibly relevant for upstream adoption. -2xxx: Only relevant for official Debian release. diff --git a/contrib/debian/patches/series b/contrib/debian/patches/series deleted file mode 100644 index 8b13789179..0000000000 --- a/contrib/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ - diff --git a/contrib/debian/rules b/contrib/debian/rules deleted file mode 100755 index 239dcf21bf..0000000000 --- a/contrib/debian/rules +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/make -f -# -*- mode: makefile; coding: utf-8 -*- - -#DEB_MAKE_CHECK_TARGET = test_bitcoin -#build/bitcoind:: -# $(if $(filter nocheck,$(DEB_BUILD_OPTIONS)),,src/test_bitcoin) - -DEB_INSTALL_EXAMPLES_novacoind += debian/examples/* -DEB_INSTALL_MANPAGES_novacoind += debian/manpages/* - -%: - dh --with bash-completion $@ - -override_dh_auto_build: - cd src; $(MAKE) -f makefile.unix novacoind - $(MAKE) - -override_dh_auto_clean: - if [ -f Makefile ]; then $(MAKE) clean; else rm -rf build/; rm -f novacoin-qt; fi - cd src; $(MAKE) -f makefile.unix clean - -override_dh_auto_configure: - qmake novacoin-qt.pro USE_QRCODE=1 - -override_dh_auto_test: - cd src; $(MAKE) -f makefile.unix test_novacoin - src/test_novacoin - -# Ensure wrapper is set executable -binary-post-install/novacoind: - chmod +x $(cdbs_curdestdir)usr/bin/novacoind -binary-post-install/novacoin-qt: - chmod +x $(cdbs_curdestdir)usr/bin/novacoin-qt diff --git a/contrib/debian/source/format b/contrib/debian/source/format deleted file mode 100644 index 163aaf8d82..0000000000 --- a/contrib/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/contrib/debian/watch b/contrib/debian/watch deleted file mode 100644 index 5da4e007a7..0000000000 --- a/contrib/debian/watch +++ /dev/null @@ -1,4 +0,0 @@ -# Run the "uscan" command to check for upstream updates and more. -version=4 -opts=uversionmangle=s/(\d)(alpha|beta|rc)/$1~$2/,dversionmangle=s/~dfsg\d*// \ - http://githubredir.debian.net/github/CryptoManiac/novacoin v(.*).tar.gz diff --git a/contrib/gitian-descriptors/README b/contrib/gitian-descriptors/README deleted file mode 100644 index 9407d137c7..0000000000 --- a/contrib/gitian-descriptors/README +++ /dev/null @@ -1,233 +0,0 @@ -Download a 64bit debian netinstall iso from : http://cdimage.debian.org/debian-cd/ -I used debian-8.1.0-amd64-netinst.iso - - -Follow this guide part way: -https://github.com/bitcoin/bitcoin/blob/master/doc/gitian-building.md#setting-up-debian-for-gitian-building -( up to cloning gitian-builder ) -Or follow these text only instructions: -Create a new VirtualBox VM - -Name: gitianbuild -Type: Linux (64bit) -Version: Debian - -Memory: 1400MB or more -Hard Drive: Create a virtual hard drive now -Hard drive file type: VDI ( Virtualbox disk image ) -Storage on physical hard drive : Dynamically allocated -File location and size: 40GB (20GB should work) - - - -After creating the VM, we need to configure it. - - Click the Settings button, then go to the Network tab. Adapter 1 should be attached to NAT - - - - Click Advanced, then Port Forwarding. We want to set up a port through which we can reach the VM to get files in and out. - Create a new rule by clicking the plus icon. - - Set up the new rule the following way: - Name: SSH - Protocol: TCP - Leave Host IP empty - Host Port: 22222 - Leave Guest IP empty - Guest Port: 22 - - Click Ok twice to save. - -Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso. - -Choose the non-graphical installer. We do not need the graphical environment; it will only increase installation time and disk usage. -Choose locale and keyboard settings (doesn't matter, you can just go with the defaults or select your own information) -The VM will detect network settings using DHCP, this should all proceed automatically - Configure the network: - System name debian. - Leave domain name empty. - -Choose a root password and enter it twice (remember it for later) - -Name the new user debian (the full name doesn't matter, you can leave it empty) -Choose a user password and enter it twice (remember it for later) - -The installer will set up the clock using a time server; this process should be automatic -Set up the clock: choose a time zone (depends on the locale settings that you picked earlier; specifics don't matter) - -Disk setup - Partitioning method: Guided - Use the entire disk - -Select disk to partition: SCSI1 (0,0,0) -Partitioning scheme: All files in one partition -Finish partitioning and write changes to disk -> Yes - - -The base system will be installed, this will take a minute or so - Choose a mirror (any will do - preferably one that is close to you and you should get the best download speeds) - -Enter proxy information (unless you are on an intranet, you can leave this empty) - - -Wait a bit while 'Select and install software' runs -Participate in popularity contest -> No - Choose software to install. We need just the base system. Make sure only 'SSH server' and 'Standard System Utilities' are checked. Uncheck 'Debian Desktop Environment' and 'Print Server' - - -Install the GRUB boot loader to the master boot record? -> Yes - - -Installation Complete -> Continue -After installation, the VM will reboot and you will have a working Debian VM. - -Congratulations! - - -On your debian virtual machine log in as root and run the following commands to get the show on the road. - -Install base packages: -# apt-get install git ruby sudo apt-cacher-ng qemu-utils debootstrap lxc python-cheetah parted kpartx bridge-utils -Add the debian user to the superusers list: -# adduser debian sudo - -When you get a colorful screen with a question about the 'LXC directory', just go with the default (/var/lib/lxc). -Then set up LXC and the rest with the following, which is a complex jumble of settings and workarounds: - -Add the following to a script and execute it: - -# make sure the build script can exectute it without providing a password -echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-start" > /etc/sudoers.d/gitian-lxc -# add cgroup for LXC -echo "cgroup /sys/fs/cgroup cgroup defaults 0 0" >> /etc/fstab -# make /etc/rc.local script that sets up bridge between guest and host -echo '#!/bin/sh -e' > /etc/rc.local -echo 'brctl addbr br0' >> /etc/rc.local -echo 'ifconfig br0 10.0.3.2/24 up' >> /etc/rc.local -echo 'exit 0' >> /etc/rc.local -# make sure that USE_LXC is always set when logging in as debian, -# and configure LXC IP addresses -echo 'export USE_LXC=1' >> /home/debian/.profile -echo 'export GITIAN_HOST_IP=10.0.3.2' >> /home/debian/.profile -echo 'export LXC_GUEST_IP=10.0.3.5' >> /home/debian/.profile - - -reboot - -The debian box will be rebooted and our setup should be complete - -************************ THIS IS WHERE YOU CAN STOP USING THE LINKED GUIDE ******************************* - - -ssh debian@localhost -p 22222 - -git clone https://github.com/devrandom/gitian-builder.git -git clone https://github.com/SDCDev/shadowcoin - -cd gitian-builder - -May be necessary to edit bin/make-base-vm - add sudo before mkfs. - -./bin/make-base-vm --lxc --arch amd64 --suite trusty -./bin/make-base-vm --lxc --arch i386 --suite trusty - -mkdir inputs; -cd inputs; -wget http://liquidtelecom.dl.sourceforge.net/project/flex/flex-2.5.38.tar.gz; -wget http://download.icu-project.org/files/icu4c/55.1/icu4c-55_1-src.tgz; -wget http://wtogami.fedorapeople.org/boost-mingw-gas-cross-compile-2013-03-03.patch; -wget http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.9.20151008.tar.gz -Ominiupnpc-1.9.20151008.tar.gz; -wget http://www.openssl.org/source/openssl-1.0.2d.tar.gz; -wget http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz; -wget http://download.qt.io/official_releases/qt/5.5/5.5.0/single/qt-everywhere-opensource-src-5.5.0.tar.xz -wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.bz2/download -Oboost_1_55_0.tar.bz2; - -Mirror - http://mindstalk.net/host/boost-mingw-gas-cross-compile-2013-03-03.patch - - -$ cd ..; -$ LXC_EXECUTE=lxc-execute; PATH="$(pwd)/libexec/:$PATH"; - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/boost-linux.yml -$ mv build/out/boost-*.zip inputs/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/deps-linux.yml -$ mv build/out/shadow-deps-*.zip inputs/ - -$ ./bin/gbuild --commit shadowcoin=HEAD ../shadowcoin/contrib/gitian-descriptors/gitian-linux.yml -$ mkdir -p ../compiled/linux -$ mv build/out/* ../compiled/linux/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/boost-win.yml -$ mv build/out/boost-*.zip inputs/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/deps-win.yml -$ mv build/out/shadow-deps-*.zip inputs/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/qt-win.yml -$ mv build/out/qt-win*.zip inputs/ - -$ ./bin/gbuild --commit shadowcoin=HEAD ../shadowcoin/contrib/gitian-descriptors/gitian-win.yml -$ mkdir -p ../compiled/win -$ mv build/out/* ../compiled/win/ - -$ ./bin/gbuild --commit osxcross=master,libdmg-hfsplus=master ../shadowcoin/contrib/gitian-descriptors/osxcross.yml -$ mv build/out/osxcross.tar.xz inputs/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/deps-osx.yml -$ mv build/out/shadow-deps-osx-gitian inputs/ - -$ ./bin/gbuild ../shadowcoin/contrib/gitian-descriptors/qt-osx.yml -$ mv build/out/qt-osx*.tar.xz inputs/ - -$ ./bin/gbuild --commit shadowcoin=HEAD ../shadowcoin/contrib/gitian-descriptors/gitian-osx.yml -$ mkdir -p ../compiled/osx -$ mv build/out/* ../compiled/osx/ - -Notes: - To check the progress of the script: - login to the vm on a new terminal (ssh debian@localhost -p 22222) - cd gitian-builder - tail -f var/install.log - or - tail -f var/build.log - - - - - - - - -Gavin's notes on getting gitian builds up and running: - -You need the right hardware: you need a 64-bit-capable CPU with hardware virtualization support (Intel VT-x or AMD-V). Not all modern CPUs support hardware virtualization. - -You probably need to enable hardware virtualization in your machine's BIOS. - -You need to be running a recent version of 64-bit-Ubuntu, and you need to install several prerequisites: - sudo apt-get install apache2 git apt-cacher-ng python-vm-builder qemu-kvm - -Sanity checks: - sudo service apt-cacher-ng status # Should return apt-cacher-ng is running - ls -l /dev/kvm # Should show a /dev/kvm device - -Once you've got the right hardware and software: - - git clone git://github.com/bitcoin/bitcoin.git - git clone git://github.com/devrandom/gitian-builder.git - mkdir gitian-builder/inputs - wget 'http://miniupnp.tuxfamily.org/files/download.php?file=miniupnpc-1.6.tar.gz' -O gitian-builder/inputs/miniupnpc-1.6.tar.gz - - cd gitian-builder - bin/make-base-vm --arch i386 - bin/make-base-vm --arch amd64 - cd .. - - # To build - cd bitcoin - git pull - cd ../gitian-builder - git pull - ./bin/gbuild --commit bitcoin=HEAD ../bitcoin/contrib/gitian.yml - diff --git a/contrib/gitian-descriptors/deps-linux.yml b/contrib/gitian-descriptors/deps-linux.yml deleted file mode 100644 index 25123edbf9..0000000000 --- a/contrib/gitian-descriptors/deps-linux.yml +++ /dev/null @@ -1,105 +0,0 @@ ---- -name: "shadow-deps" -suites: -- "trusty" -architectures: -- "i386" -- "amd64" -packages: -- "g++" -- "pkg-config" -- "libtool" -- "faketime" -- "bsdmainutils" -reference_datetime: "2015-10-01 00:00:00" -remotes: [] -files: -- "openssl-1.0.2d.tar.gz" -- "miniupnpc-1.9.20151008.tar.gz" -- "db-4.8.30.NC.tar.gz" -- "boost_1_55_0.tar.bz2" -script: | - STAGING="$HOME/install" - TEMPDIR="$HOME/tmp" - OPTFLAGS='-O2' - if [ "$GBUILD_BITS" == "32" ]; then - export LD_PRELOAD=/usr/lib/i386-linux-gnu/faketime/libfaketime.so.1; - else - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1; - fi - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - export LIBRARY_PATH="$STAGING/lib" - # Integrity Check - echo "671c36487785628a703374c652ad2cebea45fa920ae5681515df25d9f2c9a8c8 openssl-1.0.2d.tar.gz" | sha256sum -c - echo "e444ac3b587ce82709c4d0cfca1fe71f44f9fc433e9f946b12b9e1bfe667a633 miniupnpc-1.9.20151008.tar.gz" | sha256sum -c - echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c - echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | sha256sum -c - - # - tar xzf openssl-1.0.2d.tar.gz - cd openssl-1.0.2d - # need -fPIC to avoid relocation error in 64 bit builds - ./config no-shared no-zlib no-dso no-krb5 --openssldir=$STAGING -fPIC - # need to build OpenSSL with faketime because a timestamp is embedded into cversion.o - make - make install_sw - cd .. - # - tar xzf miniupnpc-1.9.20151008.tar.gz - cd miniupnpc-1.9.20151008 - # miniupnpc is always built with -fPIC - INSTALLPREFIX=$STAGING make $MAKEOPTS libminiupnpc.a install - ls $STAGING/lib/libminiupnpc.so* - rm -f $STAGING/lib/libminiupnpc.so* # no way to skip shared lib build - cd .. - # - - # - #tar xjf protobuf-2.5.0.tar.bz2 - #cd protobuf-2.5.0 - #mkdir -p $STAGING/host/bin - #unset FAKETIME # unset fake time during configure, as it does some clock sanity tests - # need --with-pic to avoid relocation error in 64 bit builds - #./configure --prefix=$STAGING --bindir=$STAGING/host/bin --enable-static --disable-shared --with-pic --without-zlib - # Workaround to prevent re-configuring by make; make all files have a date in the past - #find . -print0 | xargs -r0 touch -t 200001010000 - #export FAKETIME=$REFERENCE_DATETIME - #make $MAKEOPTS install - #cd .. - # - tar xzf db-4.8.30.NC.tar.gz - cd db-4.8.30.NC/build_unix - # need --with-pic to avoid relocation error in 64 bit builds - ../dist/configure --prefix=$STAGING --enable-cxx --disable-shared --with-pic - # Workaround to prevent re-configuring by make; make all files have a date in the past - find . -print0 | xargs -r0 touch -t 200001010000 - make $MAKEOPTS library_build - make install_lib install_include - cd ../.. - - # Input Integrity Check - tar --warning=no-timestamp -xjf boost_1_55_0.tar.bz2 - cd boost_1_55_0 - GCCVERSION=$(g++ -E -dM $(mktemp --suffix=.h) | grep __VERSION__ | cut -d ' ' -f 3 | cut -d '"' -f 2) - # note: bjam with -d+2 reveals that -O3 is implied by default, no need to provide it in cxxflags - echo "using gcc : $GCCVERSION : g++ - : - \"-frandom-seed=boost1 -fPIC\" - ;" > user-config.jam - - ./bootstrap.sh --without-icu - - ./bjam toolset=gcc threadapi=pthread threading=multi variant=release link=static runtime-link=shared --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 --layout=tagged --build-type=complete --prefix="$STAGING" $MAKEOPTS -d+2 install - - # post-process all generated libraries to be deterministic - # extract them to a temporary directory then re-build them deterministically - for LIB in $(find $STAGING -name \*.a); do - rm -rf $TEMPDIR && mkdir $TEMPDIR && cd $TEMPDIR - ar xv $LIB | cut -b5- > /tmp/list.txt - rm $LIB - ar crsD $LIB $(cat /tmp/list.txt) - done - # - cd $STAGING - find include lib | sort | tar --no-recursion -cJf $OUTDIR/shadow-deps-linux${GBUILD_BITS}-gitian.tar.xz -T - diff --git a/contrib/gitian-descriptors/deps-osx.yml b/contrib/gitian-descriptors/deps-osx.yml deleted file mode 100644 index 2313fb5e3b..0000000000 --- a/contrib/gitian-descriptors/deps-osx.yml +++ /dev/null @@ -1,112 +0,0 @@ ---- -name: "shadow-deps" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "git-core" -- "clang" -- "llvm-dev" -- "faketime" -- "psmisc" -reference_datetime: "2011-01-30 00:00:00" -remotes: [] -files: -- "openssl-1.0.2d.tar.gz" -- "db-4.8.30.NC.tar.gz" -- "miniupnpc-1.9.20151008.tar.gz" -- "zlib-1.2.8.tar.gz" -- "icu4c-55_1-src.tgz" -- "boost_1_55_0.tar.bz2" -- "osxcross.tar.xz" -script: | - # - # Input Integrity Check - echo "671c36487785628a703374c652ad2cebea45fa920ae5681515df25d9f2c9a8c8 openssl-1.0.2d.tar.gz" | sha256sum -c - echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c - echo "e444ac3b587ce82709c4d0cfca1fe71f44f9fc433e9f946b12b9e1bfe667a633 miniupnpc-1.9.20151008.tar.gz" | sha256sum -c - echo "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d zlib-1.2.8.tar.gz" | sha256sum -c - echo "e16b22cbefdd354bec114541f7849a12f8fc2015320ca5282ee4fd787571457b icu4c-55_1-src.tgz" | sha256sum -c - echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | shasum -c - # - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - BUILDDIR=$HOME/build - INSTALLPREFIX=$HOME/install - TEMPDIR=$HOME/tmp - DEPSDIR=$HOME/deps - SDK=$DEPSDIR/SDK/MacOSX10.9.sdk - HOST=x86_64-apple-darwin13 - MIN_VERSION=10.6 - # - mkdir -p $INSTALLPREFIX $BUILDDIR $DEPSDIR - cd $DEPSDIR - tar xf $BUILDDIR/osxcross.tar.xz - PATH=$PATH:$DEPSDIR/bin - # - cd $BUILDDIR - tar xzf openssl-1.0.2d.tar.gz - cd openssl-1.0.2d - CC=cc ./Configure --cross-compile-prefix=$HOST- darwin64-x86_64-cc no-shared no-dso --openssldir=$INSTALLPREFIX - make - make install_sw - # - cd $BUILDDIR - tar xzf db-4.8.30.NC.tar.gz - cd db-4.8.30.NC/build_unix - sed -i 's/__atomic_compare_exchange/__atomic_compare_exchange_db/g' ../dbinc/atomic.h - ../dist/configure --prefix=$INSTALLPREFIX --enable-cxx --host=$HOST --disable-shared --disable-replication - make $MAKEOPTS library_build - make install_lib install_include - cd ../.. - # - tar xzf miniupnpc-1.9.20151008.tar.gz - cd miniupnpc-1.9.20151008 - make -f Makefile OS=Darwin CC=$HOST-cc AR=$HOST-ar libminiupnpc.a - install -d $INSTALLPREFIX/include/miniupnpc - install *.h $INSTALLPREFIX/include/miniupnpc - install libminiupnpc.a $INSTALLPREFIX/lib - # - cd $BUILDDIR - mkdir -p icuCross - cd icuCross - tar xzf $BUILDDIR/icu4c-55_1-src.tgz - cd icu/source - mkdir -p $TEMPDIR/icu - ./runConfigureICU MacOSX --prefix=$TEMPDIR/icu --enable-static --disable-shared - make - make install - #rm -rf icu - cd $BUILDDIR - tar xzf icu4c-55_1-src.tgz - cd icu/source - ./runConfigureICU MacOSX --host=$HOST --with-cross-build=$BUILDDIR/icuCross/icu/source --prefix=$INSTALLPREFIX --enable-static --disable-shared - make - make install - # - cd $BUILDDIR - tar --warning=no-timestamp -xjf boost_1_55_0.tar.bz2 - cd boost_1_55_0 - ./bootstrap.sh --with-libraries=chrono,filesystem,program_options,system,thread,test - echo "using darwin : : ${HOST}-clang++ - : - \"-target ${HOST} -mmacosx-version-min=${MIN_VERSION} --sysroot ${SDK} -msse2 -Qunused-arguments -I${INSTALLPREFIX}/include -DBOOST_HAS_INT128=1\" - \"-L${INSTALLPREFIX}/lib -B${DEPSDIR}/bin\" - \"${HOST}-libtool\" - \"${HOST}-strip\" : - ;" > user-config.jam - ./b2 -d2 --layout=tagged --build-type=complete --prefix="${INSTALLPREFIX}" --toolset=darwin-4.2.1 --user-config=user-config.jam variant=release threading=multi link=static install - # - # post-process all generated libraries to be deterministic - # extract them to a temporary directory then re-build them deterministically - #for LIB in $(find $INSTALLPREFIX -name \*.a); do - # rm -rf $TEMPDIR && mkdir $TEMPDIR && cd $TEMPDIR - # $HOST-ar xv $LIB | cut -b5- > /tmp/list.txt - # rm $LIB - # $HOST-ar crs $LIB $(cat /tmp/list.txt) - #done - # - cd $INSTALLPREFIX - find include lib | sort | tar --no-recursion -cJf $OUTDIR/shadow-deps-osx-gitian.tar.xz -T - diff --git a/contrib/gitian-descriptors/deps-win.yml b/contrib/gitian-descriptors/deps-win.yml deleted file mode 100644 index b40942cb39..0000000000 --- a/contrib/gitian-descriptors/deps-win.yml +++ /dev/null @@ -1,175 +0,0 @@ ---- -name: "shadow-deps" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "mingw-w64" -- "g++-mingw-w64" -- "git-core" -- "faketime" -- "psmisc" -reference_datetime: "2011-01-30 00:00:00" -remotes: [] -files: -- "openssl-1.0.2d.tar.gz" -- "db-4.8.30.NC.tar.gz" -- "miniupnpc-1.9.20151008.tar.gz" -- "zlib-1.2.8.tar.gz" -- "libpng-1.6.10.tar.gz" -- "icu4c-55_1-src.tgz" -- "boost_1_55_0.tar.bz2" -- "boost-mingw-gas-cross-compile-2013-03-03.patch" -script: | - # - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - INDIR=$HOME/build - TEMPDIR=$HOME/tmp - # Input Integrity Check - echo "671c36487785628a703374c652ad2cebea45fa920ae5681515df25d9f2c9a8c8 openssl-1.0.2d.tar.gz" | sha256sum -c - echo "12edc0df75bf9abd7f82f821795bcee50f42cb2e5f76a6a281b85732798364ef db-4.8.30.NC.tar.gz" | sha256sum -c - echo "e444ac3b587ce82709c4d0cfca1fe71f44f9fc433e9f946b12b9e1bfe667a633 miniupnpc-1.9.20151008.tar.gz" | sha256sum -c - echo "36658cb768a54c1d4dec43c3116c27ed893e88b02ecfcb44f2166f9c0b7f2a0d zlib-1.2.8.tar.gz" | sha256sum -c - echo "b0206a22b49c91fc5521b2cfb1c251433a37aed0a645bc504ab3d061f27e4d51 libpng-1.6.10.tar.gz" | sha256sum -c - echo "e16b22cbefdd354bec114541f7849a12f8fc2015320ca5282ee4fd787571457b icu4c-55_1-src.tgz" | sha256sum -c - echo "fff00023dd79486d444c8e29922f4072e1d451fc5a4d2b6075852ead7f2b7b52 boost_1_55_0.tar.bz2" | sha256sum -c - echo "d2b7f6a1d7051faef3c9cf41a92fa3671d905ef1e1da920d07651a43299f6268 boost-mingw-gas-cross-compile-2013-03-03.patch" \ - | sha256sum -c - # - for BITS in 32 64; do # for architectures - # - INSTALLPREFIX=$HOME/staging${BITS} - BUILDDIR=$HOME/build${BITS} - if [ "$BITS" == "32" ]; then - HOST=i686-w64-mingw32 - else - HOST=x86_64-w64-mingw32 - fi - # - mkdir -p $INSTALLPREFIX $BUILDDIR - cd $BUILDDIR - # - tar xzf $INDIR/openssl-1.0.2d.tar.gz - cd openssl-1.0.2d - if [ "$BITS" == "32" ]; then - OPENSSL_TGT=mingw - else - OPENSSL_TGT=mingw64 - fi - ./Configure --cross-compile-prefix=$HOST- ${OPENSSL_TGT} no-shared no-dso --openssldir=$INSTALLPREFIX - make - make install_sw - cd .. - # - tar xzf $INDIR/db-4.8.30.NC.tar.gz - cd db-4.8.30.NC/build_unix - ../dist/configure --prefix=$INSTALLPREFIX --enable-mingw --enable-cxx --host=$HOST --disable-shared --disable-replication - make $MAKEOPTS library_build - make install_lib install_include - cd ../.. - # - tar xzf $INDIR/miniupnpc-1.9.20151008.tar.gz - cd miniupnpc-1.9.20151008 - echo " - --- miniupnpc-1.9/Makefile.mingw.orig 2013-09-29 18:52:51.014087958 -1000 - +++ miniupnpc-1.9/Makefile.mingw 2013-09-29 19:09:29.663318691 -1000 - @@ -67,8 +67,8 @@ - - wingenminiupnpcstrings.o: wingenminiupnpcstrings.c - - -miniupnpcstrings.h: miniupnpcstrings.h.in wingenminiupnpcstrings - - wingenminiupnpcstrings \$< \$@ - +miniupnpcstrings.h: miniupnpcstrings.h.in - + sed -e 's|OS/version|MSWindows/5.1.2600|' -e 's|MINIUPNPC_VERSION_STRING \"version\"|MINIUPNPC_VERSION_STRING \"VERSIONHERE\"|' \$< > \$@ - - minixml.o: minixml.c minixml.h miniupnpcstrings.h - - " | sed "s/VERSIONHERE/$(cat VERSION)/" | patch -p1 - mkdir -p dll - make -f Makefile.mingw CC=$HOST-gcc AR=$HOST-ar libminiupnpc.a - install -d $INSTALLPREFIX/include/miniupnpc - install *.h $INSTALLPREFIX/include/miniupnpc - install libminiupnpc.a $INSTALLPREFIX/lib - cd .. - # - # - tar xzf $INDIR/zlib-1.2.8.tar.gz - cd zlib-1.2.8 - CROSS_PREFIX=$HOST- ./configure --prefix=$INSTALLPREFIX --static - make - make install - cd .. - # - tar xzf $INDIR/libpng-1.6.10.tar.gz - cd libpng-1.6.10 - OPT="-O2" - CPPFLAGS="${OPT} -I$INSTALLPREFIX/include" CFLAGS="${OPT} -I$INSTALLPREFIX/include" LDFLAGS="${OPT} -L$INSTALLPREFIX/lib" ./configure --disable-shared --prefix=$INSTALLPREFIX --host=$HOST - make $MAKEOPTS - make install - cd .. - # - mkdir icuCross - cd icuCross - tar xzf $INDIR/icu4c-55_1-src.tgz - cd icu/source - mkdir -p $TEMPDIR/icu - ./runConfigureICU MinGW --prefix=$TEMPDIR/icu --enable-static --disable-shared - make - make install - cd ../../.. - #rm -rf icu - tar xzf $INDIR/icu4c-55_1-src.tgz - cd icu/source - ./runConfigureICU MinGW --host=$HOST --with-cross-build=$BUILDDIR/icuCross/icu/source --prefix=$INSTALLPREFIX --enable-static --disable-shared - make - make install - cd ../.. - # - tar --warning=no-timestamp -xjf $INDIR/boost_1_55_0.tar.bz2 - cd boost_1_55_0 - GCCVERSION=$($HOST-g++ -E -dM $(mktemp --suffix=.h) | grep __VERSION__ | cut -d ' ' -f 3 | cut -d '"' -f 2) - echo "using gcc : $GCCVERSION : $HOST-g++ - : - $HOST-windres - $HOST-ar - -frandom-seed=boost1 - $HOST-ranlib - ;" > user-config.jam - ./bootstrap.sh --without-icu - - # Workaround: Upstream boost dev refuses to include patch that would allow Free Software cross-compile toolchain to work - # This patch was authored by the Fedora package developer and ships in Fedora's mingw32-boost. - # Please obtain the exact patch that matches the above sha256sum from one of the following mirrors. - # - # Read History: https://svn.boost.org/trac/boost/ticket/7262 - # History Mirror: http://rose.makesad.us/~paulproteus/mirrors/7262%20Boost.Context%20fails%20to%20build%20using%20MinGW.html - # - # Patch: https://svn.boost.org/trac/boost/raw-attachment/ticket/7262/boost-mingw.patch - # Patch Mirror: http://wtogami.fedorapeople.org/boost-mingw-gas-cross-compile-2013-03-03.patch - # Patch Mirror: http://mindstalk.net/host/boost-mingw-gas-cross-compile-2013-03-03.patch - # Patch Mirror: http://rose.makesad.us/~paulproteus/mirrors/boost-mingw-gas-cross-compile-2013-03-03.patch - patch -p0 < $INDIR/boost-mingw-gas-cross-compile-2013-03-03.patch - - # Bug Workaround: boost-1.54.0 broke the ability to disable zlib, still broken in 1.55 - # https://svn.boost.org/trac/boost/ticket/9156 - sed -i 's^\[ ac.check-library /zlib//zlib : /zlib//zlib^^' libs/iostreams/build/Jamfile.v2 - sed -i 's^zlib.cpp gzip.cpp \]^^' libs/iostreams/build/Jamfile.v2 - - # http://statmt.org/~s0565741/software/boost_1_52_0/libs/context/doc/html/context/requirements.html - # "For cross-compiling the lib you must specify certain additional properties at bjam command line: target-os, abi, binary-format, architecture and address-model." - ./bjam toolset=gcc binary-format=pe target-os=windows threadapi=win32 address-model=$BITS threading=multi variant=release link=static runtime-link=static --user-config=user-config.jam --without-mpi --without-python -sNO_BZIP2=1 -sNO_ZLIB=1 --layout=tagged --build-type=complete --prefix="$INSTALLPREFIX" $MAKEOPTS install - # post-process all generated libraries to be deterministic - # extract them to a temporary directory then re-build them deterministically - for LIB in $(find $INSTALLPREFIX -name \*.a); do - rm -rf $TEMPDIR && mkdir $TEMPDIR && cd $TEMPDIR - $HOST-ar xv $LIB | cut -b5- > /tmp/list.txt - rm $LIB - $HOST-ar crsD $LIB $(cat /tmp/list.txt) - done - # - cd $INSTALLPREFIX - find include lib | sort | tar --no-recursion -cJf $OUTDIR/shadow-deps-win$BITS-gitian.tar.xz -T - - done # for BITS in diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml deleted file mode 100644 index a4f4939975..0000000000 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- -name: "shadow" -suites: -- "trusty" -architectures: -- "i386" -- "amd64" -packages: -- "g++" -- "libqt5webkit5-dev" -- "qt5-qmake" -- "qt5-default" -- "qttools5-dev-tools" -- "git-core" -- "pkg-config" -- "libtool" -- "automake" -- "faketime" -- "bsdmainutils" -reference_datetime: "2015-05-25 00:00:00" -remotes: -- "url": "https://github.com/ShadowProject/shadowcoin.git" - "dir": "shadowcoin" -files: -- "shadow-deps-linux32-gitian.tar.xz" -- "shadow-deps-linux64-gitian.tar.xz" -script: | - #Integrity check - echo "0d1e171cd3683f2ebb8e3dc1ab29bdcca4ed136b4ee30d376f1c3cf8c29ea7d0 shadow-deps-linux32-gitian.tar.xz" |sha256sum -c - echo "3f3f36e20fc1c3dcd00a4f32a7f07172989933b2b8534147fec896de1b520b3b shadow-deps-linux64-gitian.tar.xz" |sha256sum -c - STAGING="$HOME/install" - OPTFLAGS='-O2' - BINDIR="${OUTDIR}/bin/${GBUILD_BITS}" # 32/64 bit build specific output directory - TEMPDIR="$HOME/tempdir" - if [ "$GBUILD_BITS" == "32" ]; then - export LD_PRELOAD=/usr/lib/i386-linux-gnu/faketime/libfaketime.so.1; - else - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1; - fi - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - export LIBRARY_PATH="$STAGING/lib" - mkdir -p ${BINDIR} - # - mkdir -p $STAGING - cd $STAGING - tar xf ../build/shadow-deps-linux${GBUILD_BITS}-gitian.tar.xz - cd ../build - # - cd shadowcoin - mkdir -p $OUTDIR/src - git archive HEAD | tar -x -C $OUTDIR/src - cp $OUTDIR/src/doc/README $OUTDIR - cp $OUTDIR/src/COPYING $OUTDIR - cd src - make -f makefile.unix STATIC=1 OPENSSL_INCLUDE_PATH="$STAGING/include" OPENSSL_LIB_PATH="$STAGING/lib" $MAKEOPTS shadowcoind USE_UPNP=1 BOOST_LIB_SUFFIX="-mt" DEBUGFLAGS= - mkdir -p $STAGING/bin/$GBUILD_BITS - install -s shadowcoind $OUTDIR/bin/$GBUILD_BITS - # - cd .. - qmake INCLUDEPATH="$STAGING/include" LIBS="-L$STAGING/lib" BOOST_LIB_SUFFIX="-mt" RELEASE=1 USE_QRCODE=1 - make $MAKEOPTS - install shadow $OUTDIR/bin/$GBUILD_BITS diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml deleted file mode 100644 index 37a1276f62..0000000000 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ /dev/null @@ -1,88 +0,0 @@ ---- -name: "shadow" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "git-core" -- "clang" -- "llvm-dev" -- "unzip" -- "zip" -- "nsis" -- "faketime" -- "autoconf2.13" -- "libtool" -- "automake" -- "pkg-config" -- "bsdmainutils" -- "python" -- "genisoimage" -reference_datetime: "2013-06-01 00:00:00" -remotes: -- "url": "https://github.com/ShadowProject/shadowcoin.git" - "dir": "shadowcoin" -files: -- "qt-osx-5.5.0-gitian.tar.xz" -- "shadow-deps-osx-gitian.zip" -- "osxcross.tar.xz" -script: | - # Defines - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - INDIR=$HOME/build - OPTFLAGS='-O2' - TEMPDIR="$HOME/tempdir" - BUILDDIR=$HOME/build - DEPSDIR=$HOME/deps - HOST=x86_64-apple-darwin13 - DISTNAME=x86_64-darwin - export PATH=$DEPSDIR/host/bin:$DEPSDIR:$DEPSDIR/bin:$PATH - NEEDDIST=1 - # Qt: workaround for determinism in resource ordering - # Qt5's rcc uses a QHash to store the files for the resource. - # A security fix in QHash makes the ordering of keys to be different on every run - # (https://qt.gitorious.org/qt/qtbase/commit/c01eaa438200edc9a3bbcd8ae1e8ded058bea268). - # This is good in general but qrc shouldn't be doing a traversal over a randomized container. - # The thorough solution would be to use QMap instead of QHash, but this requires patching Qt. - # For now luckily there is a test mode that forces a fixed seed. - export QT_RCC_TEST=1 - mkdir -p $BUILDDIR $BINDIR $DEPSDIR - cd $DEPSDIR - unzip -o $BUILDDIR/shadow-deps-osx-gitian.zip - tar xf $BUILDDIR/osxcross.tar.xz - mkdir -p $HOME/install - cd $HOME/install - tar xf $BUILDDIR/qt-osx-5.5.0-gitian.tar.xz - # - cd $BUILDDIR/shadowcoin - mkdir -p $OUTDIR/src - git archive HEAD | tar -x -C $OUTDIR/src - cp $OUTDIR/src/doc/README $OUTDIR/readme.txt - cp $OUTDIR/src/COPYING $OUTDIR/COPYING.txt - # - #cd src - #make -f makefile.linux-mingw HOST="$HOST" DEPSDIR="$DEPSDIR" CURDIR="$BUILDDIR/shadowcoin/src" STATIC=1 $MAKEOPTS USE_UPNP=1 BOOST_LIB_SUFFIX="-mt-s" DEBUGFLAGS= - #cp shadowcoind.exe $BINDIR/ - #cd .. - # - #$DEPSDIR/qt/host/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/lib BOOST_INCLUDE_PATH=$HOME/build/include BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1h OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1h/include INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1 - ~/install/host/bin/qmake -xplatform macx-clang-linux RELEASE=1 QMAKE_LRELEASE="~/install/host/bin/lrelease" MINIUPNPC_LIB_PATH="$DEPSDIR/lib" MINIUPNPC_INCLUDE_PATH="$DEPSDIR/include" BDB_LIB_PATH="$DEPSDIR/lib" BDB_INCLUDE_PATH="$DEPSDIR/include" BOOST_LIB_PATH="$DEPSDIR/lib" BOOST_INCLUDE_PATH="$DEPSDIR/include" BOOST_LIB_SUFFIX="-mt-s" BOOST_THREAD_LIB_SUFFIX="-mt-s" OPENSSL_LIB_PATH="$DEPSDIR/lib" OPENSSL_INCLUDE_PATH="$DEPSDIR/include" INCLUDEPATH="$DEPSDIR/include" DEFINES="BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 USE_BUILD_INFO=1" QMAKE_CXXFLAGS+=" -I/home/ubuntu/deps/SDK/MacOSX10.9.sdk/usr/include -DBOOST_HAS_INT128=1 -frandom-seed=shadow" - make $MAKEOPTS - # macdeploy: TODO: .dmg - export OTOOL=${HOST}-otool - export INSTALLNAMETOOL=${HOST}-install_name_tool - export STRIP=${HOST}-strip - chmod +x contrib/macdeploy/macdeployqtplus - OTOOL=${HOST}-otool INSTALLNAMETOOL=${HOST}-install_name_tool STRIP=${HOST}-strip contrib/macdeploy/macdeployqtplus Shadow.app - mkdir -p dist/.background - install contrib/macdeploy/background.png dist/.background - install contrib/macdeploy/DS_Store dist/.DS_Store - cd dist - ln -sf /Applications Applications - cd .. - genisoimage -no-cache-inodes -l -probe -V "Shadow" -no-pad -r -apple -o Shadow.tmp.dmg dist - dmg dmg Shadow.tmp.dmg $OUTDIR/Shadow.dmg - # diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml deleted file mode 100644 index 3fbe018e63..0000000000 --- a/contrib/gitian-descriptors/gitian-win.yml +++ /dev/null @@ -1,102 +0,0 @@ ---- -name: "shadow" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "mingw-w64" -- "g++-mingw-w64" -- "git-core" -- "nsis" -- "faketime" -- "autoconf2.13" -- "libtool" -- "automake" -- "pkg-config" -- "bsdmainutils" -reference_datetime: "2013-06-01 00:00:00" -remotes: -- "url": "https://github.com/ShadowProject/shadowcoin.git" - "dir": "shadowcoin" -files: -- "qt-win32-5.5.0-gitian.tar.xz" -- "qt-win64-5.5.0-gitian.tar.xz" -- "shadow-deps-win32-gitian.tar.xz" -- "shadow-deps-win64-gitian.tar.xz" -script: | - # Defines - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - export TZ=UTC - INDIR=$HOME/build - OPTFLAGS='-O2' - TEMPDIR="$HOME/tempdir" - - NEEDDIST=1 - # Qt: workaround for determinism in resource ordering - # Qt5's rcc uses a QHash to store the files for the resource. - # A security fix in QHash makes the ordering of keys to be different on every run - # (https://qt.gitorious.org/qt/qtbase/commit/c01eaa438200edc9a3bbcd8ae1e8ded058bea268). - # This is good in general but qrc shouldn't be doing a traversal over a randomized container. - # The thorough solution would be to use QMap instead of QHash, but this requires patching Qt. - # For now luckily there is a test mode that forces a fixed seed. - export QT_RCC_TEST=1 - for BITS in 32 64; do # for architectures - # - STAGING=$HOME/staging${BITS} - BUILDDIR=$HOME/build${BITS} - BINDIR=$OUTDIR/$BITS - DEPSDIR=$HOME/deps${BITS} - if [ "$BITS" == "32" ]; then - HOST=i686-w64-mingw32 - DISTNAME=i686-win - else - HOST=x86_64-w64-mingw32 - DISTNAME=x86_64-win - fi - export PATH=$STAGING/host/bin:$PATH - rm -rf $DEPSDIR - rm -rf $BUILDDIR - rm -rf $STAGING - mkdir -p $STAGING $BUILDDIR $BINDIR $DEPSDIR - # - cd $STAGING - #mkdir qt - #cd qt - #5edf8d14e47eb6438d3b5a20ed577343a07512eb220e6f83cbb3fbd33112a776 qt-win32-5.5.0-gitian-r3.zip - #75a3b425f08969983b2faf0af83b01fd753f99a15ced0b6f998d4db0a1c077f3 qt-win64-5.5.0-gitian-r3.zip - - tar xf $INDIR/qt-win${BITS}-5.5.0-gitian.tar.xz - cd $DEPSDIR - tar xf $INDIR/shadow-deps-win${BITS}-gitian.tar.xz - # - cd $BUILDDIR - cp -r ../build/shadowcoin . - cd shadowcoin - mkdir -p $OUTDIR/src - git archive HEAD | tar -x -C $OUTDIR/src - cp $OUTDIR/src/doc/README_windows.txt $OUTDIR/readme.txt - cp $OUTDIR/src/COPYING $OUTDIR/COPYING.txt - # - cd src - make -f makefile.linux-mingw HOST="$HOST" DEPSDIR="$DEPSDIR" CURDIR="$BUILDDIR/shadowcoin/src" STATIC=1 $MAKEOPTS USE_UPNP=1 BOOST_LIB_SUFFIX="-mt-s" DEBUGFLAGS= - cp shadowcoind.exe $BINDIR/ - cd .. - # - #$DEPSDIR/qt/host/bin/qmake -spec unsupported/win32-g++-cross MINIUPNPC_LIB_PATH=$HOME/build/miniupnpc MINIUPNPC_INCLUDE_PATH=$HOME/build/ BDB_LIB_PATH=$HOME/build/db-4.8.30.NC/build_unix BDB_INCLUDE_PATH=$HOME/build/db-4.8.30.NC/build_unix BOOST_LIB_PATH=$HOME/build/lib BOOST_INCLUDE_PATH=$HOME/build/include BOOST_LIB_SUFFIX=-mt-s BOOST_THREAD_LIB_SUFFIX=_win32-mt-s OPENSSL_LIB_PATH=$HOME/build/openssl-1.0.1h OPENSSL_INCLUDE_PATH=$HOME/build/openssl-1.0.1h/include INCLUDEPATH=$HOME/build DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_LRELEASE=lrelease QMAKE_CXXFLAGS=-frandom-seed=bitcoin USE_BUILD_INFO=1 - $STAGING/host/bin/qmake -xplatform win32-g++ RELEASE=1 QMAKE_LRELEASE="$STAGING/host/bin/lrelease" MINIUPNPC_LIB_PATH="$DEPSDIR/lib" MINIUPNPC_INCLUDE_PATH="$DEPSDIR/include" BDB_LIB_PATH="$DEPSDIR/lib" BDB_INCLUDE_PATH="$DEPSDIR/include" BOOST_LIB_PATH="$DEPSDIR/lib" BOOST_INCLUDE_PATH="$DEPSDIR/include" BOOST_LIB_SUFFIX="-mt-s" BOOST_THREAD_LIB_SUFFIX="_win32-mt-s" OPENSSL_LIB_PATH="$DEPSDIR/lib" OPENSSL_INCLUDE_PATH="$DEPSDIR/include" INCLUDEPATH="$DEPSDIR/include" DEFINES=BOOST_THREAD_USE_LIB BITCOIN_NEED_QT_PLUGINS=1 QMAKE_CXXFLAGS=-frandom-seed=shadow USE_BUILD_INFO=1 - make $MAKEOPTS - cp release/shadow.exe $BINDIR/ - # - unset LD_PRELOAD - unset FAKETIME - done # for BITS in - # - # sort distribution tar file and normalize user/group/mtime information for deterministic output - mkdir -p $OUTDIR/src - rm -rf $TEMPDIR - mkdir -p $TEMPDIR - cd $TEMPDIR - cd $BINDIR - #tar -xvf $HOME/build/shadowcoin/$DISTNAME | sort | tar --no-recursion -cT /dev/stdin --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 --mtime="$REFERENCE_DATETIME" | gzip -n > $OUTDIR/src/$DISTNAME diff --git a/contrib/gitian-descriptors/osxcross.yml b/contrib/gitian-descriptors/osxcross.yml deleted file mode 100644 index 7e7816ae06..0000000000 --- a/contrib/gitian-descriptors/osxcross.yml +++ /dev/null @@ -1,61 +0,0 @@ ---- -name: "osxcross" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "clang" -- "llvm-dev" -- "libxml2-dev" -- "uuid-dev" -- "libssl-dev" -- "bsdmainutils" -- "zip" -- "cmake" -reference_datetime: "2013-06-01 00:00:00" -remotes: -- "url": "https://github.com/tpoechtrager/osxcross.git" - "dir": "osxcross" -- "url": "https://github.com/planetbeing/libdmg-hfsplus" - "dir": "libdmg-hfsplus" -files: -- "MacOSX10.9.sdk.tar.xz" -script: | - # Defines - export TZ=UTC - export TAR_OPTIONS="-m --mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME"" - BUILDDIR=$HOME/build - PREFIX=$HOME/install - mkdir -p $BUILDDIR $PREFIX - cd $BUILDDIR - PATH=$PATH:$BUILDDIR - - # Build OSX Cross - cd osxcross - ln -s $HOME/build/MacOSX10.9.sdk.tar.xz tarballs/ - UNATTENDED=1 ./build.sh - cd target - mv * $PREFIX - # Fix broken symlinks - rm -f $PREFIX/bin/osxcross-macports $PREFIX/bin/osxcross-mp $PREFIX/bin/omp - mv ../tools/osxcross-macports $PREFIX/bin - cd $PREFIX/bin - ln -sf osxcross-macports osxcross-mp - ln -sf osxcross-macports omp - cd $PREFIX/SDK/MacOSX10.9.sdk/usr/include - rm stdarg.h - ln -sf ../../System/Library/Frameworks/Kernel.framework/Versions/A/Headers/stdarg.h . - cd ../share - rm -rf man # No need for manuals... - # Build hdutil and .dmg dependencies - cd $BUILDDIR/libdmg-hfsplus - cmake CMakeLists.txt - make - mv dmg/dmg $PREFIX/bin - mv hfs/hfsplus $PREFIX/bin - mv hdutil/hdutil $PREFIX/bin - cd $PREFIX - # Adjust timestamps on files, for deterministic tar output - find . -print0 | xargs -r0 touch -t 200001010000 - find | sort | tar --no-recursion -cJf $OUTDIR/osxcross.tar.xz -T - diff --git a/contrib/gitian-descriptors/qt-osx.yml b/contrib/gitian-descriptors/qt-osx.yml deleted file mode 100644 index fce7cb1fe0..0000000000 --- a/contrib/gitian-descriptors/qt-osx.yml +++ /dev/null @@ -1,238 +0,0 @@ ---- -name: "shadow-qt" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "clang" -- "llvm-dev" -- "zip" -- "unzip" -- "faketime" -- "libz-dev" -- "ruby-full" -- "perl" -- "python" -- "m4" -- "bison" -- "gperf" -- "sharutils" -reference_datetime: "2011-01-30 00:00:00" -remotes: [] -files: -- "qt-everywhere-opensource-src-5.5.0.tar.xz" -- "shadow-deps-osx-gitian.zip" -- "flex-2.5.38.tar.gz" -- "osxcross.tar.xz" -script: | - # Integrity Check - echo "7ea2a16ecb8088e67db86b0835b887d5316121aeef9565d5d19be3d539a2c2af qt-everywhere-opensource-src-5.5.0.tar.xz" | sha256sum -c - echo "16d68bae5336c0698817bb5a1a4bd9a6804263608fdf553ca63fd90b682ec366 shadow-deps-osx-gitian.zip" | sha256sum -c - echo "80f7c7188d7611e47e47d2a70c8ef65026c1cf71ddeb4ace9b1be5b8a76ffbd2 flex-2.5.38.tar.gz" | sha256sum -c - # - # Defines - export TZ=UTC - BUILDDIR=$HOME/build - TEMPDIR=$HOME/tmp - INSTALLPREFIX=$HOME/install - DEPSDIR=$HOME/deps - HOST=x86_64-apple-darwin13 - MIN_VERSION=10.6 - SDK_VERSION=10.9 - SDK=${DEPSDIR}/SDK/MacOSX${SDK_VERSION}.sdk - # - # Qt: workaround for determinism in resource ordering - # Qt5's rcc uses a QHash to store the files for the resource. - # A security fix in QHash makes the ordering of keys to be different on every run - # (https://qt.gitorious.org/qt/qtbase/commit/c01eaa438200edc9a3bbcd8ae1e8ded058bea268). - # This is good in general but qrc shouldn't be doing a traversal over a randomized container. - # The thorough solution would be to use QMap instead of QHash, but this requires patching Qt. - # For now luckily there is a test mode that forces a fixed seed. - export QT_RCC_TEST=1 - # - # Fix our paths - export PATH="$DEPSDIR/bin:$DEPSDIR/lib:$PATH" - export INCLUDE="$DEPSDIR/include:$INCLUDE" - export LIB="$DEPSDIR/lib:$LIB" - # - mkdir -p $INSTALLPREFIX $INSTALLPREFIX/host/bin $DEPSDIR $BUILDDIR - # - cd $BUILDDIR - # - tar xzf $BUILDDIR/flex-2.5.38.tar.gz - cd flex-2.5.38 - ./configure --prefix=$DEPSDIR - make - make install - cd .. - # - # Need mingw-compiled openssl from shadow-deps: - cd $DEPSDIR - unzip -o $BUILDDIR/shadow-deps-osx-gitian.zip - tar xf $BUILDDIR/osxcross.tar.xz - tar xf qt-everywhere-opensource-src-5.5.0.tar.xz - # - QTDIR=$BUILDDIR/qt-everywhere-opensource-src-5.5.0 - cd $QTDIR - SPECDIR="qtbase/mkspecs" - SPECNAME="macx-clang-linux" - SPECFILE="${SPECDIR}/${SPECNAME}/qmake.conf" - rm -rf ${SPECDIR}/${SPECNAME} - cp -rp ${SPECDIR}/macx-clang ${SPECDIR}/${SPECNAME} - sed 's/qt_instdate=`date +%Y-%m-%d`/qt_instdate=2011-01-30/' -i qtbase/configure - sed 's/if \[ "$$$$XPLATFORM_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/if \[ "$$$$BUILD_ON_MAC" = "yes" \]; then xspecvals=$$$$(macSDKify/' -i qtbase/configure - # - sed 's/load(qt_config)//' -i $SPECFILE - cat > ${SPECFILE} < /tmp/list.txt - # rm $LIB - # $HOST-ar crsD $LIB $(cat /tmp/list.txt) - #done - # - cd $INSTALLPREFIX - # Remove unused non-deterministic stuff - rm host/bin/qtpaths lib/libQt5Bootstrap.a lib/libQt5Bootstrap.la - rm -f ${INSTALLPREFIX}/lib/Qt*.framework/Qt*.prl - cd include - ln -sf ../lib/QtNetwork.framework/Headers/ QtNetwork - ln -sf ../lib/QtWidgets.framework/Headers/ QtWidgets - ln -sf ../lib/QtGui.framework/Headers/ QtGui - ln -sf ../lib/QtCore.framework/Headers/ QtCore - ln -sf ../lib/QtTest.framework/Headers/ QtTest - ln -sf ../lib/QtWebKitWidgets.framework/Headers/ QtWebKitWidgets - cd .. - # as zip stores file timestamps, use faketime to intercept stat calls to set dates for all files to reference date - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - find -print0 | xargs -r0 touch # fix up timestamps before packaging - find | sort | tar --no-recursion -cJf $OUTDIR/qt-osx-5.5.0-gitian.tar.xz -T - diff --git a/contrib/gitian-descriptors/qt-win.yml b/contrib/gitian-descriptors/qt-win.yml deleted file mode 100644 index a2c6e9ad87..0000000000 --- a/contrib/gitian-descriptors/qt-win.yml +++ /dev/null @@ -1,256 +0,0 @@ ---- -name: "shadow-qt" -suites: -- "trusty" -architectures: -- "amd64" -packages: -- "mingw-w64" -- "g++-mingw-w64" -- "faketime" -- "libz-dev" -- "ruby-full" -- "perl" -- "python" -- "m4" -- "bison" -- "gperf" -- "sharutils" -- "zip" -- "unzip" -reference_datetime: "2011-01-30 00:00:00" -remotes: [] -files: -- "qt-everywhere-opensource-src-5.5.0.tar.xz" -- "shadow-deps-win32-gitian.tar.xz" -- "shadow-deps-win64-gitian.tar.xz" -- "flex-2.5.38.tar.gz" -script: | - # Integrity Check - echo "7ea2a16ecb8088e67db86b0835b887d5316121aeef9565d5d19be3d539a2c2af qt-everywhere-opensource-src-5.5.0.tar.xz" | sha256sum -c - echo "306264166531eecbb35ec645c425b1b5538e8ce3035d7bf599db0b2cc76c730f shadow-deps-win32-gitian.tar.xz" | sha256sum -c - echo "1c7c36ca02624fc2e0f026a84853217e84a9f27f8542a5b18d13164ea48edea7 shadow-deps-win64-gitian.tar.xz" | sha256sum -c - echo "80f7c7188d7611e47e47d2a70c8ef65026c1cf71ddeb4ace9b1be5b8a76ffbd2 flex-2.5.38.tar.gz" | sha256sum -c - # Defines - export TZ=UTC - INDIR=$HOME/build - TEMPDIR=$HOME/tmp - # Qt: workaround for determinism in resource ordering - # Qt5's rcc uses a QHash to store the files for the resource. - # A security fix in QHash makes the ordering of keys to be different on every run - # (https://qt.gitorious.org/qt/qtbase/commit/c01eaa438200edc9a3bbcd8ae1e8ded058bea268). - # This is good in general but qrc shouldn't be doing a traversal over a randomized container. - # The thorough solution would be to use QMap instead of QHash, but this requires patching Qt. - # For now luckily there is a test mode that forces a fixed seed. - export QT_RCC_TEST=1 - # - export OLDPATH="$PATH" - export OLDINCLUDE="$INCLUDE" - export OLDLIB="$LIB" - - for BITS in 32 64; do # for architectures - # - INSTALLPREFIX=$HOME/staging${BITS} - BUILDDIR=$HOME/build${BITS} - DEPSDIR=$HOME/deps${BITS} - if [ "$BITS" == "32" ]; then - HOST=i686-w64-mingw32 - else - HOST=x86_64-w64-mingw32 - fi - # - export PATH="$DEPSDIR/lib:$OLDPATH" - export INCLUDE="$DEPSDIR/include:$OLDINCLUDE" - export LIB="$DEPSDIR/lib:$OLDLIB" - export PATH="$DEPSDIR/bin:$PATH" - - # - mkdir -p $INSTALLPREFIX $INSTALLPREFIX/host/bin $DEPSDIR $BUILDDIR - # - cd $BUILDDIR - # - tar xzf $INDIR/flex-2.5.38.tar.gz - cd flex-2.5.38 - ./configure --prefix=$DEPSDIR - make - make install - cd .. - # - # Need mingw-compiled openssl from shadow-deps: - cd $DEPSDIR - tar xf $INDIR/shadow-deps-win${BITS}-gitian.tar.xz - # - ln -sf $DEPSDIR/lib/libsicudt.a $DEPSDIR/lib/libicudt.a - ln -sf $DEPSDIR/lib/libsicuin.a $DEPSDIR/lib/libicuin.a - ln -sf $DEPSDIR/lib/libsicuio.a $DEPSDIR/lib/libicuio.a - ln -sf $DEPSDIR/lib/libsicule.a $DEPSDIR/lib/libicule.a - ln -sf $DEPSDIR/lib/libsiculx.a $DEPSDIR/lib/libiculx.a - ln -sf $DEPSDIR/lib/libsicutest.a $DEPSDIR/lib/libicutest.a - ln -sf $DEPSDIR/lib/libsicutu.a $DEPSDIR/lib/libicutu.a - ln -sf $DEPSDIR/lib/libsicuuc.a $DEPSDIR/lib/libicuuc.a - # - cd $BUILDDIR - # - tar xf $INDIR/qt-everywhere-opensource-src-5.5.0.tar.xz - # - cd qt-everywhere-opensource-src-5.5.0 - QTDIR=$BUILDDIR/qt-everywhere-opensource-src-5.5.0 - - sed -i 's,\.exe,,' "$QTDIR/qtwebkit/Tools/qmake/mkspecs/features/functions.prf" - sed -i 's,\win_flex,flex,' "$QTDIR/qtwebkit/Tools/qmake/mkspecs/features/default_pre.prf" - # - # TODO: find better fix !? - sed -i 's/FLT_MANT_DIG/24/' "$QTDIR/qtwebkit/Source/WebCore/html/StepRange.cpp" - sed -i 's/DBL_MANT_DIG/53/' "$QTDIR/qtwebkit/Source/WebCore/html/StepRange.cpp" - # - # - SPECNAME="win32-g++" - SPECFILE="qtbase/mkspecs/${SPECNAME}/qmake.conf" - sed 's/qt_instdate=`date +%Y-%m-%d`/qt_instdate=2011-01-30/' -i qtbase/configure - #sed 's/EXTRA_LFLAGS=\n/EXTRA_LFLAGS= --enable-deterministic-ld\n/' -i qtbase/configure - sed --posix "s|QMAKE_CFLAGS = -pipe -fno-keep-inline-dllexport|QMAKE_CFLAGS\t\t= -pipe -fno-keep-inline-dllexport -isystem /usr/$HOST/include/ -frandom-seed=qtbuild -I$DEPSDIR/include|" -i ${SPECFILE} - #sed --posix "s|QMAKE_LFLAGS =|QMAKE_LFLAGS\t\t= -L$DEPSDIR/lib --enable-deterministic-ld|" -i ${SPECFILE} - sed --posix "s|QMAKE_LFLAGS =|QMAKE_LFLAGS\t\t= -L$DEPSDIR/lib|" -i ${SPECFILE} - sed "s/src_plugins.depends = src_sql src_xml src_network/src_plugins.depends = src_xml src_network/" -i qtbase/src/src.pro - #sed "s|X11/extensions/XIproto.h|X11/X.h|" -i qtbase/src/plugins/platforms/xcb/qxcbxsettings.cpp - # Before we tried to pass arguments to ar (static linking) in using QMAKE_LIB, however - # qt removes the arguments for ar and provides a script which makes it impossible to pass the determinism flag - - # so rather than try to replace ar, post-process all libraries and plugins at the end. - # - # Don't load faketime while compiling Qt, qmake will get stuck in nearly infinite loops - #export LD_PRELOAD=/usr/lib/faketime/libfaketime.so.1 - #export FAKETIME=$REFERENCE_DATETIME - # - # fputs not in std namespace? - #sed 's/std::fputs/fputs/' -i $QTDIR/qttools/src/windeployqt/main.cpp - # - CONFIG_OPTS=" - -opensource - -confirm-license - -release - -static - -xplatform $SPECNAME - -no-audio-backend - -no-glib - -no-dbus - -no-cups - -no-iconv - -no-gif - -no-freetype - -no-nis - -no-pch - -no-qml-debug - -nomake examples - -nomake tests - -no-feature-style-windowsmobile - -no-feature-style-windowsce - -no-sql-db2 - -no-sql-ibase - -no-sql-oci - -no-sql-tds - -no-sql-mysql - -no-sql-odbc - -no-sql-psql - -no-sql-sqlite - -no-sql-sqlite2 - -prefix $INSTALLPREFIX - -bindir ${INSTALLPREFIX}/host/bin - -device-option CROSS_COMPILE=${HOST}- - -icu - -v - -qt-libpng - -qt-libjpeg - -system-zlib - -qt-pcre - -no-pulseaudio - -no-openvg - -no-opengl - -no-xrender - -no-alsa - -no-mtdev - -no-mitshm - -no-kms - -no-reduce-relocations - -no-egl - -no-eglfs - -no-linuxfb - -no-xinput2 - -no-libudev - -no-gstreamer - -optimized-qmake - -skip qtwinextras - -skip qtandroidextras - -skip qtmacextras - -skip qtx11extras - -skip qtsvg - -skip qtxmlpatterns - -skip qtdeclarative - -skip qtquickcontrols - -skip qtmultimedia - -skip qtactiveqt - -skip qtlocation - -skip qtsensors - -skip qtconnectivity - -skip qtwebsockets - -skip qtwebchannel - -skip qtwebkit-examples - -skip qtimageformats - -skip qtgraphicaleffects - -skip qtscript - -skip qtquick1 - -skip qtwayland - -skip qtserialport - -skip qtenginio - -skip qtwebengine - -skip qt3d - -skip qtcanvas3d - -skip qtdoc" - OPENSSL_LIBS="-L$DEPSDIR/lib -lssl -lcrypto -lgdi32" ./configure $CONFIG_OPTS - # - #make qmake_all - #cd qtbase - #make -C src sub-corelib sub-network sub-widgets sub-gui sub-plugins sub-testlib - #make -C src sub-corelib-install_subtargets sub-network-install_subtargets sub-widgets-install_subtargets sub-gui-install_subtargets sub-plugins-install_subtargets sub-testlib-install_subtargets - #make -C ../qttools/src/linguist/lrelease - #make -C ../qttools/src/linguist/lrelease install_target - #make -C ../qttranslations - #make -C ../qttranslations install_subtargets - make $MAKEOPTS - make $MAKEOPTS install - # - cd $QTDIR/qtwebkit - sed 's,type nul,cat /dev/null,' -i Source/WebCore/DerivedSources.pri - for TARGET in Source/WebCore/Target.pri Source/WebKit2/Target.pri Source/JavaScriptCore/Target.pri Source/ThirdParty/leveldb/Target.pri Source/ThirdParty/ANGLE/Target.pri Source/WebKit/WebKit1.pro Source/WTF/WTF.pro - do - sed --posix 's/^CONFIG += staticlib optimize_full/CONFIG(shared, static|shared): CONFIG += staticlib optimize_full\nCONFIG(static, static|shared): CONFIG += optimize_full/' -i $TARGET - sed 's/^CONFIG += staticlib/CONFIG(shared, static|shared): CONFIG += staticlib/' -i $TARGET - echo "CONFIG(static, static|shared) { - target.path = \$\$[QT_INSTALL_LIBS] - INSTALLS += target - }" >> $TARGET - done - $INSTALLPREFIX/host/bin/qmake CONFIG+="release static" - make - make install - # - # post-process all generated libraries and plugins to be deterministic - # extract them to a temporary directory then re-build them deterministically - for LIB in $(find $INSTALLPREFIX -name *.a); do - rm -rf $TEMPDIR && mkdir $TEMPDIR && cd $TEMPDIR - $HOST-ar xv $LIB | cut -b5- > /tmp/list.txt - rm $LIB - $HOST-ar crsD $LIB $(cat /tmp/list.txt) - done - # - cd $INSTALLPREFIX - # Remove unused non-deterministic stuff - rm host/bin/qtpaths.exe lib/libQt5Bootstrap.a lib/libQt5Bootstrap.la - # as zip stores file timestamps, use faketime to intercept stat calls to set dates for all files to reference date - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 - export FAKETIME=$REFERENCE_DATETIME - find -print0 | xargs -r0 touch # fix up timestamps before packaging - find | sort | tar --no-recursion -cJf $OUTDIR/qt-win${BITS}-5.5.0-gitian.tar.xz -T - - unset LD_PRELOAD - unset FAKETIME - rm -rf $BUILDDIR - done # for BITS in diff --git a/contrib/gitian-downloader/bluematt-key.pgp b/contrib/gitian-downloader/bluematt-key.pgp deleted file mode 100644 index fb6d9eb284..0000000000 Binary files a/contrib/gitian-downloader/bluematt-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/devrandom-key.pgp b/contrib/gitian-downloader/devrandom-key.pgp deleted file mode 100644 index 71898127ba..0000000000 Binary files a/contrib/gitian-downloader/devrandom-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/gavinandresen-key.pgp b/contrib/gitian-downloader/gavinandresen-key.pgp deleted file mode 100644 index f81f44e874..0000000000 Binary files a/contrib/gitian-downloader/gavinandresen-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/laanwj-key.pgp b/contrib/gitian-downloader/laanwj-key.pgp deleted file mode 100644 index 559295109d..0000000000 --- a/contrib/gitian-downloader/laanwj-key.pgp +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: SKS 1.1.0 - -mQENBE5UtMEBCADOUz2i9l/D8xYINCmfUDnxi+DXvX5LmZ39ZdvsoE+ugO0SRRGdIHEFO2is -0xezX50wXu9aneb+tEqM0BuiLo6VxaXpxrkxHpr6c4jf37SkE/H0qsi/txEUp7337y3+4HMG -lUjiuh802I72p1qusjsKBnmnnR0rwNouTcoDmGUDh7jpKCtzFv+2TR2dRthJn7vmmjq3+bG6 -PYfqoFY1yHrAGT1lrDBULZsQ/NBLI2+J4oo2LYv3GCq8GNnzrovqvTvui50VSROhLrOe58o2 -shE+sjQShAy5wYkPt1R1fQnpfx+5vf+TPnkxVwRb3h5GhCp0YL8XC/BXsd5vM4KlVH2rABEB -AAG0K1dsYWRpbWlyIEouIHZhbiBkZXIgTGFhbiA8bGFhbndqQGdtYWlsLmNvbT6JATgEEwEC -ACIFAk5UtMECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHSBCwEjRsmmy6YIAK09 -buNXyYQrJBsX16sXxEhx5QPKyF3uHJDFJv66SdnpvIkNoznsaPiRJkbTANop93FZmaGa6wVn -zGDiz7jPA8Dpxx5aAYPhIT+zPJAdXWM3wJ/Gio9besRNzniai8Lwi5MZ9R/5yFGBobm6/AcN -4sUoqA3NSV2U3I29R0Vwlzo8GVtmyi9ENSi6Oo7AcXNTRt69cxW4nAHkB+amwwDJlcAb31ex -bogYXPhScwqQZixRr+JBkKxBjkTXXnQypT4KI5SegYwQVYfyiZmDP7UHKe/u6pSKKbVphLg8 -xLB5spcXse8/a2+onrbNlw6y8TXiJ++Z54PE7zztWTXf2huakeG5AQ0ETlS0wQEIAMNO3OkP -xoPRKWzBLcI7JRITAW+HNaLTq3uN2+4WxA57DEjbL9EDoAv+7wTkDAL40f0T+xiu6GJcLFjw -GJZu/tYu7+mErHjrdo+K4suCQt7w5EXCBvOLjhW4tyYMzNx8hP+oqzOW9iEC+6VV91+DYeqt -EkJuyVXOI4vzBlTw8uGow8aMMsCq8XVvKUZFTPsjGl197Q5B3A+ZOFCR8xqiqdPjuz6MglVV -oFdDNu3EZn8zkGsQlovXoE9ndVeVzx/XMNmsxFaMYsReUs253RIf1FEfgExID0fg2OnyLCjS -2iFW1RgajS+/saIkKl+N1iuMzJA7wMAM0plhRueOG0MtZSsAEQEAAYkBHwQYAQIACQUCTlS0 -wQIbDAAKCRB0gQsBI0bJpmsDB/4waenn2CvSHXyomykfpwf5lMte1V5LvH3z5R2LY+1NopRv -LSz3iC39x69XWiTbhywDfgafnGPW4pWBOff2/bu5/A6z1Hnan1vyrRRD/hx1uMJ7S6q+bIvZ -iVIg1p0jH6tdIIhwX3cydhdRZHo7e9oSMgOUWsr6Ar59NRo9CENwGPE4U61HXfOnxWdrFWoA -XdwZczBeLxmUy6Vo6sKqv+gE4bqrtAM0sY/MsQ9cU95x+52ox/sq44lQMwd3ZBYUP7B1qbHI -hZSZuch6MLi5scLPeau0ZvCaljiaMeivP5+x0gWPRs0kI+9sZxInbqvrsJ6oOBJM3xYGhtn1 -zZ7qmZR7 -=si/k ------END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/linux-download-config b/contrib/gitian-downloader/linux-download-config deleted file mode 100644 index aef614d0ca..0000000000 --- a/contrib/gitian-downloader/linux-download-config +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: bitcoin -urls: -- http://bitcoin.org/bitcoin-latest-linux-gitian.zip -rss: -- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss - xpath: //item/link/text() - pattern: bitcoin-\d+.\d+.\d+-linux-gitian.zip -signers: - 0A82509767C7D4A5D14DA2301AE1D35043E08E54: - weight: 40 - name: BlueMatt - key: bluematt - BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: - weight: 40 - name: Devrandom - key: devrandom - E463A93F5F3117EEDE6C7316BD02942421F4889F: - weight: 40 - name: Luke-Jr - key: luke-jr - D762373D24904A3E42F33B08B9A408E71DAAC974: - weight: 40 - name: "Pieter Wuille" - key: sipa - 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: - weight: 40 - name: tcatm - key: tcatm - 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: - weight: 40 - name: "Gavin Andresen" - key: gavinandresen - 71A3B16735405025D447E8F274810B012346C9A6: - weight: 40 - name: "Wladimir J. van der Laan" - key: laanwj -minimum_weight: 120 diff --git a/contrib/gitian-downloader/luke-jr-key.pgp b/contrib/gitian-downloader/luke-jr-key.pgp deleted file mode 100644 index c40917d78c..0000000000 Binary files a/contrib/gitian-downloader/luke-jr-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/richardsmith-key.gpg b/contrib/gitian-downloader/richardsmith-key.gpg deleted file mode 100644 index 04d1d538be..0000000000 --- a/contrib/gitian-downloader/richardsmith-key.gpg +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.10 (GNU/Linux) - -mQINBFAsDREBEADD88DdBoGu/rMpNYWyzXNWfHI5su/JX1tfzM/pb/iSrC4ywOtZ -P7wCqqAB1lhuT94j2m8kpv/VSb98Q7ZURxbwY/zEQnDuifiBCj5hO4lWTdSKgmLy -8xVR7WHEYCscKFl92mG6tqDewnD2oX5NyJrFeXPAM9R9jBIDc2oyUVznv5Rb2YUp -D4rdIHbEMoe524Ucw8ez5Kxtf0OW0Zbrraq1utbcL3B99FMnoSaXq5AiGTmcI3Xm -Mx8T8E6I2gd6ZLEtJbgzG7B8so/0tbpGIYExzatjWEzuDEPAgAB028nNWf8q+SE+ -G3Zo/ZrCenGYPmDKIaSlqmdhqHe22AGtn+k6gzvLVN9MHY2exIWhu2R8uw6cGCbG -piw7HPDR0epgf5im50rr/k9ZgELhURqDezeHCwRBFtBZd+1sLgzMocYybq7XM9e6 -dcHRZoXamlMibKoYMp30jfyb5mVYwnOJAQNUkFxwZOJXONOvwEyO+89ep0c7H/I5 -h/4F7UGTpRB84HpkZCK+rxOg90UpOQEAA1OKi2od5DNBtu9JnXOD8Ki9lXHaGgL2 -H6Q+ugntvsYmcJZ22IkymZ1DPaEPJa8Y/pwovl9rYac1A1v9PFkl2XsE2EZyipmF -QjTSimnmvCCIXFSG7yN4iP/H/+vP8kdV2HuPfLnq7i0uIe9q9s0ogtZEpwARAQAB -tCVyaWNoYXJkc21pdGggPGljZWVhdHNjcmVhbUBnbWFpbC5jb20+iQI+BBMBAgAo -BQJQLA0RAhsDBQkSzAMABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCiiuz9 -atLt+MecD/9qO/1ALT4EH5MewKG6mMT9hrbsIf07Cc0uKl4/hpbElK2iEclcXdj6 -fXyxVF0+1Vl8Bfkj47n4sL8aOmVjZ8YpFcW59GqE9Me9Sw7bPE5x8Ly2Am+NMkhz -myq3aJX54bzUGvBxCNwZYV46DxKjsOLrw2I/Tzt2zjzROlCW/r4IpEuFAQY5zzNv -YryzWuaJF27pVZH2od9X0nEfn7qBoDYWEtvlI5jfsL4HI0bd4Ws9xMrkjHKBaFaC -H5sxZS7mxicTRf4qeP/XKxdEI461sg28wYewnIBqYm8OEkwFS3YB51hlA1ufi3Za -m5sMmiut8H5jq0QXH+LWWQAADOnCbMrr3zbkaueMvLzjUsR1EtbYlpGPHXwk9eVk -9XckZ1hMjUl5VCBLzquuGuJonUfb5plxEDJ2MCkkkhBJ6DR3yMpjS//ogi52fwlI -0yltpyXUXcgURwvQ1pwpTkjbD09KqUmxViULFMLXT3e6vRc5pH9e7mja5LxSe/No -Kqm0RdFlM/2CMDQ0ByNUGWjAPozuxm5PeO0ypS3+tDBiLcgZnayWelsuHzR4BCmk -LkXiNTrIlXSJpBWsg5D99ni8VrFGLwn9PBaDrOsztfL8iDFgVUzPbizbEEAbKiYq -lo/qnq2nrxR7YtChJQwhKlc0NHOWmqJOp2+AIW+L1LfDiVo3wuH6XrkCDQRQLA0R -ARAA0e4sHZQDTZZ9DdmML1yhL9C0DqsBaDTiKQY+s9lanrjSs7HKgv8bK+gTNvng -/O0M1/xhSOsgepq5lpdl7h5QqGZ1oCSF3QYxCeGe85g9SKBsUFNbYwdS2JXBwO3V -1euBM2pNSmNL0PYiTsWylUQPymUZ4ww2n6giVYWmsEqSF/Ld/kkfODzJAP4AwBIJ -f+2GY+vWcvxNKES1JT98p/dlMMMXeDKqcXIIzoZbnpk5gd21oGXbMwaf9s8bK8ob -BMqZCORmSnG9npRSfFXDHSa2983nGPUoL8bMzeyDu/1PViclxTWtI012gYp99pRm -JXzGiGdBmuLItAQW5o8DWXfiiobYd5H0+PfAX62H5oXTWH1T5jblyxcyA+fYU71t -wCRZ93OEHv0Q/RafH6Fr+ltZVnpPmYpJ4gyWpyoP2j91N6KaVyrfbCaN0Cyv4bQG -JCg8Ss8UqOnsFj88KikYwRMVxJp5E6MpM0yEuIU+vrB+58yOmeNCQ+LwBNnltCmC -9v0YYibMbmUv4wRvScGHPAfJ3CWndRbIObXoMlLs9nayMCqpBTEDGhTKheocQdMo -aLt3OJsaTmFKE7iFGKImGgUdD94kbkzb7R+ZRlI9mNNiq+Kuj19CSAVdM9vttjyt -whPYPR6d4GNWZFS+Gg9k2Bv7O2cDYh78Go7ywuAtPkcTMv8AEQEAAYkCJQQYAQIA -DwUCUCwNEQIbDAUJEswDAAAKCRCiiuz9atLt+PAXEACLd967Sz06DpjMHqgHahCr -m1Kt13EM/mbrnoFJWePTp1JAtlzSMXKsWo7zOCC71dyI8PEfjylsZiuC3uL54DDl -JlQmlXa6/qi1KnqroJEkZ+YoDnIy/jiN1L3SqMVwUeQrd5N0koPZflpnoAq1np97 -wWDwK8NqALq5VsqXhVWvXeqjDM1q9+7fO7xDQLFZ0MNhqoMBdE4QRRkw55XWJKS9 -RI/hxDFuCJlK04eFTU/5pUSksEZZ0vl43YkXlN54qiyOvkVL2Aq9gVgvdaqGbG8x -kVSEtJK9XTwlo+BA/sFCMlR4NL1XCrrvv9/1SwiFAFSV4dz6Cg9ObAonNh0mbnwj -IaaBzS18pqRzqZg69aZzlKp6LxBYOmZTQuPiwdF0Cn/b5VNtgLKInmOvDvpHFWE2 -H4dU3Al/B+3o1Bm24mAgLQHGFh4GN4BV1ge+Lijiz+N0sUfPsqtHaP3RNZsm/4oL -zyVuoSMRL+NtkB03SID7CBzrVLGWRGgeWjLfLz+wnrDGlWz0N7dKJx76nayTvsM2 -xd81jat8FyHFFoB5D4xn+czbkCq1k3giyKqilz2NNXX0G7kUiU0D+tvIb76qP389 -9uiMAuC5q1Ibo+k3pOZrWWHX3c9HB1Qlry9Qw57Y4ncqjRcdMf884da5mTmCjl/d -EwL78xfzdw9iYRRwoeP+IQ== -=jMKy ------END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/scottnadal-key.gpg b/contrib/gitian-downloader/scottnadal-key.gpg deleted file mode 100644 index 678ec7e962..0000000000 --- a/contrib/gitian-downloader/scottnadal-key.gpg +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.10 (GNU/Linux) - -mQINBFAs/eYBEADJq87tlE9Lu4dtgzKcnLrY6m7Eab3fPL4aW+g1PC3O4rMn2jjT -vp4TU+DHBgt9r+DBpiK48v9fd3BNpg8mB25pDgdWtoBj64D1YxlU/NxbwnR4SGDD -nSCjp/Z+ZxTCjUHfAu384P9nsSvMFksVhhzgd9JXvxJzB61odjgPRVs5buJtLzrg -v7jJdBZPDC2R9kJIggdrrN4sWhE9o3VQ4kFMxEu3KGJSLZuGRdwr1Ni5jxpo1Hio -Xf1LDKJ5+kTb2YpHL9trxe9ELt3HLa5mryCVff1wwN+MBwsXdvxTjF2RXJUWbKlC -M78DjLCCyM5T1XPb4D0dp/olEhNqI6IrBhR9rEOVR5Rbsl49lfhQIUEDAVlogAoG -yzwQMO/NGOD0NUgQV/7ZIN1fpKPuipJsCId2UvzuxzjwtMf20VUI5OPKRk122OOv -9c91y9fI9H6rgHKcS96HLM840pkQmr00CpsEtCjtYxvOKCakCcbq4SHZSrB2gjcK -msY/DfEjO5An/LXh5IbEiSSgSXfCTSXMU7yB36yX4CniIDTEe044DlTwhSGUnw65 -alTp4taaswjB+yhAWI5IXOGifFyOAFW0BhGpDHuWoevUHKYXMla9czB0Jn1VIX/E -bAPxi5sZKHjhhjZY6ngZAO2HXliWHXIeLvwjUdE0+AAP5B+eh7kyMV7mlQARAQAB -tCJzY290dG5hZGFsIDxzY290dC5uYWRhbEBnbWFpbC5jb20+iQI+BBMBAgAoBQJQ -LP3mAhsDBQkSzAMABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAu6TbaW7w+ -y477EAC9yNgDSSdSmqUVQdrPdEn1RyZl4sjAznuRk+CKffi83/ZwjZJkT12GapPF -9/wW/YXGGbb2wUK17xIz8ZcKCjZeSf8w0HNwFfy8bOOkewpJ3QMp+PO61KTa1sfn -hJvPKQTxKAM49tiq1O/x5hppKCrJjPzlH41+4rfrFk7+v5ZHusIDqxIzepS+MyNy -fhmCq1Pd2w/R3zHIDH7R8uuuJKDDkZhhJgQjjxGo4Mqo6UaJOHsmLNGmQi+at/Eu -BssrO2OHSShCvA6/fvKXN4XEFxm7w3WUylw3h47j1hXhQClqBJrLA08N7+iNqKKg -DX2ePpWIptwjJyqn/6UtEfFyeIBQITpxyrVoWCtdnNdo03AQpraPV8DICyxQY3e9 -FFKkrod+XKeGqs7Lsk5mPUOQVl7KoCfmW+M1vcvEpK7wElSRUdy0Fw0s6BiYN1xH -baOsBIvc1KWN9x//ctJPcjxEONiPDKv1dyWUYIWieSTrFjP6aOLoe0uGkDXxxlEs -4X4ZAgLUXs4j62on9lsFH1pVAQOpbmVS06vmmHQTR3skG9D8s4jVn1dyJQ35I0ml -P0IH4DazTTld6laYptd4CqlohotME+yh9VqiQ0Tg1u6L4VwYsBN6AKGgOq+T8T0b -VPNK1+Si9Poq4J/wPPqUQRzxSgWbX5Ho/k+6t0R8dpne6oFGrbkCDQRQLP3mARAA -mIA7DN9DT1xN0uazTRXV4lqFTuG+86iPU35eUtReGcChYwq0V56bV+gywObo4fAP -QsynzCUvtk+8FSL++SLysIaD/VAu3YAqsI/shzA/KG77ZqgR3/E6pnkaN8aFVPRf -dFFbBYioXP2MkOMd2MqPSnUI5+dMKnJ4HBQvucG5yxdR7VKP9VxBwQcfZEcE+l8a -yRyaAr3NNDm69Qxb6TeiJlwSQvcY4FhnP9EpIW11DEIvCEKKr6X0UoWFTm7dSfLk -n2e1IsK1kk3Uy45KzrR/4dYB7PhEP0VjLZ4bueXMjvZW8YBUoC6emOU/3B+/j3GO -N+62XE9u0Vsh2uzRnOqjucn+i83Og7+1VaXVRh77giWTlDTAeJARRGa6ScmxI9Vk -MJgbe2oseDxTv9QF5guqLUNe0MlUZ/9SXXjou/D+L/S9Beo775sfn57gANDbaGRm -9795YyAHphl26Qp7es3uj99mlK7tGDHajb2JkJutMtaevGuVNN9QlUrhr7klPOAd -6jdAxsU9Sn/gnUBZJbCFoQlUveEjkSu24/tYoo6Oy7VgMxwt/CMhB5HzVOpY20Ym -BDTO9P9MBeD0/wSPyanHc+XVepXWwsp4EC5RVnJFLf+o3vmeQYqiF0qXuapLmLnK -XqSD+M+uIr15XxTLLx9vsjUVN/xkLu7DCgyVeRA3ytUAEQEAAYkCJQQYAQIADwUC -UCz95gIbDAUJEswDAAAKCRAu6TbaW7w+yxsEEACu+7g6trtjYQZ3FStCK8OZOAJl -jefUONgZX8woSSmyeVlg5Ex9cSvAgfOhiM2J2+K8aI53woOsiE3LihElaX+Qi+hE -GgjsFdd6lNn3i5gFydDHs6uLvtVAXxAOOOaXWT/ucsTgBRGcY4H1QYlkTGD8Xsf8 -qyUOzP/s8RQbvIrGrQtLN3O9r8wDBzDdZZjp/IZZaY6VT1r3AvF2mX+ip8/OqxNc -Yd3qxf8s7Kyn0eChSq1DAp83XMWxCje2EwXXzDA7Jd0pMAppWevFks4INGyCxz+9 -jOZ4Ris2a907ShWmIg8bw40r5L69j59qPk0fr44X6XVguN9zmKpLV5fyY88Qy9iq -8uy/3UVprZ0LnPbBXhbDsFkgiDOo2zCJfaVhPirMlpPJg/T5pFyAt+klrq6bD+tD -50Hh9gOpXXg58bELJhOtDUCV6Froc99LeqoBvlKJWqr58QguO2mn1cFJcP+nVzxz -DBpB/dWsmQst/NQ3YlgfVr6CcgqlCqVI4yNT91Q5Ns8/pdkcUBIVDUC+4oyKwA4n -XZMmydPJDdUiluwVSeIw0N/jiZhBJvMJHlOQ3xmb8In0WXcnE5JbibCITTN/T224 -jL14ObF+aMWlFanqRDUwllEQFv0Wa9dgTaHzxl+l9Ojw+YaYt/96UTtEJaMaxmww -JzdBFnCP7RoNHIQ20A== -=CQsQ ------END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/sipa-key.pgp b/contrib/gitian-downloader/sipa-key.pgp deleted file mode 100644 index a52a5deb1b..0000000000 Binary files a/contrib/gitian-downloader/sipa-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/sunnyking-key.gpg b/contrib/gitian-downloader/sunnyking-key.gpg deleted file mode 100644 index 16b2a40b3c..0000000000 --- a/contrib/gitian-downloader/sunnyking-key.gpg +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1.4.10 (GNU/Linux) - -mQINBFAsDOMBEACysMqtJfC7ikO2o+ioQZvHSSbL2R2zdgYxPjtQvLqbNMiJyV3q -vwXGWh0Z3eGu/cpHvfN6mguwHqgh319AtU6wiOHX/1yGMf2MUNFhoh8RlDWhZ+ba -gMTv7pcZKE2Ca7JgDtLNWd+NpjYrlGDSEEFl2vTohKKd+V7hRjyMc8iLkLjVdtdd -OTuFQeyNB8DUMUr3GuaPr52RgidZdMbJ0QSnEQeN9/ZTYjmYfREO+mal+2G/OKMk -6naUcGrhwHimc02WDddkqMhe5eZsU3XG+WqrD5NkN3my72XjkqSE1++k2+XgnOon -pUOciWfF3R3RBlOn0MlfKvNa/GXZ7PFxke3tkxdym8BV10l8spV++tPuhxovR7Gp -XG8Mt66uxlFc4S9wTg5FJilk2W75LK+FjFLAk9gJ24IHUawdSpLdCM+a4/JL1Ys+ -CQUuQA06Xdq3x8iuZSduRrnLeFEkM/F6JmyH22L8b5ptIm/wgjCaa+R/8P5ROO/E -FM1z7sw2RK12ZNPqwrNysePSVze2MGNdPnmb2KDcxSlxoK6Nzcef5xGkP/WwdBnd -WN2iA70I0S8DEywpY3hrJ4YIDg+SvCsoRIBH90PUORQ5Uhfj15QbmT2bZrqoFaDY -1+dWmijsPJ6+6MYjDWte/WVDSqTJEa22R/SAjGETGmUig7OqE7FFaQFLPwARAQAB -tCNzdW5ueWtpbmcgPHN1bm55a2luZzk5OTlAZ21haWwuY29tPokCPgQTAQIAKAUC -UCwM4wIbAwUJEswDAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQGPNEBNK5 -Xmp4hg//f/rUs1ABrsd7ciHN0ByOH/WKdlUNNvf8jua86mHdPcHAFtZ3HC8ICVLe -7TAUMEgQ1Vsmk1QBILCaE50cD9iya4uCYCpBN6RZXUd09Te+ugb+VUYda4NmVbF+ -ZYidDjLwFZ3MV4uXZLWMGnxVDYVrBDHdfvFkZvi+/thtEME+Ea84diBZcAW/ncUb -AMNxNsmOTlTcPuB47UZVxg2vSJWkJe9O6IpuF782+49O14hsxidPMV+BKOaYWwoj -wGlJ+NDkobaQ/a0lI0aGHL1KXA58mNMB0i7SoYB8YJMfL2+lx0AZsvxaqFmuMcPf -zo7I9UCyf/gHorQaxsbz2/LUfpFL4T7IWt9IJkVe8TT9KQV8T0l9uUaQtX3iLwqQ -IRJWdQZMpnENhEgkSLRSkmCV/162ksYoboSpfI3Qhz1h0yqnwHAGBKSbE/2IGVo5 -3m/27xUFy5+7WeiON7DelYS6mx4UiAkhSWj4/u60YNnq5eTAYQFqawtSwIiO9pLH -C1gqOCoakESdFCQfABNsI6paIkfTylZhLd20qrr9qvBfvOgpMRXbO6xBPYp92/UK -9uRkFFCJORLBUl9saLfZa4Hw1CcY06IA3XXBx2/kp42aeAnWrfzqLvXwFZGtOJie -ajQsJUeDLFjbsYmw9FP8izK2H6plEa3PLFDz2gP+MSLZ5+13eES5Ag0EUCwM4wEQ -AMTFatCCzaUPwFpM9GyC7JwIWofDRpZBigXnzTC8RwHnb1ruWliFUkTEeSB8z7pC -3DaQ+owf0TUqj0c8Ui3SVfCcQqIJuWBycxxUnSaqWvz7wRaRN+WG4gaWgA2z7k4Q -CMmVhbxTaaZ67rfqtFOKM7EaIqOBE+AKg5BCCrxnja/xR0eZxRLwZKXqfakgqXy8 -HaWOzLPU6zMheTXu4YW5S6jvZOaMRkKI5xEUdQf/UPYkwYM6PaA/o70rTSGuQ/mc -zwFZp7FxKqKINPBSJLu1CjhnnrZM37y26I5O+nErDTinvYg5Rkq5wV3gMNbzpOdA -qPdw2qkVwKWDErNrA9amKuM0/fpvu/kXkGnfkugvt3Rokc3MQO2u5HI1eO571zaV -GoDt1oYjpKPuu6JMe2b5D1fLhyHicGaH8V2vpJi6+01Ww09srKemox54J4Z/Xjw6 -gyaWuPkCHO3roNjeGMtzbbJeOYEZC/AMTuqmnv3gHXENgrxKjCkkGddH8t7nZUNT -zmTMHrqOzhacRIp/6jpKCNXea2FaeRQECtDD2awNxUpmFFQeGpXJGsGc/GYHqvtV -HxWOiio1BpHhjCySHCYpqsq/GtGVdxNVz6o7H0/i4wipT7Q2dKVKbSuapaqI01jv -40019gtjOV7Gw8fX0MLt3ViCQVHpDxdMN/vkumw9YKA1ABEBAAGJAiUEGAECAA8F -AlAsDOMCGwwFCRLMAwAACgkQGPNEBNK5XmpymA//UXydFKX11RGloxzMfdgoFvjw -mNoZeS5Sv22hpsS2XswqAIbGdI/s2PbEzLv6nn0ck1PUFn9wL+TxB9GF2wWelpI4 -qe1mKsedJbj9PG6Wx2Invn6IcEInMrSLspBWiJJL2eP4y1hjAGG4v1wxPXQ4/FNe -OvXzAwShz79nVY35MDPBpL/dlhRJAIe/T7pYiI/HB8p4bI9MbtJcfp61oRPt17UC -vIQFnKKkwPT99i3PsOqAa8mVa2Ae4EElHG844Hr89ptHrGjudssfBf4kOaENMQqE -MFlyGaT9CLrD/2Qs/rXqFz3VAQykw/Cuw0kiRJjS5xKZZjVbz3Zd9suklk6YkSpI -jLzcPPON8nC6wvtUus5d0gtQeGx2DaX9n2+ubKlZgTSvT41PO/2Th9o3CgptHYJT -59ncrZP515yd0ZMknZ9bFt9BaE3V17hblOjFXoFqmAhwXyHQD9Ffd62AO1h2JNx5 -BAr4D7VyxJ3WX1yJFtdGsU7iD6ko4HahRepfp8UMtyVRLWVPGVmNq38Tozb4dhyh -fk3MxiatbEXQZbvFVr8WfGoNOIXB4Kg68NGxwZv6Jd5lobDOQjVYOykD2UpuOXmY -VRanFk5eIy0UWYAwUNP+XnjGHdwtX4ZYh+O4wDnWEZd4soVMXzOBuyWTSKahHhZi -KIjGheFAFTRFLgBmol4= -=Qxzm ------END PGP PUBLIC KEY BLOCK----- diff --git a/contrib/gitian-downloader/tcatm-key.pgp b/contrib/gitian-downloader/tcatm-key.pgp deleted file mode 100644 index baaec76b8c..0000000000 Binary files a/contrib/gitian-downloader/tcatm-key.pgp and /dev/null differ diff --git a/contrib/gitian-downloader/win32-download-config b/contrib/gitian-downloader/win32-download-config deleted file mode 100644 index 0f7032e643..0000000000 --- a/contrib/gitian-downloader/win32-download-config +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: bitcoin -urls: -- http://bitcoin.org/bitcoin-latest-win32-gitian.zip -rss: -- url: http://sourceforge.net/api/file/index/project-id/244765/mtime/desc/limit/100/rss - xpath: //item/link/text() - pattern: bitcoin-\d+.\d+.\d+-win32-gitian.zip -signers: - 0A82509767C7D4A5D14DA2301AE1D35043E08E54: - weight: 40 - name: BlueMatt - key: bluematt - BF6273FAEF7CC0BA1F562E50989F6B3048A116B5: - weight: 40 - name: Devrandom - key: devrandom - E463A93F5F3117EEDE6C7316BD02942421F4889F: - weight: 40 - name: Luke-Jr - key: luke-jr - D762373D24904A3E42F33B08B9A408E71DAAC974: - weight: 40 - name: "Pieter Wuille" - key: sipa - 77E72E69DA7EE0A148C06B21B34821D4944DE5F7: - weight: 40 - name: tcatm - key: tcatm - 01CDF4627A3B88AAE4A571C87588242FBE38D3A8: - weight: 40 - name: "Gavin Andresen" - key: gavinandresen - 71A3B16735405025D447E8F274810B012346C9A6: - weight: 40 - name: "Wladimir J. van der Laan" - key: laanwj -minimum_weight: 120 diff --git a/contrib/macdeploy/DS_Store b/contrib/macdeploy/DS_Store deleted file mode 100644 index b0cf9225e2..0000000000 Binary files a/contrib/macdeploy/DS_Store and /dev/null differ diff --git a/contrib/macdeploy/LICENSE b/contrib/macdeploy/LICENSE deleted file mode 100644 index 94a9ed024d..0000000000 --- a/contrib/macdeploy/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/contrib/macdeploy/background.png b/contrib/macdeploy/background.png deleted file mode 100644 index 3be24dc04e..0000000000 Binary files a/contrib/macdeploy/background.png and /dev/null differ diff --git a/contrib/macdeploy/background.psd b/contrib/macdeploy/background.psd deleted file mode 100644 index dab835c77a..0000000000 Binary files a/contrib/macdeploy/background.psd and /dev/null differ diff --git a/contrib/macdeploy/createdmg b/contrib/macdeploy/createdmg deleted file mode 100755 index f30a62c445..0000000000 --- a/contrib/macdeploy/createdmg +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -e - -OTOOL=${HOST}-otool INSTALLNAMETOOL=${HOST}-install_name_tool STRIP=${HOST}-strip contrib/macdeploy/macdeployqtplus Umbra.app -mkdir -p dist/.background -install contrib/macdeploy/background.png dist/.background -install contrib/macdeploy/DS_Store dist/.DS_Store -install src/qt/res/icons/shadow.icns dist/.VolumeIcon.icns -cd dist -ln -sf /Applications Applications -cd .. -genisoimage -no-cache-inodes -l -probe -V "Umbra" -no-pad -r -apple -o umbra.tmp.dmg dist -dmg dmg umbra.tmp.dmg umbra.macosx.dmg diff --git a/contrib/macdeploy/fancy.plist b/contrib/macdeploy/fancy.plist deleted file mode 100644 index 387119aea0..0000000000 --- a/contrib/macdeploy/fancy.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - window_bounds - - 300 - 300 - 800 - 620 - - background_picture - background.png - icon_size - 96 - applications_symlink - - items_position - - Applications - - 370 - 156 - - Shadow.app - - 128 - 156 - - - - diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus deleted file mode 100755 index f58afcdef9..0000000000 --- a/contrib/macdeploy/macdeployqtplus +++ /dev/null @@ -1,882 +0,0 @@ -#!/usr/bin/env python - -# -# Copyright (C) 2011 Patrick "p2k" Schneider -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -import subprocess, sys, re, os, shutil, stat, os.path, time -from string import Template -from argparse import ArgumentParser - -# This is ported from the original macdeployqt with modifications - -class FrameworkInfo(object): - def __init__(self): - self.frameworkDirectory = "" - self.frameworkName = "" - self.frameworkPath = "" - self.binaryDirectory = "" - self.binaryName = "" - self.binaryPath = "" - self.version = "" - self.installName = "" - self.deployedInstallName = "" - self.sourceFilePath = "" - self.destinationDirectory = "" - self.sourceResourcesDirectory = "" - self.sourceVersionContentsDirectory = "" - self.sourceContentsDirectory = "" - self.destinationResourcesDirectory = "" - self.destinationVersionContentsDirectory = "" - - def __eq__(self, other): - if self.__class__ == other.__class__: - return self.__dict__ == other.__dict__ - else: - return False - - def __str__(self): - return """ Framework name: %s - Framework directory: %s - Framework path: %s - Binary name: %s - Binary directory: %s - Binary path: %s - Version: %s - Install name: %s - Deployed install name: %s - Source file Path: %s - Deployed Directory (relative to bundle): %s -""" % (self.frameworkName, - self.frameworkDirectory, - self.frameworkPath, - self.binaryName, - self.binaryDirectory, - self.binaryPath, - self.version, - self.installName, - self.deployedInstallName, - self.sourceFilePath, - self.destinationDirectory) - - def isDylib(self): - return self.frameworkName.endswith(".dylib") - - def isQtFramework(self): - if self.isDylib(): - return self.frameworkName.startswith("libQt") - else: - return self.frameworkName.startswith("Qt") - - reOLine = re.compile(r'^(.+) \(compatibility version [0-9.]+, current version [0-9.]+\)$') - bundleFrameworkDirectory = "Contents/Frameworks" - bundleBinaryDirectory = "Contents/MacOS" - - @classmethod - def fromOtoolLibraryLine(cls, line): - # Note: line must be trimmed - if line == "": - return None - - # Don't deploy system libraries (exception for libQtuitools and libQtlucene). - if line.startswith("/System/Library/") or line.startswith("@executable_path") or (line.startswith("/usr/lib/") and "libQt" not in line): - return None - - m = cls.reOLine.match(line) - if m is None: - raise RuntimeError("otool line could not be parsed: " + line) - - path = m.group(1) - - info = cls() - info.sourceFilePath = path - info.installName = path - - if path.endswith(".dylib"): - dirname, filename = os.path.split(path) - info.frameworkName = filename - info.frameworkDirectory = dirname - info.frameworkPath = path - - info.binaryDirectory = dirname - info.binaryName = filename - info.binaryPath = path - info.version = "-" - - info.installName = path - info.deployedInstallName = "@executable_path/../Frameworks/" + info.binaryName - info.sourceFilePath = path - info.destinationDirectory = cls.bundleFrameworkDirectory - else: - parts = path.split("/") - i = 0 - # Search for the .framework directory - for part in parts: - if part.endswith(".framework"): - break - i += 1 - if i == len(parts): - raise RuntimeError("Could not find .framework or .dylib in otool line: " + line) - - info.frameworkName = parts[i] - info.frameworkDirectory = "/".join(parts[:i]) - info.frameworkPath = os.path.join(info.frameworkDirectory, info.frameworkName) - - info.binaryName = parts[i+3] - info.binaryDirectory = "/".join(parts[i+1:i+3]) - info.binaryPath = os.path.join(info.binaryDirectory, info.binaryName) - info.version = parts[i+2] - - info.deployedInstallName = "@executable_path/../Frameworks/" + os.path.join(info.frameworkName, info.binaryPath) - info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory) - - info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources") - info.sourceContentsDirectory = os.path.join(info.frameworkPath, "Contents") - info.sourceVersionContentsDirectory = os.path.join(info.frameworkPath, "Versions", info.version, "Contents") - info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources") - info.destinationContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Contents") - info.destinationVersionContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Versions", info.version, "Contents") - - return info - -class ApplicationBundleInfo(object): - def __init__(self, path): - self.path = path - appName = os.path.splitext(os.path.basename(path))[0] - self.binaryPath = os.path.join(path, "Contents", "MacOS", appName) - if not os.path.exists(self.binaryPath): - raise RuntimeError("Could not find bundle binary for " + path) - self.resourcesPath = os.path.join(path, "Contents", "Resources") - self.pluginPath = os.path.join(path, "Contents", "PlugIns") - -class DeploymentInfo(object): - def __init__(self): - self.qtPath = None - self.pluginPath = None - self.deployedFrameworks = [] - - def detectQtPath(self, frameworkDirectory): - parentDir = os.path.dirname(frameworkDirectory) - if os.path.exists(os.path.join(parentDir, "translations")): - # Classic layout, e.g. "/usr/local/Trolltech/Qt-4.x.x" - self.qtPath = parentDir - elif os.path.exists(os.path.join(parentDir, "share", "qt4", "translations")): - # MacPorts layout, e.g. "/opt/local/share/qt4" - self.qtPath = os.path.join(parentDir, "share", "qt4") - elif os.path.exists(os.path.join(os.path.dirname(parentDir), "share", "qt4", "translations")): - # Newer Macports layout - self.qtPath = os.path.join(os.path.dirname(parentDir), "share", "qt4") - else: - self.qtPath = os.getenv("QTDIR", None) - - if self.qtPath is not None: - pluginPath = os.path.join(self.qtPath, "plugins") - if os.path.exists(pluginPath): - self.pluginPath = pluginPath - - def usesFramework(self, name): - nameDot = "%s." % name - libNameDot = "lib%s." % name - for framework in self.deployedFrameworks: - if framework.endswith(".framework"): - if framework.startswith(nameDot): - return True - elif framework.endswith(".dylib"): - if framework.startswith(libNameDot): - return True - return False - -def getFrameworks(binaryPath, verbose): - if verbose >= 3: - print "Inspecting with otool: " + binaryPath - otoolbin=os.getenv("OTOOL", "otool") - otool = subprocess.Popen([otoolbin, "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - o_stdout, o_stderr = otool.communicate() - if otool.returncode != 0: - if verbose >= 1: - sys.stderr.write(o_stderr) - sys.stderr.flush() - raise RuntimeError("otool failed with return code %d" % otool.returncode) - - otoolLines = o_stdout.split("\n") - otoolLines.pop(0) # First line is the inspected binary - if ".framework" in binaryPath or binaryPath.endswith(".dylib"): - otoolLines.pop(0) # Frameworks and dylibs list themselves as a dependency. - - libraries = [] - for line in otoolLines: - line = line.replace("@loader_path", os.path.dirname(binaryPath)) - info = FrameworkInfo.fromOtoolLibraryLine(line.strip()) - if info is not None: - if verbose >= 3: - print "Found framework:" - print info - libraries.append(info) - - return libraries - -def runInstallNameTool(action, *args): - installnametoolbin=os.getenv("INSTALLNAMETOOL", "install_name_tool") - subprocess.check_call([installnametoolbin, "-"+action] + list(args)) - -def changeInstallName(oldName, newName, binaryPath, verbose): - if verbose >= 3: - print "Using install_name_tool:" - print " in", binaryPath - print " change reference", oldName - print " to", newName - runInstallNameTool("change", oldName, newName, binaryPath) - -def changeIdentification(id, binaryPath, verbose): - if verbose >= 3: - print "Using install_name_tool:" - print " change identification in", binaryPath - print " to", id - runInstallNameTool("id", id, binaryPath) - -def runStrip(binaryPath, verbose): - stripbin=os.getenv("STRIP", "strip") - if verbose >= 3: - print "Using strip:" - print " stripped", binaryPath - subprocess.check_call([stripbin, "-x", binaryPath]) - -def copyFramework(framework, path, verbose): - if framework.sourceFilePath.startswith("Qt"): - #standard place for Nokia Qt installer's frameworks - fromPath = "/Library/Frameworks/" + framework.sourceFilePath - else: - fromPath = framework.sourceFilePath - toDir = os.path.join(path, framework.destinationDirectory) - toPath = os.path.join(toDir, framework.binaryName) - - if not os.path.exists(fromPath): - raise RuntimeError("No file at " + fromPath) - - if os.path.exists(toPath): - return None # Already there - - if not os.path.exists(toDir): - os.makedirs(toDir) - - shutil.copy2(fromPath, toPath) - if verbose >= 3: - print "Copied:", fromPath - print " to:", toPath - - permissions = os.stat(toPath) - if not permissions.st_mode & stat.S_IWRITE: - os.chmod(toPath, permissions.st_mode | stat.S_IWRITE) - - if not framework.isDylib(): # Copy resources for real frameworks - - linkfrom = os.path.join(path, "Contents","Frameworks", framework.frameworkName, "Versions", "Current") - linkto = framework.version - if not os.path.exists(linkfrom): - os.symlink(linkto, linkfrom) - if verbose >= 2: - print "Linked:", linkfrom, "->", linkto - fromResourcesDir = framework.sourceResourcesDirectory - if os.path.exists(fromResourcesDir): - toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory) - shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True) - if verbose >= 3: - print "Copied resources:", fromResourcesDir - print " to:", toResourcesDir - fromContentsDir = framework.sourceVersionContentsDirectory - if not os.path.exists(fromContentsDir): - fromContentsDir = framework.sourceContentsDirectory - if os.path.exists(fromContentsDir): - toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory) - shutil.copytree(fromContentsDir, toContentsDir, symlinks=True) - contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory) - if verbose >= 3: - print "Copied Contents:", fromContentsDir - print " to:", toContentsDir - elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout) - qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib") - qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib") - if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath): - shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True) - if verbose >= 3: - print "Copied for libQtGui:", qtMenuNibSourcePath - print " to:", qtMenuNibDestinationPath - - return toPath - -def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploymentInfo=None): - if deploymentInfo is None: - deploymentInfo = DeploymentInfo() - - while len(frameworks) > 0: - framework = frameworks.pop(0) - deploymentInfo.deployedFrameworks.append(framework.frameworkName) - - if verbose >= 2: - print "Processing", framework.frameworkName, "..." - - # Get the Qt path from one of the Qt frameworks - if deploymentInfo.qtPath is None and framework.isQtFramework(): - deploymentInfo.detectQtPath(framework.frameworkDirectory) - - if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath): - if verbose >= 2: - print framework.frameworkName, "already deployed, skipping." - continue - - # install_name_tool the new id into the binary - changeInstallName(framework.installName, framework.deployedInstallName, binaryPath, verbose) - - # Copy farmework to app bundle. - deployedBinaryPath = copyFramework(framework, bundlePath, verbose) - # Skip the rest if already was deployed. - if deployedBinaryPath is None: - continue - - if strip: - runStrip(deployedBinaryPath, verbose) - - # install_name_tool it a new id. - changeIdentification(framework.deployedInstallName, deployedBinaryPath, verbose) - # Check for framework dependencies - dependencies = getFrameworks(deployedBinaryPath, verbose) - - for dependency in dependencies: - changeInstallName(dependency.installName, dependency.deployedInstallName, deployedBinaryPath, verbose) - - # Deploy framework if necessary. - if dependency.frameworkName not in deploymentInfo.deployedFrameworks and dependency not in frameworks: - frameworks.append(dependency) - - return deploymentInfo - -def deployFrameworksForAppBundle(applicationBundle, strip, verbose): - frameworks = getFrameworks(applicationBundle.binaryPath, verbose) - if len(frameworks) == 0 and verbose >= 1: - print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path) - return DeploymentInfo() - else: - return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose) - -def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose): - # Lookup available plugins, exclude unneeded - plugins = [] - if deploymentInfo.pluginPath is None: - return - for dirpath, dirnames, filenames in os.walk(deploymentInfo.pluginPath): - pluginDirectory = os.path.relpath(dirpath, deploymentInfo.pluginPath) - if pluginDirectory == "designer": - # Skip designer plugins - continue - elif pluginDirectory == "phonon" or pluginDirectory == "phonon_backend": - # Deploy the phonon plugins only if phonon is in use - if not deploymentInfo.usesFramework("phonon"): - continue - elif pluginDirectory == "sqldrivers": - # Deploy the sql plugins only if QtSql is in use - if not deploymentInfo.usesFramework("QtSql"): - continue - elif pluginDirectory == "script": - # Deploy the script plugins only if QtScript is in use - if not deploymentInfo.usesFramework("QtScript"): - continue - elif pluginDirectory == "qmltooling" or pluginDirectory == "qml1tooling": - # Deploy the qml plugins only if QtDeclarative is in use - if not deploymentInfo.usesFramework("QtDeclarative"): - continue - elif pluginDirectory == "bearer": - # Deploy the bearer plugins only if QtNetwork is in use - if not deploymentInfo.usesFramework("QtNetwork"): - continue - elif pluginDirectory == "position": - # Deploy the position plugins only if QtPositioning is in use - if not deploymentInfo.usesFramework("QtPositioning"): - continue - elif pluginDirectory == "sensors" or pluginDirectory == "sensorgestures": - # Deploy the sensor plugins only if QtSensors is in use - if not deploymentInfo.usesFramework("QtSensors"): - continue - elif pluginDirectory == "audio" or pluginDirectory == "playlistformats": - # Deploy the audio plugins only if QtMultimedia is in use - if not deploymentInfo.usesFramework("QtMultimedia"): - continue - elif pluginDirectory == "mediaservice": - # Deploy the mediaservice plugins only if QtMultimediaWidgets is in use - if not deploymentInfo.usesFramework("QtMultimediaWidgets"): - continue - - for pluginName in filenames: - pluginPath = os.path.join(pluginDirectory, pluginName) - if pluginName.endswith("_debug.dylib"): - # Skip debug plugins - continue - elif pluginPath == "imageformats/libqsvg.dylib" or pluginPath == "iconengines/libqsvgicon.dylib": - # Deploy the svg plugins only if QtSvg is in use - if not deploymentInfo.usesFramework("QtSvg"): - continue - elif pluginPath == "accessible/libqtaccessiblecompatwidgets.dylib": - # Deploy accessibility for Qt3Support only if the Qt3Support is in use - if not deploymentInfo.usesFramework("Qt3Support"): - continue - elif pluginPath == "graphicssystems/libqglgraphicssystem.dylib": - # Deploy the opengl graphicssystem plugin only if QtOpenGL is in use - if not deploymentInfo.usesFramework("QtOpenGL"): - continue - elif pluginPath == "accessible/libqtaccessiblequick.dylib": - # Deploy the accessible qtquick plugin only if QtQuick is in use - if not deploymentInfo.usesFramework("QtQuick"): - continue - - plugins.append((pluginDirectory, pluginName)) - - for pluginDirectory, pluginName in plugins: - if verbose >= 2: - print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..." - - sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName) - destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory) - if not os.path.exists(destinationDirectory): - os.makedirs(destinationDirectory) - - destinationPath = os.path.join(destinationDirectory, pluginName) - shutil.copy2(sourcePath, destinationPath) - if verbose >= 3: - print "Copied:", sourcePath - print " to:", destinationPath - - if strip: - runStrip(destinationPath, verbose) - - dependencies = getFrameworks(destinationPath, verbose) - - for dependency in dependencies: - changeInstallName(dependency.installName, dependency.deployedInstallName, destinationPath, verbose) - - # Deploy framework if necessary. - if dependency.frameworkName not in deploymentInfo.deployedFrameworks: - deployFrameworks([dependency], appBundleInfo.path, destinationPath, strip, verbose, deploymentInfo) - -qt_conf="""[Paths] -Translations=Resources -Plugins=PlugIns -""" - -ap = ArgumentParser(description="""Improved version of macdeployqt. - -Outputs a ready-to-deploy app in a folder "dist" and optionally wraps it in a .dmg file. -Note, that the "dist" folder will be deleted before deploying on each run. - -Optionally, Qt translation files (.qm) and additional resources can be added to the bundle. - -Also optionally signs the .app bundle; set the CODESIGNARGS environment variable to pass arguments -to the codesign tool. -E.g. CODESIGNARGS='--sign "Developer ID Application: ..." --keychain /encrypted/foo.keychain'""") - -ap.add_argument("app_bundle", nargs=1, metavar="app-bundle", help="application bundle to be deployed") -ap.add_argument("-verbose", type=int, nargs=1, default=[1], metavar="<0-3>", help="0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug") -ap.add_argument("-no-plugins", dest="plugins", action="store_false", default=True, help="skip plugin deployment") -ap.add_argument("-no-strip", dest="strip", action="store_false", default=True, help="don't run 'strip' on the binaries") -ap.add_argument("-sign", dest="sign", action="store_true", default=False, help="sign .app bundle with codesign tool") -ap.add_argument("-dmg", nargs="?", const="", metavar="basename", help="create a .dmg disk image; if basename is not specified, a camel-cased version of the app name is used") -ap.add_argument("-fancy", nargs=1, metavar="plist", default=[], help="make a fancy looking disk image using the given plist file with instructions; requires -dmg to work") -ap.add_argument("-add-qt-tr", nargs=1, metavar="languages", default=[], help="add Qt translation files to the bundle's ressources; the language list must be separated with commas, not with whitespace") -ap.add_argument("-translations-dir", nargs=1, metavar="path", default=None, help="Path to Qt's translation files") -ap.add_argument("-add-resources", nargs="+", metavar="path", default=[], help="list of additional files or folders to be copied into the bundle's resources; must be the last argument") - -config = ap.parse_args() - -verbose = config.verbose[0] - -# ------------------------------------------------ - -app_bundle = config.app_bundle[0] - -if not os.path.exists(app_bundle): - if verbose >= 1: - sys.stderr.write("Error: Could not find app bundle \"%s\"\n" % (app_bundle)) - sys.exit(1) - -app_bundle_name = os.path.splitext(os.path.basename(app_bundle))[0] - -# ------------------------------------------------ -translations_dir = None -if config.translations_dir and config.translations_dir[0]: - if os.path.exists(config.translations_dir[0]): - translations_dir = config.translations_dir[0] - else: - if verbose >= 1: - sys.stderr.write("Error: Could not find translation dir \"%s\"\n" % (translations_dir)) - sys.exit(1) -# ------------------------------------------------ - -for p in config.add_resources: - if verbose >= 3: - print "Checking for \"%s\"..." % p - if not os.path.exists(p): - if verbose >= 1: - sys.stderr.write("Error: Could not find additional resource file \"%s\"\n" % (p)) - sys.exit(1) - -# ------------------------------------------------ - -if len(config.fancy) == 1: - if verbose >= 3: - print "Fancy: Importing plistlib..." - try: - import plistlib - except ImportError: - if verbose >= 1: - sys.stderr.write("Error: Could not import plistlib which is required for fancy disk images.\n") - sys.exit(1) - - p = config.fancy[0] - if verbose >= 3: - print "Fancy: Loading \"%s\"..." % p - if not os.path.exists(p): - if verbose >= 1: - sys.stderr.write("Error: Could not find fancy disk image plist at \"%s\"\n" % (p)) - sys.exit(1) - - try: - fancy = plistlib.readPlist(p) - except: - if verbose >= 1: - sys.stderr.write("Error: Could not parse fancy disk image plist at \"%s\"\n" % (p)) - sys.exit(1) - - try: - assert not fancy.has_key("window_bounds") or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4) - assert not fancy.has_key("background_picture") or isinstance(fancy["background_picture"], str) - assert not fancy.has_key("icon_size") or isinstance(fancy["icon_size"], int) - assert not fancy.has_key("applications_symlink") or isinstance(fancy["applications_symlink"], bool) - if fancy.has_key("items_position"): - assert isinstance(fancy["items_position"], dict) - for key, value in fancy["items_position"].iteritems(): - assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int) - except: - if verbose >= 1: - sys.stderr.write("Error: Bad format of fancy disk image plist at \"%s\"\n" % (p)) - sys.exit(1) - - if fancy.has_key("background_picture"): - bp = fancy["background_picture"] - if verbose >= 3: - print "Fancy: Resolving background picture \"%s\"..." % bp - if not os.path.exists(bp): - bp = os.path.join(os.path.dirname(p), bp) - if not os.path.exists(bp): - if verbose >= 1: - sys.stderr.write("Error: Could not find background picture at \"%s\" or \"%s\"\n" % (fancy["background_picture"], bp)) - sys.exit(1) - else: - fancy["background_picture"] = bp -else: - fancy = None - -# ------------------------------------------------ - -if os.path.exists("dist"): - if verbose >= 2: - print "+ Removing old dist folder +" - - shutil.rmtree("dist") - -# ------------------------------------------------ - -target = os.path.join("dist", app_bundle) - -if verbose >= 2: - print "+ Copying source bundle +" -if verbose >= 3: - print app_bundle, "->", target - -os.mkdir("dist") -shutil.copytree(app_bundle, target, symlinks=True) - -applicationBundle = ApplicationBundleInfo(target) - -# ------------------------------------------------ - -if verbose >= 2: - print "+ Deploying frameworks +" - -try: - deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose) - if deploymentInfo.qtPath is None: - deploymentInfo.qtPath = os.getenv("QTDIR", None) - if deploymentInfo.qtPath is None: - if verbose >= 1: - sys.stderr.write("Warning: Could not detect Qt's path, skipping plugin deployment!\n") - config.plugins = False -except RuntimeError as e: - if verbose >= 1: - sys.stderr.write("Error: %s\n" % str(e)) - sys.exit(1) - -# ------------------------------------------------ - -if config.plugins: - if verbose >= 2: - print "+ Deploying plugins +" - - try: - deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose) - except RuntimeError as e: - if verbose >= 1: - sys.stderr.write("Error: %s\n" % str(e)) - sys.exit(1) - -# ------------------------------------------------ - -if len(config.add_qt_tr) == 0: - add_qt_tr = [] -else: - if translations_dir is not None: - qt_tr_dir = translations_dir - else: - if deploymentInfo.qtPath is not None: - qt_tr_dir = os.path.join(deploymentInfo.qtPath, "translations") - else: - sys.stderr.write("Error: Could not find Qt translation path\n") - sys.exit(1) - add_qt_tr = ["qt_%s.qm" % lng for lng in config.add_qt_tr[0].split(",")] - for lng_file in add_qt_tr: - p = os.path.join(qt_tr_dir, lng_file) - if verbose >= 3: - print "Checking for \"%s\"..." % p - if not os.path.exists(p): - if verbose >= 1: - sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file)) - sys.exit(1) - -# ------------------------------------------------ - -if verbose >= 2: - print "+ Installing qt.conf +" - -f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") -f.write(qt_conf) -f.close() - -# ------------------------------------------------ - -if len(add_qt_tr) > 0 and verbose >= 2: - print "+ Adding Qt translations +" - -for lng_file in add_qt_tr: - if verbose >= 3: - print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file) - shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file)) - -# ------------------------------------------------ - -if len(config.add_resources) > 0 and verbose >= 2: - print "+ Adding additional resources +" - -for p in config.add_resources: - t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p)) - if verbose >= 3: - print p, "->", t - if os.path.isdir(p): - shutil.copytree(p, t, symlinks=True) - else: - shutil.copy2(p, t) - -# ------------------------------------------------ - -if config.sign and 'CODESIGNARGS' not in os.environ: - print "You must set the CODESIGNARGS environment variable. Skipping signing." -elif config.sign: - if verbose >= 1: - print "Code-signing app bundle %s"%(target,) - subprocess.check_call("codesign --force %s %s"%(os.environ['CODESIGNARGS'], target), shell=True) - -# ------------------------------------------------ - -if config.dmg is not None: - - #Patch in check_output for Python 2.6 - if "check_output" not in dir( subprocess ): - def f(*popenargs, **kwargs): - if 'stdout' in kwargs: - raise ValueError('stdout argument not allowed, it will be overridden.') - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) - output, unused_err = process.communicate() - retcode = process.poll() - if retcode: - cmd = kwargs.get("args") - if cmd is None: - cmd = popenargs[0] - raise CalledProcessError(retcode, cmd) - return output - subprocess.check_output = f - - def runHDIUtil(verb, image_basename, **kwargs): - hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"] - if kwargs.has_key("capture_stdout"): - del kwargs["capture_stdout"] - run = subprocess.check_output - else: - if verbose < 2: - hdiutil_args.append("-quiet") - elif verbose >= 3: - hdiutil_args.append("-verbose") - run = subprocess.check_call - - for key, value in kwargs.iteritems(): - hdiutil_args.append("-" + key) - if not value is True: - hdiutil_args.append(str(value)) - - return run(hdiutil_args) - - if verbose >= 2: - if fancy is None: - print "+ Creating .dmg disk image +" - else: - print "+ Preparing .dmg disk image +" - - if config.dmg != "": - dmg_name = config.dmg - else: - spl = app_bundle_name.split(" ") - dmg_name = spl[0] + "".join(p.capitalize() for p in spl[1:]) - - if fancy is None: - try: - runHDIUtil("create", dmg_name, srcfolder="dist", format="UDBZ", volname=app_bundle_name, ov=True) - except subprocess.CalledProcessError as e: - sys.exit(e.returncode) - else: - if verbose >= 3: - print "Determining size of \"dist\"..." - size = 0 - for path, dirs, files in os.walk("dist"): - for file in files: - size += os.path.getsize(os.path.join(path, file)) - size += int(size * 0.1) - - if verbose >= 3: - print "Creating temp image for modification..." - try: - runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=app_bundle_name, ov=True) - except subprocess.CalledProcessError as e: - sys.exit(e.returncode) - - if verbose >= 3: - print "Attaching temp image..." - try: - output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True) - except subprocess.CalledProcessError as e: - sys.exit(e.returncode) - - m = re.search("/Volumes/(.+$)", output) - disk_root = m.group(0) - disk_name = m.group(1) - - if verbose >= 2: - print "+ Applying fancy settings +" - - if fancy.has_key("background_picture"): - bg_path = os.path.join(disk_root, os.path.basename(fancy["background_picture"])) - if verbose >= 3: - print fancy["background_picture"], "->", bg_path - shutil.copy2(fancy["background_picture"], bg_path) - else: - bg_path = None - - if fancy.get("applications_symlink", False): - os.symlink("/Applications", os.path.join(disk_root, "Applications")) - - # The Python appscript package broke with OSX 10.8 and isn't being fixed. - # So we now build up an AppleScript string and use the osascript command - # to make the .dmg file pretty: - appscript = Template( """ - on run argv - tell application "Finder" - tell disk "$disk" - open - set current view of container window to icon view - set toolbar visible of container window to false - set statusbar visible of container window to false - set the bounds of container window to {$window_bounds} - set theViewOptions to the icon view options of container window - set arrangement of theViewOptions to not arranged - set icon size of theViewOptions to $icon_size - $background_commands - $items_positions - close -- close/reopen works around a bug... - open - update without registering applications - delay 5 - eject - end tell - end tell - end run - """) - - itemscript = Template('set position of item "${item}" of container window to {${position}}') - items_positions = [] - if fancy.has_key("items_position"): - for name, position in fancy["items_position"].iteritems(): - params = { "item" : name, "position" : ",".join([str(p) for p in position]) } - items_positions.append(itemscript.substitute(params)) - - params = { - "disk" : "Shadow", - "window_bounds" : "300,300,800,620", - "icon_size" : "96", - "background_commands" : "", - "items_positions" : "\n ".join(items_positions) - } - if fancy.has_key("window_bounds"): - params["window.bounds"] = ",".join([str(p) for p in fancy["window_bounds"]]) - if fancy.has_key("icon_size"): - params["icon_size"] = str(fancy["icon_size"]) - if bg_path is not None: - # Set background file, then call SetFile to make it invisible. - # (note: making it invisible first makes set background picture fail) - bgscript = Template("""set background picture of theViewOptions to file "$bgpic" - do shell script "SetFile -a V /Volumes/$disk/$bgpic" """) - params["background_commands"] = bgscript.substitute({"bgpic" : os.path.basename(bg_path), "disk" : params["disk"]}) - - s = appscript.substitute(params) - if verbose >= 2: - print("Running AppleScript:") - print(s) - - p = subprocess.Popen(['osascript', '-'], stdin=subprocess.PIPE) - p.communicate(input=s) - if p.returncode: - print("Error running osascript.") - - if verbose >= 2: - print "+ Finalizing .dmg disk image +" - time.sleep(5) - - try: - runHDIUtil("convert", dmg_name + ".temp", format="UDBZ", o=dmg_name + ".dmg", ov=True) - except subprocess.CalledProcessError as e: - sys.exit(e.returncode) - - os.unlink(dmg_name + ".temp.dmg") - -# ------------------------------------------------ - -if verbose >= 2: - print "+ Done +" - -sys.exit(0) diff --git a/contrib/macdeploy/node-appdmg.json b/contrib/macdeploy/node-appdmg.json deleted file mode 100644 index 1f35bb0782..0000000000 --- a/contrib/macdeploy/node-appdmg.json +++ /dev/null @@ -1,12 +0,0 @@ -//npm install -g appdmg -//appdmg node-appdmg.json Umbra.dmg -//Mount .dmg and copy /Volumes/Umbra/.DS_Store to ./DS_Store -{ - "title": "Umbra", - "icon": "../../src/qt/res/icons/shadow.icns", - "background": "background.png", - "contents": [ - { "x": 370, "y": 156, "type": "link", "path": "/Applications" }, - { "x": 128, "y": 156, "type": "file", "path": "../../Umbra.app" } - ] -} diff --git a/contrib/macdeploy/notes.txt b/contrib/macdeploy/notes.txt deleted file mode 100644 index 9b592fc955..0000000000 --- a/contrib/macdeploy/notes.txt +++ /dev/null @@ -1,26 +0,0 @@ - -macdeployqtplus works best on OS X Lion, for Snow Leopard you'd need to install -Python 2.7 and make it your default Python installation. - -You will need the appscript package for the fancy disk image creation to work. -Install it by invoking "sudo easy_install appscript". - -Ths script should be invoked in the target directory like this: -$source_dir/contrib/macdeploy/macdeployqtplus NovaCoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy $source_dir/contrib/macdeploy/fancy.plist -verbose 2 - -During the process, the disk image window will pop up briefly where the fancy -settings are applied. This is normal, please do not interfere. - -You can also set up Qt Creator for invoking the script. For this, go to the -"Projects" tab on the left side, switch to "Run Settings" above and add a -deploy configuration. Next add a deploy step choosing "Custom Process Step". -Fill in the following. - -Enable custom process step: [x] -Command: %{sourceDir}/contrib/macdeploy/macdeployqtplus -Working directory: %{buildDir} -Command arguments: NovaCoin-Qt.app -add-qt-tr da,de,es,hu,ru,uk,zh_CN,zh_TW -dmg -fancy %{sourceDir}/contrib/macdeploy/fancy.plist -verbose 2 - -After that you can start the deployment process through the menu with -Build -> Deploy Project "novacoin-qt" - diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py deleted file mode 100755 index fd8a8b7129..0000000000 --- a/contrib/qt_translations.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python - -# Helpful little script that spits out a comma-separated list of -# language codes for Qt icons that should be included -# in binary bitcoin distributions - -import glob -import os -import re -import sys - -if len(sys.argv) != 3: - sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0]) - -d1 = sys.argv[1] -d2 = sys.argv[2] - -l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ]) -l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ]) - -print ",".join(sorted(l1.intersection(l2))) - diff --git a/contrib/wallettools/walletchangepass.py b/contrib/wallettools/walletchangepass.py deleted file mode 100644 index 30f3f5b26a..0000000000 --- a/contrib/wallettools/walletchangepass.py +++ /dev/null @@ -1,5 +0,0 @@ -from jsonrpc import ServiceProxy -access = ServiceProxy("http://127.0.0.1:8332") -pwd = raw_input("Enter old wallet passphrase: ") -pwd2 = raw_input("Enter new wallet passphrase: ") -access.walletpassphrasechange(pwd, pwd2) \ No newline at end of file diff --git a/contrib/wallettools/walletunlock.py b/contrib/wallettools/walletunlock.py deleted file mode 100644 index f847c6fe61..0000000000 --- a/contrib/wallettools/walletunlock.py +++ /dev/null @@ -1,4 +0,0 @@ -from jsonrpc import ServiceProxy -access = ServiceProxy("http://127.0.0.1:8332") -pwd = raw_input("Enter wallet passphrase: ") -access.walletpassphrase(pwd, 60) \ No newline at end of file diff --git a/doc/CMakeEnvVars.png b/doc/CMakeEnvVars.png new file mode 100644 index 0000000000..28107593be Binary files /dev/null and b/doc/CMakeEnvVars.png differ diff --git a/doc/CMakeEnvVars_vcpkg.png b/doc/CMakeEnvVars_vcpkg.png new file mode 100644 index 0000000000..6c8a9c1b01 Binary files /dev/null and b/doc/CMakeEnvVars_vcpkg.png differ diff --git a/doc/Doxyfile b/doc/Doxyfile deleted file mode 100644 index 08d4f8c37f..0000000000 --- a/doc/Doxyfile +++ /dev/null @@ -1,1752 +0,0 @@ -# Doxyfile 1.7.4 - -# !!! Invoke doxygen from project root using: -# doxygen doc/Doxyfile - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Bitcoin - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.5.0 - -# Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. - -PROJECT_BRIEF = "P2P Digital Currency" - -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. - -PROJECT_LOGO = doc/bitcoin_logo_doxygen.png - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doc/doxygen - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). - -INLINE_GROUPED_CLASSES = NO - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. - -STRICT_PROTO_MATCHING = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = src - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.f90 \ - *.f \ - *.for \ - *.vhd \ - *.vhdl - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix file system feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. - -FILTER_SOURCE_PATTERNS = - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the HTML output directory. Note -# that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -FORMULA_TRANSPARENT = YES - -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. - -USE_MATHJAX = NO - -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to the -# mathjax.org site, so you can quickly see the result without installing -# MathJax, but it is strongly recommended to install a local copy of MathJax -# before deployment. - -MATHJAX_RELPATH = http://www.mathjax.org/mathjax - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4 - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for -# the generated latex document. The footer should contain everything after -# the last chapter. If it is left blank doxygen will generate a -# standard footer. Notice: only use this tag if you know what you are doing! - -LATEX_FOOTER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# pointed to by INCLUDE_PATH will be searched when a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition that -# overrules the definition found in the source code. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all references to function-like macros -# that are alone on a line, have an all uppercase name, and do not end with a -# semicolon, because these will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option also works with HAVE_DOT disabled, but it is recommended to -# install and use dot, since it yields more powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called Helvetica to the output -# directory and reference it in all dot files that doxygen generates. -# When you want a differently looking font you can specify the font name -# using DOT_FONTNAME. You need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = Helvetica - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will generate a graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are svg, png, jpg, or gif. -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the -# \mscfile command). - -MSCFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/doc/MacOSX-build-instructions-README.md b/doc/MacOSX-build-instructions-README.md new file mode 100644 index 0000000000..564b3f414b --- /dev/null +++ b/doc/MacOSX-build-instructions-README.md @@ -0,0 +1,87 @@ +# Aliaswallet Building from Source for macOS + +First, you need to clone the Git repository. + +## Build with Qt Creator + +### Install Qt SDK 5.12.2 (QtWebEngine) + +- **Qt SDK**: [Download Qt Installer](https://www.qt.io/download-qt-installer) + +Now you can open `/src/src.pro` in Qt Creator. + +## Build on Command Line + +### Export Path to Qt + +```bash +export QT_PATH=~/Qt/5.12.2/clang_64 +``` + +### Setup Required Libraries and Environment Variables + +#### Boost + +1. Determine the number of available cores to improve build speed: + +```bash +system_profiler | grep "Total Number of Cores" +export CORES= +``` + +2. Download, extract and build Boost: + +```bash +cd ~ +mkdir Boost +cd Boost +wget https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.gz +tar xzf boost_1_68_0.tar.gz +cd boost_1_68_0 +./bootstrap.sh +./b2 \ + cxxflags="-std=c++0x" \ + address-model=64 \ + -j ${CORES} \ + install \ + --prefix=$(pwd) \ + --build-type=complete \ + --layout=tagged +``` + +3. Export path to Boost libraries and headers: + +```bash +export BOOST_PATH=$(pwd) +``` + +#### OpenSSL + +1. Install OpenSSL 1.1.1 +2. Export path to OpenSSL libraries and headers (example): + +```bash +export OPENSSL_PATH=/usr/local/Cellar/openssl@1.1/1.1.1d +``` + +#### Tor + +Download prepared Tor archive: + +```bash +cd ~ +mkdir Tor +cd Tor +wget https://github.com/aliascash/resources/raw/master/resources/Aliaswallet.Tor.libraries.macOS.zip +``` + +### Build Using Helper Scripts + +```bash +cd +./scripts/mac-build.sh +rm -f Aliaswallet*.dmg +unzip ~/Tor/Tor.zip +# rm -rf src/bin/debug +./scripts/mac-deployqt.sh +``` diff --git a/doc/README b/doc/README deleted file mode 100644 index 0d435fd962..0000000000 --- a/doc/README +++ /dev/null @@ -1,20 +0,0 @@ -ShadowCoin - -Copyright (c) 2014 ShadowCoin Developers -Copyright (c) 2014 BlackCoin Developers -Copyright (c) 2013 NovaCoin Developers -Copyright (c) 2011-2012 PPCoin Developers -Distributed under the MIT/X11 software license, see the accompanying -file license.txt or http://www.opensource.org/licenses/mit-license.php. -This product includes software developed by the OpenSSL Project for use in -the OpenSSL Toolkit (http://www.openssl.org/). This product includes -cryptographic software written by Eric Young (eay@cryptsoft.com). - - -Intro ------ -ShadowCoin is a free open source project derived from Bitcoin, with -the goal of providing a long-term energy-efficient scrypt-based crypto-currency. -Built on the foundation of Bitcoin, PPCoin, NovaCoin and BlackCoin, innovations such as proof-of-stake -help further advance the field of crypto-currency. - diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 0000000000..4df1dcb70d --- /dev/null +++ b/doc/README.md @@ -0,0 +1,8 @@ +# Alias Documentation + +## Building Alias + +For detailed build instructions, check out our [Wiki](https://github.com/aliascash/documentation/wiki) or go straight to these pages: + +- Build on and for [Windows](https://github.com/aliascash/documentation/wiki/Build-Windows) +- Build on and for [Mac](https://github.com/aliascash/documentation/wiki/Build-Mac) diff --git a/doc/README_osx.txt b/doc/README_osx.txt new file mode 100644 index 0000000000..231afa3cad --- /dev/null +++ b/doc/README_osx.txt @@ -0,0 +1,77 @@ +# Deterministic macOS DMG Notes + +Working macOS DMGs are created in Linux by combining a recent clang, Apple's binutils (ld, ar, etc), and DMG authoring tools. + +## Toolchain Overview + +Apple uses clang extensively for development and has upstreamed the necessary functionality so that a vanilla clang can take advantage. It supports the use of `-F`, `-target`, `-mmacosx-version-min`, and `--sysroot`, which are all necessary when building for macOS. A pre-compiled version of 3.2 is used because it was not available in the Precise repositories at the time this work was started. In the future, it can be switched to use system packages instead. + +Apple's version of binutils (called cctools) contains lots of functionality missing in the FSF's binutils. In addition to extra linker options for frameworks and sysroots, several other tools are needed as well such as `install_name_tool`, `lipo`, and `nmedit`. These do not build under Linux, so they have been patched to do so. The work here was used as a starting point: + +- [toolchain4](https://github.com/mingwandroid/toolchain4) + +## Required Source Packages + +In order to build a working toolchain, the following source packages are needed from Apple: cctools, dyld, and ld64. + +These tools inject timestamps by default, which produce non-deterministic binaries. The `ZERO_AR_DATE` environment variable is used to disable that. + +This version of cctools has been patched to use the current version of clang's headers and its `libLTO.so` rather than those from llvmgcc, as it was originally done in toolchain4. + +## Apple SDK Requirements + +To complicate things further, all builds must target an Apple SDK. These SDKs are free to download, but not redistributable. + +To obtain it, register for a developer account, then download the Xcode 6.1.1 DMG: + +- [Xcode 6.1.1 DMG](https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg) + +This file is several gigabytes in size, but only a single directory inside is needed: + +``` +Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk +``` + +Unfortunately, the usual Linux tools (7zip, hpmount, loopback mount) are incapable of opening this file. To create a tarball suitable for Gitian input, mount the DMG in macOS, then create it with: + +```bash +tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk +``` + +## Build Process + +The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries which are created using these tools. The build process has been designed to avoid including the SDK's files in Gitian's outputs. All interim tarballs are fully deterministic and may be freely redistributed. + +## DMG Creation Tools + +### genisoimage + +`genisoimage` is used to create the initial DMG. It is not deterministic as-is, so it has been patched. A system genisoimage will work fine, but it will not be deterministic because the file-order will change between invocations. + +The patch can be seen here: + +- [genisoimage.diff](https://raw.githubusercontent.com/theuni/osx-cross-depends/master/patches/cdrtools/genisoimage.diff) + +No effort was made to fix this cleanly, so it likely leaks memory badly. But it's only used for a single invocation, so that's no real concern. + +### libdmg-hfsplus + +`genisoimage` cannot compress DMGs, so afterwards, the `dmg` tool from the libdmg-hfsplus project is used to compress it. There are several bugs in this tool and its maintainer has seemingly abandoned the project. It has been forked and is available (with fixes) here: + +- [libdmg-hfsplus](https://github.com/theuni/libdmg-hfsplus) + +The `dmg` tool has the ability to create DMGs from scratch as well, but this functionality is broken. Only the compression feature is currently used. Ideally, the creation could be fixed and genisoimage would no longer be necessary. + +## DMG Customization + +Background images and other features can be added to DMG files by inserting a `.DS_Store` before creation. The easiest way to create this file is to build a DMG without one, move it to a device running macOS, customize the layout, then grab the `.DS_Store` file for later use. That is the approach taken here. + +## Code Signing + +As of macOS Mavericks (10.9), using an Apple-blessed key to sign binaries is a requirement in order to satisfy the new Gatekeeper requirements. Because this private key cannot be shared, we'll have to be a bit creative in order for the build process to remain somewhat deterministic. Here's how it works: + +1. Builders use Gitian to create an unsigned release. This outputs an unsigned DMG which users may choose to bless and run. It also outputs an unsigned app structure in the form of a tarball, which also contains all of the tools that have been previously (deterministically) built in order to create a final DMG. + +2. The Apple keyholder uses this unsigned app to create a detached signature, using the script that is also included there. + +3. Builders feed the unsigned app + detached signature back into Gitian. It uses the pre-built tools to recombine the pieces into a deterministic DMG. diff --git a/doc/README_windows.txt b/doc/README_windows.txt deleted file mode 100644 index 1deded8f15..0000000000 --- a/doc/README_windows.txt +++ /dev/null @@ -1,20 +0,0 @@ -ShadowCoin - -Copyright (c) 2014 ShadowCoin Developers -Copyright (c) 2014 BlackCoin Developers -Copyright (c) 2013 NovaCoin Developers -Copyright (c) 2011-2013 PPCoin Developers -Distributed under the MIT/X11 software license, see the accompanying -file license.txt or http://www.opensource.org/licenses/mit-license.php. -This product includes software developed by the OpenSSL Project for use in -the OpenSSL Toolkit (http://www.openssl.org/). This product includes -cryptographic software written by Eric Young (eay@cryptsoft.com). - - -Intro ------ -ShadowCoin is a free open source project derived from Bitcoin, with -the goal of providing a long-term energy-efficient scrypt-based crypto-currency. -Built on the foundation of Bitcoin, PPCoin, NovaCoin and BlackCoin, innovations such as proof-of-stake -help further advance the field of crypto-currency. - diff --git a/doc/assets-attribution.txt b/doc/assets-attribution.txt deleted file mode 100644 index 2fdb6bc424..0000000000 --- a/doc/assets-attribution.txt +++ /dev/null @@ -1,58 +0,0 @@ -Code: src/strlcpy.h -Author: Todd C. Miller -License: ISC - -Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png, - src/qt/res/src/*.svg -Designer: Wladimir van der Laan -License: MIT - -Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png, - src/qt/res/icons/history.png, src/qt/res/icons/key.png, - src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png, - src/qt/res/icons/receive.png, src/qt/res/icons/send.png, - src/qt/res/icons/synced.png, src/qt/res/icons/filesave.png -Icon Pack: NUVOLA ICON THEME for KDE 3.x -Designer: David Vignoni (david@icon-king.com) - ICON KING - www.icon-king.com -License: LGPL -Site: http://www.icon-king.com/projects/nuvola/ - -Icon: src/qt/res/icons/connect*.png -Icon Pack: Human-O2 -Designer: schollidesign -License: GNU/GPL -Site: http://findicons.com/icon/93743/blocks_gnome_netstatus_0 - -Icon: src/qt/res/icons/transaction*.png -Designer: md2k7 -Site: https://forum.bitcoin.org/index.php?topic=15276.0 -License: You are free to do with these icons as you wish, including selling, - copying, modifying etc. - -Icon: src/qt/res/icons/configure.png, src/qt/res/icons/quit.png, - src/qt/res/icons/editcopy.png, src/qt/res/icons/editpaste.png, - src/qt/res/icons/add.png, src/qt/res/icons/edit.png, - src/qt/res/icons/remove.png (edited) -Designer: http://www.everaldo.com -Icon Pack: Crystal SVG -License: LGPL - -Icon: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png -Designer: Bitboy (optimized for 16x16 by Wladimir van der Laan) -License: Public Domain -Site: http://forum.bitcoin.org/?topic=1756.0 - -Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng -Icon Pack: Kids -Designer: Everaldo (Everaldo Coelho) -License: GNU/GPL -Site: http://findicons.com/icon/17102/reload?id=17102 - -Image: src/qt/res/images/splash2.jpg (Wallet image) -Designer: Crobbo (forum) -Site: https://bitcointalk.org/index.php?topic=32273.0 -License: Public domain - -ShadowCoin Logo -License: Creative Commons Attribution 4.0 International License diff --git a/doc/bitcoin_logo_doxygen.png b/doc/bitcoin_logo_doxygen.png deleted file mode 100644 index 5b41b02e18..0000000000 Binary files a/doc/bitcoin_logo_doxygen.png and /dev/null differ diff --git a/doc/build-msw.txt b/doc/build-msw.txt deleted file mode 100644 index 8bb7c0f16f..0000000000 --- a/doc/build-msw.txt +++ /dev/null @@ -1,84 +0,0 @@ -Copyright (c) 2009-2012 Bitcoin Developers -Distributed under the MIT/X11 software license, see the accompanying -file license.txt or http://www.opensource.org/licenses/mit-license.php. -This product includes software developed by the OpenSSL Project for use in -the OpenSSL Toolkit (http://www.openssl.org/). This product includes -cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP -software written by Thomas Bernard. - - -See readme-qt.rst for instructions on building ShadowCoin QT, the -graphical user interface. - -WINDOWS BUILD NOTES -=================== - -Compilers Supported -------------------- -TODO: What works? -Note: releases are cross-compiled using mingw running on Linux. - - -Dependencies ------------- -Libraries you need to download separately and build: - - default path download -OpenSSL \openssl-1.0.1b-mgw http://www.openssl.org/source/ -Berkeley DB \db-4.8.30.NC-mgw http://www.oracle.com/technology/software/products/berkeley-db/index.html -Boost \boost-1.47.0-mgw http://www.boost.org/users/download/ -miniupnpc \miniupnpc-1.6-mgw http://miniupnp.tuxfamily.org/files/ - -Their licenses: -OpenSSL Old BSD license with the problematic advertising requirement -Berkeley DB New BSD license with additional requirement that linked software must be free open source -Boost MIT-like license -miniupnpc New (3-clause) BSD license - -Versions used in this release: -OpenSSL 1.0.1b -Berkeley DB 4.8.30.NC -Boost 1.47.0 -miniupnpc 1.6 - - -OpenSSL -------- -MSYS shell: -un-tar sources with MSYS 'tar xfz' to avoid issue with symlinks (OpenSSL ticket 2377) -change 'MAKE' env. variable from 'C:\MinGW32\bin\mingw32-make.exe' to '/c/MinGW32/bin/mingw32-make.exe' - -cd /c/openssl-1.0.1b-mgw -./config -make - -Berkeley DB ------------ -MSYS shell: -cd /c/db-4.8.30.NC-mgw/build_unix -sh ../dist/configure --enable-mingw --enable-cxx -make - -Boost ------ -DOS prompt: -downloaded boost jam 3.1.18 -cd \boost-1.47.0-mgw -bjam toolset=gcc --build-type=complete stage - -MiniUPnPc ---------- -UPnP support is optional, make with USE_UPNP= to disable it. - -MSYS shell: -cd /c/miniupnpc-1.6-mgw -make -f Makefile.mingw -mkdir miniupnpc -cp *.h miniupnpc/ - -ShadowCoin -------- -DOS prompt: -cd \shadowcoin\src -mingw32-make -f makefile.mingw -strip shadowcoind.exe diff --git a/doc/build-osx.txt b/doc/build-osx.txt deleted file mode 100644 index 8597e9de85..0000000000 --- a/doc/build-osx.txt +++ /dev/null @@ -1,52 +0,0 @@ -Copyright (c) 2009-2012 Bitcoin Developers -Distributed under the MIT/X11 software license, see the accompanying file -license.txt or http://www.opensource.org/licenses/mit-license.php. This -product includes software developed by the OpenSSL Project for use in the -OpenSSL Toolkit (http://www.openssl.org/). This product includes cryptographic -software written by Eric Young (eay@cryptsoft.com) and UPnP software written by -Thomas Bernard. - - -Mac OS X shadowcoind build instructions -Laszlo Hanyecz -Douglas Huff - - -See readme-qt.rst for instructions on building ShadowCoin QT, the -graphical user interface. - -Tested on 10.5 and 10.6 intel. PPC is not supported because it's big-endian. - -All of the commands should be executed in Terminal.app.. it's in -/Applications/Utilities - -You need to install XCode with all the options checked so that the compiler and -everything is available in /usr not just /Developer I think it comes on the DVD -but you can get the current version from http://developer.apple.com - - -1. Clone the github tree to get the source code: - -2. Download and install MacPorts from http://www.macports.org/ - -2a. (for 10.7 Lion) - Edit /opt/local/etc/macports/macports.conf and uncomment "build_arch i386" - -3. Install dependencies from MacPorts - -sudo port install boost db48 openssl miniupnpc - -Optionally install qrencode (and set USE_QRCODE=1): -sudo port install qrencode - -4. Now you should be able to build shadowcoind: - -cd shadowcoin/src -make -f makefile.osx - -Run: - ./shadowcoind --help # for a list of command-line options. -Run - ./shadowcoind -daemon # to start the shadowcoin daemon. -Run - ./shadowcoind help # When the daemon is running, to get a list of RPC commands diff --git a/doc/build-unix.txt b/doc/build-unix.txt deleted file mode 100644 index cb86f204cc..0000000000 --- a/doc/build-unix.txt +++ /dev/null @@ -1,153 +0,0 @@ -Copyright (c) 2009-2012 Bitcoin Developers -Distributed under the MIT/X11 software license, see the accompanying -file license.txt or http://www.opensource.org/licenses/mit-license.php. -This product includes software developed by the OpenSSL Project for use in -the OpenSSL Toolkit (http://www.openssl.org/). This product includes -cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP -software written by Thomas Bernard. - - -UNIX BUILD NOTES -================ - -To Build --------- - -cd src/ -make -f makefile.unix # Headless shadowcoin - -See readme-qt.rst for instructions on building ShadowCoin QT, -the graphical shadowcoin. - -Dependencies ------------- - - Library Purpose Description - ------- ------- ----------- - libssl SSL Support Secure communications - libdb Berkeley DB Blockchain & wallet storage - libboost Boost C++ Library - miniupnpc UPnP Support Optional firewall-jumping support - libqrencode QRCode generation Optional QRCode generation - -Note that libexecinfo should be installed, if you building under *BSD systems. -This library provides backtrace facility. - -miniupnpc may be used for UPnP port mapping. It can be downloaded from -http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and -turned off by default. Set USE_UPNP to a different value to control this: - USE_UPNP=- No UPnP support - miniupnp not required - USE_UPNP=0 (the default) UPnP support turned off by default at runtime - USE_UPNP=1 UPnP support turned on by default at runtime - -libqrencode may be used for QRCode image generation. It can be downloaded -from http://fukuchi.org/works/qrencode/index.html.en, or installed via -your package manager. Set USE_QRCODE to control this: - USE_QRCODE=0 (the default) No QRCode support - libqrcode not required - USE_QRCODE=1 QRCode support enabled - -Licenses of statically linked libraries: - Berkeley DB New BSD license with additional requirement that linked - software must be free open source - Boost MIT-like license - miniupnpc New (3-clause) BSD license - -Versions used in this release: - GCC 4.9.0 - OpenSSL 1.0.1g - Berkeley DB 5.3.28.NC - Boost 1.55.0 - miniupnpc 1.9.20140401 - -Dependency Build Instructions: Ubuntu & Debian ----------------------------------------------- -sudo apt-get install build-essential -sudo apt-get install libssl-dev -sudo apt-get install libdb++-dev -sudo apt-get install libboost-all-dev -sudo apt-get install libqrencode-dev - -If using Boost 1.37, append -mt to the boost libraries in the makefile. - - -Dependency Build Instructions: Gentoo -------------------------------------- - -emerge -av1 --noreplace boost openssl sys-libs/db - -Take the following steps to build (no UPnP support): - cd ${SHADOWCOIN_DIR}/src - make -f makefile.unix USE_UPNP= - strip shadowcoind - - -Notes ------ -The release is built with GCC and then "strip shadowcoind" to strip the debug -symbols, which reduces the executable size by about 90%. - - -miniupnpc ---------- -tar -xzvf miniupnpc-1.6.tar.gz -cd miniupnpc-1.6 -make -sudo su -make install - - -Berkeley DB ------------ -You need Berkeley DB. If you have to build Berkeley DB yourself: -../dist/configure --enable-cxx -make - - -Boost ------ -If you need to build Boost yourself: -sudo su -./bootstrap.sh -./bjam install - - -Security --------- -To help make your shadowcoin installation more secure by making certain attacks impossible to -exploit even if a vulnerability is found, you can take the following measures: - -* Position Independent Executable - Build position independent code to take advantage of Address Space Layout Randomization - offered by some kernels. An attacker who is able to cause execution of code at an arbitrary - memory location is thwarted if he doesn't know where anything useful is located. - The stack and heap are randomly located by default but this allows the code section to be - randomly located as well. - - On an Amd64 processor where a library was not compiled with -fPIC, this will cause an error - such as: "relocation R_X86_64_32 against `......' can not be used when making a shared object;" - - To build with PIE, use: - make -f makefile.unix ... -e PIE=1 - - To test that you have built PIE executable, install scanelf, part of paxutils, and use: - scanelf -e ./shadowcoin - - The output should contain: - TYPE - ET_DYN - -* Non-executable Stack - If the stack is executable then trivial stack based buffer overflow exploits are possible if - vulnerable buffers are found. By default, shadowcoin should be built with a non-executable stack - but if one of the libraries it uses asks for an executable stack or someone makes a mistake - and uses a compiler extension which requires an executable stack, it will silently build an - executable without the non-executable stack protection. - - To verify that the stack is non-executable after compiling use: - scanelf -e ./shadowcoin - - the output should contain: - STK/REL/PTL - RW- R-- RW- - - The STK RW- means that the stack is readable and writeable but not executable. diff --git a/doc/coding.txt b/doc/coding.txt deleted file mode 100644 index 59409859f9..0000000000 --- a/doc/coding.txt +++ /dev/null @@ -1,99 +0,0 @@ -Please be consistent with the existing coding style. - -Block style: - -bool Function(char* psz, int n) -{ - // Comment summarising what this section of code does - for (int i = 0; i < n; i++) - { - // When something fails, return early - if (!Something()) - return false; - ... - } - - // Success return is usually at the end - return true; -} - -- ANSI/Allman block style -- 4 space indenting, no tabs -- No extra spaces inside parenthesis; please don't do ( this ) -- No space after function names, one space after if, for and while - -Variable names begin with the type in lowercase, like nSomeVariable. -Please don't put the first word of the variable name in lowercase like -someVariable. - -Common types: -n integer number: short, unsigned short, int, unsigned int, - int64_t, uint64_t, sometimes char if used as a number -d double, float -f flag -hash uint256 -p pointer or array, one p for each level of indirection -psz pointer to null terminated string -str string object -v vector or similar list objects -map map or multimap -set set or multiset -bn CBigNum - -------------------------- -Locking/mutex usage notes - -The code is multi-threaded, and uses mutexes and the -CRITICAL_BLOCK/TRY_CRITICAL_BLOCK macros to protect data structures. - -Deadlocks due to inconsistent lock ordering (thread 1 locks cs_main -and then cs_wallet, while thread 2 locks them in the opposite order: -result, deadlock as each waits for the other to release its lock) are -a problem. Compile with -DDEBUG_LOCKORDER to get lock order -inconsistencies reported in the debug.log file. - -Re-architecting the core code so there are better-defined interfaces -between the various components is a goal, with any necessary locking -done by the components (e.g. see the self-contained CKeyStore class -and its cs_KeyStore lock for example). - -------- -Threads - -StartNode : Starts other threads. - -ThreadGetMyExternalIP : Determines outside-the-firewall IP address, -sends addr message to connected peers when it determines it. - -ThreadIRCSeed : Joins IRC bootstrapping channel, watching for new -peers and advertising this node's IP address. - -ThreadSocketHandler : Sends/Receives data from peers on port 8333. - -ThreadMessageHandler : Higher-level message handling (sending and -receiving). - -ThreadOpenConnections : Initiates new connections to peers. - -ThreadTopUpKeyPool : replenishes the keystore's keypool. - -ThreadCleanWalletPassphrase : re-locks an encrypted wallet after user -has unlocked it for a period of time. - -SendingDialogStartTransfer : used by pay-via-ip-address code (obsolete) - -ThreadDelayedRepaint : repaint the gui - -ThreadFlushWalletDB : Close the wallet.dat file if it hasn't been used -in 500ms. - -ThreadRPCServer : Remote procedure call handler, listens on port 8332 -for connections and services them. - -ThreadBitcoinMiner : Generates bitcoins - -ThreadMapPort : Universal plug-and-play startup/shutdown - -Shutdown : Does an orderly shutdown of everything - -ExitTimeout : Windows-only, sleeps 5 seconds then exits application diff --git a/doc/readme-qt.rst b/doc/readme-qt.rst deleted file mode 100644 index 58c4417fed..0000000000 --- a/doc/readme-qt.rst +++ /dev/null @@ -1,144 +0,0 @@ -Shadow: Qt5 GUI for ShadowCoin -=============================== - -Build instructions -=================== - -Debian -------- - -First, make sure that the required packages for Qt5 development of your -distribution are installed, for Debian and Ubuntu these are: - -:: - - apt-get install qt5-default qt5-qmake qtbase5-dev-tools qttools5-dev-tools build-essential libboost-dev libboost-system-dev libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev libssl-dev libdb++-dev libminiupnpc-dev libqt5webkit5-dev - -then execute the following: - -:: - - qmake - make - -Alternatively, install Qt Creator and open the `shadow.pro` file. - -An executable named `shadow` will be built. - - -Windows --------- - -Windows build instructions: - -- Download the `QT Windows SDK`_ and install it. You don't need the Symbian stuff, just the desktop Qt. - -- Compile openssl, boost and dbcxx. - -- Open the .pro file in QT creator and build as normal (ctrl-B) - -.. _`QT Windows SDK`: http://qt-project.org/downloads - - -Mac OS X --------- - -- Download and install the `Qt Mac OS X SDK`_. It is recommended to also install Apple's Xcode with UNIX tools. - -- Download and install `MacPorts`_. - -- Execute the following commands in a terminal to get the dependencies: - -:: - - sudo port selfupdate - sudo port install boost db48 miniupnpc - -- Open the .pro file in Qt Creator and build as normal (cmd-B) - -.. _`Qt Mac OS X SDK`: http://qt-project.org/downloads -.. _`MacPorts`: http://www.macports.org/install.php - - -Build configuration options -============================ - -UPNnP port forwarding ---------------------- - -To use UPnP for port forwarding behind a NAT router (recommended, as more connections overall allow for a faster and more stable shadowcoin experience), pass the following argument to qmake: - -:: - - qmake "USE_UPNP=1" - -(in **Qt Creator**, you can find the setting for additional qmake arguments under "Projects" -> "Build Settings" -> "Build Steps", then click "Details" next to **qmake**) - -This requires miniupnpc for UPnP port mapping. It can be downloaded from -http://miniupnp.tuxfamily.org/files/. UPnP support is not compiled in by default. - -Set USE_UPNP to a different value to control this: - -+------------+--------------------------------------------------------------------------+ -| USE_UPNP=- | no UPnP support, miniupnpc not required; | -+------------+--------------------------------------------------------------------------+ -| USE_UPNP=0 | (the default) built with UPnP, support turned off by default at runtime; | -+------------+--------------------------------------------------------------------------+ -| USE_UPNP=1 | build with UPnP support turned on by default at runtime. | -+------------+--------------------------------------------------------------------------+ - -Notification support for recent (k)ubuntu versions ---------------------------------------------------- - -To see desktop notifications on (k)ubuntu versions starting from 10.04, enable usage of the -FreeDesktop notification interface through DBUS using the following qmake option: - -:: - - qmake "USE_DBUS=1" - -Generation of QR codes ------------------------ - -libqrencode may be used to generate QRCode images for payment requests. -It can be downloaded from http://fukuchi.org/works/qrencode/index.html.en, or installed via your package manager. Pass the USE_QRCODE -flag to qmake to control this: - -+--------------+--------------------------------------------------------------------------+ -| USE_QRCODE=0 | (the default) No QRCode support - libarcode not required | -+--------------+--------------------------------------------------------------------------+ -| USE_QRCODE=1 | QRCode support enabled | -+--------------+--------------------------------------------------------------------------+ - - -Berkely DB version warning -========================== - -A warning for people using the *static binary* version of ShadowCoin on a Linux/UNIX-ish system (tl;dr: **Berkely DB databases are not forward compatible**). - -The static binary version of ShadowCoin is linked against libdb 5.0 (see also `this Debian issue`_). - -Now the nasty thing is that databases from 5.X are not compatible with 4.X. - -If the globally installed development package of Berkely DB installed on your system is 5.X, any source you -build yourself will be linked against that. The first time you run with a 5.X version the database will be upgraded, -and 4.X cannot open the new format. This means that you cannot go back to the old statically linked version without -significant hassle! - -.. _`this Debian issue`: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=621425 - -Ubuntu 11.10 warning -==================== - -Ubuntu 11.10 has a package called 'qt-at-spi' installed by default. At the time of writing, having that package -installed causes shadow to crash intermittently. The issue has been reported as `launchpad bug 857790`_, but -isn't yet fixed. - -Until the bug is fixed, you can remove the qt-at-spi package to work around the problem, though this will presumably -disable screen reader functionality for Qt apps: - -:: - - sudo apt-get remove qt-at-spi - -.. _`launchpad bug 857790`: https://bugs.launchpad.net/ubuntu/+source/qt-at-spi/+bug/857790 diff --git a/doc/release-process.txt b/doc/release-process.txt deleted file mode 100644 index ed23ef3505..0000000000 --- a/doc/release-process.txt +++ /dev/null @@ -1,142 +0,0 @@ -* update translations (ping tcatm on IRC for now) - -* update (commit) version in sources - bitcoin-qt.pro - src/version.h - share/setup.nsi - doc/README* - -* tag version in git - - git tag -a v0.5.1 - -* write release notes. git shortlog helps a lot: - - git shortlog --no-merges v0.5.0.. - -* perform gitian builds - - * From a directory containing the bitcoin source, gitian-builder and gitian.sigs - export SIGNER=(your gitian key, ie bluematt, sipa, etc) - export VERSION=0.5.1 - cd ./gitian-builder - - * Fetch and build inputs: - mkdir -p inputs; cd inputs/ - wget 'http://miniupnp.free.fr/files/download.php?file=miniupnpc-1.6.tar.gz' -O miniupnpc-1.6.tar.gz - wget 'http://www.openssl.org/source/openssl-1.0.1b.tar.gz' - wget 'http://download.oracle.com/berkeley-db/db-4.8.30.NC.tar.gz' - wget 'http://zlib.net/zlib-1.2.6.tar.gz' - wget 'ftp://ftp.simplesystems.org/pub/libpng/png/src/libpng-1.5.9.tar.gz' - wget 'http://fukuchi.org/works/qrencode/qrencode-3.2.0.tar.bz2' - wget 'http://downloads.sourceforge.net/project/boost/boost/1.47.0/boost_1_47_0.tar.bz2' - wget 'http://download.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.4.tar.gz' - cd .. - ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/boost-win32.yml - cp build/out/boost-win32-1.47.0-gitian.zip inputs/ - ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/qt-win32.yml - cp build/out/qt-win32-4.7.4-gitian.zip inputs/ - ./bin/gbuild ../bitcoin/contrib/gitian-descriptors/deps-win32.yml - cp build/out/bitcoin-deps-0.0.3.zip inputs/ - - * Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32: - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml - ./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml - pushd build/out - zip -r bitcoin-${VERSION}-linux-gitian.zip * - mv bitcoin-${VERSION}-linux-gitian.zip ../../ - popd - ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml - ./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml - pushd build/out - zip -r bitcoin-${VERSION}-win32-gitian.zip * - mv bitcoin-${VERSION}-win32-gitian.zip ../../ - popd - - Build output expected: - 1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip) - 2. windows 32-bit binary, installer + source (bitcoin-${VERSION}-win32-gitian.zip) - 3. Gitian signatures (in gitian.sigs/${VERSION}[-win32]/(your gitian key)/ - -* repackage gitian builds for release as stand-alone zip/tar/installer exe - - * Linux .tar.gz: - unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux - tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux - rm -rf bitcoin-${VERSION}-linux - - * Windows .zip and setup.exe: - unzip bitcoin-${VERSION}-win32-gitian.zip -d bitcoin-${VERSION}-win32 - mv bitcoin-${VERSION}-win32/bitcoin-*-setup.exe . - zip -r bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win32 - rm -rf bitcoin-${VERSION}-win32 - -* perform Mac build - See this blog post for how Gavin set up his build environment to build the OSX - release; note that a patched version of macdeployqt is not needed anymore, as - the required functionality and fixes are implemented directly in macdeployqtplus: - http://gavintech.blogspot.com/2011/11/deploying-bitcoin-qt-on-osx.html - Gavin also had trouble with the macports py27-appscript package; he - ended up installing a version that worked with: /usr/bin/easy_install-2.7 appscript - - qmake RELEASE=1 USE_UPNP=1 USE_QRCODE=1 bitcoin-qt.pro - make - export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files - T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale) - python2.7 contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist - - Build output expected: - Bitcoin-Qt.dmg - -* upload builds to SourceForge - -* create SHA256SUMS for builds, and PGP-sign it - -* update bitcoin.org version - -* update forum version - -* update wiki download links - -* update wiki changelog: https://en.bitcoin.it/wiki/Changelog - -* Commit your signature to gitian.sigs: - pushd gitian.sigs - git add ${VERSION}/${SIGNER} - git add ${VERSION}-win32/${SIGNER} - git commit -a - git push # Assuming you can push to the gitian.sigs tree - popd - -------------------------------------------------------------------------- - -* After 3 or more people have gitian-built, repackage gitian-signed zips: - - * From a directory containing bitcoin source, gitian.sigs and gitian zips - export VERSION=0.5.1 - mkdir bitcoin-${VERSION}-linux-gitian - pushd bitcoin-${VERSION}-linux-gitian - unzip ../bitcoin-${VERSION}-linux-gitian.zip - mkdir gitian - cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ - for signer in $(ls ../gitian.sigs/${VERSION}/); do - cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert - cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig - done - zip -r bitcoin-${VERSION}-linux-gitian.zip * - cp bitcoin-${VERSION}-linux-gitian.zip ../ - popd - mkdir bitcoin-${VERSION}-win32-gitian - pushd bitcoin-${VERSION}-win32-gitian - unzip ../bitcoin-${VERSION}-win32-gitian.zip - mkdir gitian - cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/ - for signer in $(ls ../gitian.sigs/${VERSION}-win32/); do - cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert - cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig - done - zip -r bitcoin-${VERSION}-win32-gitian.zip * - cp bitcoin-${VERSION}-win32-gitian.zip ../ - popd - - * Upload gitian zips to SourceForge diff --git a/doc/torrc b/doc/torrc new file mode 100644 index 0000000000..e8ac8854d9 --- /dev/null +++ b/doc/torrc @@ -0,0 +1,30 @@ +# to activate obfs4 bridges, this file must be copied to +# windows: %APPDATA%/spectrecoin/tor/ +Bridge obfs4 154.35.22.9:12166 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 154.35.22.9:443 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1 +Bridge obfs4 154.35.22.13:443 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 +Bridge obfs4 192.99.11.54:443 7B126FAB960E5AC6A629C729434FF84FB5074EC2 cert=VW5f8+IBUWpPFxF+rsiVy2wXkyTQG7vEd+rHeN2jV5LIDNu8wMNEOqZXPwHdwMVEBdqXEw iat-mode=0 +Bridge obfs4 154.35.22.12:80 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 85.17.30.79:443 FC259A04A328A07FED1413E9FC6526530D9FD87A cert=RutxZlu8BtyP+y0NX7bAVD41+J/qXNhHUrKjFkRSdiBAhIHIQLhKQ2HxESAKZprn/lR3KA iat-mode=0 +Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 216.252.162.21:46089 0DB8799466902192B6C7576D58D4F7F714EC87C1 cert=XPUwcQPxEXExHfJYX58gZXN7mYpos7VNAHbkgERNFg+FCVNzuYo1Wp+uMscl3aR9hO2DRQ iat-mode=0 +Bridge obfs4 109.105.109.147:13764 BBB28DF0F201E706BE564EFE690FE9577DD8386D cert=KfMQN/tNMFdda61hMgpiMI7pbwU1T+wxjTulYnfw+4sgvG0zSH7N7fwT10BI8MUdAD7iJA iat-mode=2 +Bridge obfs4 154.35.22.10:80 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.11:443 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 83.212.101.3:50002 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0 +Bridge obfs4 109.105.109.165:10527 8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E cert=Bvg/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+/TfB7mqTFEfXILCjEwzVA iat-mode=1 +Bridge obfs4 154.35.22.11:80 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.12:4304 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 154.35.22.11:16488 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.9:80 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 +Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 +Bridge obfs4 154.35.22.10:443 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.13:16815 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 [2001:470:b381:bfff:216:3eff:fe23:d6c3]:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWODcgqIdPJ+rRupg4GGvVGfh25FWaIXZkit206OSngsp7GAIiGIXOJJROMxEqFKJg iat-mode=1 +Bridge obfs4 154.35.22.10:15937 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 +UseBridges 1 \ No newline at end of file diff --git a/doc/translation_process.md b/doc/translation_process.md deleted file mode 100644 index 3ddfc0cbf4..0000000000 --- a/doc/translation_process.md +++ /dev/null @@ -1,80 +0,0 @@ -Translations -============ - -The Qt GUI can be easily translated into other languages. Here's how we -handle those translations. - -Files and Folders ------------------ - -### bitcoin-qt.pro - -This file takes care of generating `.qm` files from `.ts` files. It is mostly -automated. - -### src/qt/bitcoin.qrc - -This file must be updated whenever a new translation is added. Please note that -files must end with `.qm`, not `.ts`. - - - locale/bitcoin_en.qm - ... - - -### src/qt/locale/ - -This directory contains all translations. Filenames must adhere to this format: - - bitcoin_xx_YY.ts or bitcoin_xx.ts - -#### Source file - -`src/qt/locale/bitcoin_en.ts` is treated in a special way. It is used as the -source for all other translations. Whenever a string in the code is changed -this file must be updated to reflect those changes. Usually, this can be -accomplished by running `lupdate` (included in the Qt SDK). - -An updated source file should be merged to github and transifex will pick it -up from there. Afterwards the new strings show up as "Remaining" in transifex -and can be translated. - -Syncing with transifex ----------------------- - -We are using http://transifex.net as a frontend for translating the client. - -https://www.transifex.net/projects/p/bitcoin/resource/tx/ - -The "transifex client" (see: http://help.transifex.net/features/client/) -will help with fetching new translations from transifex. Use the following -config to be able to connect with the client. - -### .tx/config - - [main] - host = https://www.transifex.net - - [bitcoin.tx] - file_filter = src/qt/locale/bitcoin_.ts - source_file = src/qt/locale/bitcoin_en.ts - source_lang = en - -### .tx/config (for Windows) - - [main] - host = https://www.transifex.net - - [bitcoin.tx] - file_filter = src\qt\locale\bitcoin_.ts - source_file = src\qt\locale\bitcoin_en.ts - source_lang = en - -It is also possible to directly download new translations one by one from transifex. - -### Fetching new translations - -1. `tx pull -a` -2. update `src/qt/bitcoin.qrc` manually or via - `ls src/qt/locale/*ts|xargs -n1 basename|sed 's/\(bitcoin_\(.*\)\).ts/locale/\1.qm<\/file>/'` -3. `git add` new translations from `src/qt/locale/` diff --git a/external/.gitignore b/external/.gitignore new file mode 100644 index 0000000000..16ff0f43e6 --- /dev/null +++ b/external/.gitignore @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT +leveldb/ +libevent/ +libzstd/ +openssl-cmake/ diff --git a/external/berkeleydb-cmake/CMakeLists.txt b/external/berkeleydb-cmake/CMakeLists.txt new file mode 100644 index 0000000000..fb8006508d --- /dev/null +++ b/external/berkeleydb-cmake/CMakeLists.txt @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# CMakeLists.txt - Main CMake configuration for BerkeleyDB library build system +# +# This file sets up the BerkeleyDB library build configuration, including: +# - Project configuration and minimum CMake version +# - Cache variables for build customization +# - Interface library target for linking +# - External project integration for building BerkeleyDB from source + +cmake_minimum_required(VERSION 3.2) +project(berkeleydb-cmake + VERSION 1.0.0 + DESCRIPTION "CMake build system for BerkeleyDB library" + LANGUAGES C CXX +) + +# Cache variables for build configuration +set(BERKELEYDB_ARCHIVE_LOCATION OFF CACHE STRING "Location of BerkeleyDB archive") +set(BERKELEYDB_BUILD_VERSION OFF CACHE STRING "BerkeleyDB version to build") +set(CROSS_ANDROID OFF CACHE BOOL "Cross-compiling for Android?") +set(CROSS OFF CACHE BOOL "Cross-compiling?") +set(CROSS_TARGET OFF CACHE STRING "Cross-compilation target") + +# Allow including our modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +# Create interface library target for linking against BerkeleyDB +# This provides a clean interface for consumers of the library +add_library(bdb INTERFACE) + +# Set up imported static library target +# This will be populated with the actual library location after build +add_library(bdb_lib STATIC IMPORTED GLOBAL) + +# Link the imported library to the interface target +target_link_libraries(bdb INTERFACE bdb_lib) + +# Set up build prefix and paths +# All build artifacts will be installed under this prefix +set(BERKELEYDB_PREFIX ${CMAKE_CURRENT_BINARY_DIR}) +message(STATUS "BERKELEYDB_PREFIX: ${BERKELEYDB_PREFIX}") + +# Path to the built BerkeleyDB C++ library +set(BERKELEYDB_LIBDB_PATH ${BERKELEYDB_PREFIX}/usr/local/BerkeleyDB.${BERKELEYDB_BUILD_VERSION_SHORT}/lib/libdb_cxx.a) +message(STATUS "BERKELEYDB_LIBDB_PATH: ${BERKELEYDB_LIBDB_PATH}") + +# Include the build script that handles the actual BerkeleyDB build process +include(BuildBerkeleyDB) + +# Set the imported library location property +# This tells CMake where to find the built library +set_target_properties(bdb_lib PROPERTIES IMPORTED_LOCATION ${BERKELEYDB_LIBDB_PATH}) + +# Set include directories for consumers of the bdb target +target_include_directories(bdb BEFORE INTERFACE ${BERKELEYDB_PREFIX}/usr/local/BerkeleyDB.${BERKELEYDB_BUILD_VERSION_SHORT}/include) + +# Ensure the external project is built before the imported target is used +add_dependencies(bdb_lib berkeleydb) diff --git a/external/berkeleydb-cmake/cmake/BuildBerkeleyDB.cmake b/external/berkeleydb-cmake/cmake/BuildBerkeleyDB.cmake new file mode 100644 index 0000000000..7992d34231 --- /dev/null +++ b/external/berkeleydb-cmake/cmake/BuildBerkeleyDB.cmake @@ -0,0 +1,288 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# BuildBerkeleyDB.cmake - CMake module for building BerkeleyDB from source +# +# This module handles the complete build process for BerkeleyDB, including: +# - Platform detection (Windows, Unix, Android cross-compilation) +# - Build tool detection (make, MSYS bash for Windows) +# - Configuration of build parameters for different platforms +# - External project setup for downloading and building BerkeleyDB +# - Environment setup for cross-compilation scenarios + +include(ProcessorCount) +include(ExternalProject) + +# Find required dependencies +find_package(Git REQUIRED) +# Use modern Python3 find module (PythonInterp is deprecated) +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Find patch utility (required for applying patches) +find_program(PATCH_PROGRAM patch) +if (NOT PATCH_PROGRAM) + message(FATAL_ERROR "Cannot find patch utility. This is only required for Android cross-compilation but due to script complexity " + "the requirement is always enforced") +endif() + +# Determine number of parallel jobs for building +ProcessorCount(NUM_JOBS) +if (NUM_JOBS EQUAL 0) + set(NUM_JOBS 1) +endif() + +# Default to Unix-like OS, will be overridden for Windows/Android +set(OS "UNIX") + +# Set up archive hash verification if provided +if (BERKELEYDB_ARCHIVE_HASH) + set(BERKELEYDB_CHECK_HASH URL_HASH SHA256=${BERKELEYDB_ARCHIVE_HASH}) +endif() + +# Skip build if library already exists +if (EXISTS ${BERKELEYDB_LIBDB_PATH}) + message(STATUS "Not building BerkeleyDB again. Remove ${BERKELEYDB_LIBDB_PATH} for rebuild") +else() + # Platform-specific build tool detection + if (WIN32 AND NOT CROSS) + # Windows needs special treatment, but neither cygwin nor msys, since they provide an UNIX-like environment + if (MINGW) + set(OS "WIN32") + message(WARNING "Building on windows is experimental") + + # Find MSYS bash for executing Unix-like commands + find_program(MSYS_BASH "bash.exe" + PATHS "C:/Msys/" "C:/MinGW/msys/" + PATH_SUFFIXES "/1.0/bin/" "/bin/" + DOC "Path to MSYS installation" + ) + if (NOT MSYS_BASH) + message(FATAL_ERROR "Specify MSYS installation path") + endif() + + set(MINGW_MAKE ${CMAKE_MAKE_PROGRAM}) + message(WARNING "Assuming your make program is a sibling of your compiler (resides in same directory)") + # Note: CYGWIN and MSYS are handled implicitly as they provide Unix-like environment + endif() + + set(MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM}) + elseif(NOT UNIX) + message(FATAL_ERROR "Unsupported platform") + else() + # On Unix-like systems, we can only use GNU make, no exotic things like Ninja + # (MSYS always uses GNU make) + find_program(MAKE_PROGRAM make) + if (NOT MAKE_PROGRAM) + message(FATAL_ERROR "Could not find 'make' program") + endif() + endif() + + # save old git values for core.autocrlf and core.eol +# execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.autocrlf OUTPUT_VARIABLE GIT_CORE_AUTOCRLF OUTPUT_STRIP_TRAILING_WHITESPACE) +# execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.eol OUTPUT_VARIABLE GIT_CORE_EOL OUTPUT_STRIP_TRAILING_WHITESPACE) + + # On windows we need to replace path to perl since CreateProcess(..) cannot handle unix paths + if (WIN32 AND NOT CROSS) + set(PERL_PATH_FIX_INSTALL sed -i -- 's/\\/usr\\/bin\\/perl/perl/g' Makefile) + else() + set(PERL_PATH_FIX_INSTALL true) + endif() + + # CROSS and CROSS_ANDROID cannot both be set (because of internal reasons) + if (CROSS AND CROSS_ANDROID) + # if user set CROSS_ANDROID and CROSS we assume he wants CROSS_ANDROID, so set CROSS to OFF + set(CROSS OFF) + endif() + + if (CROSS_ANDROID) + set(OS "LINUX_CROSS_ANDROID") + endif() + + # Python helper script for correct building environment + # This script sets up the proper environment for building on different platforms + set(BUILD_ENV_TOOL ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/building_env.py ${OS} ${MSYS_BASH} ${MINGW_MAKE}) + + # Configure script parameters + # Note: Additional modules can be disabled here if needed + # set(CONFIGURE_BERKELEYDB_MODULES no-cast no-md2 no-md4 no-mdc2 no-rc4 no-rc5 no-engine no-idea no-mdc2 no-rc5 no-camellia no-ssl3 no-heartbeats no-gost no-deprecated no-capieng no-comp no-dtls no-psk no-srp no-dso no-dsa no-rc2 no-des) + + # Additional configure script parameters + # Disable features we don't need and enable C++ support + set(CONFIGURE_BERKELEYDB_PARAMS + --disable-cryptography + --disable-partition + --disable-compression + --disable-replication + --enable-cxx + --prefix=${CMAKE_INSTALL_PREFIX} + --with-pic + ) + + # Configure build commands based on compilation target + if (CROSS) + # Standard cross-compilation configuration + set(COMMAND_CONFIGURE ../dist/configure ${CONFIGURE_BERKELEYDB_PARAMS} --cross-compile-prefix=${CROSS_PREFIX} ${CROSS_TARGET} ${CONFIGURE_BERKELEYDB_MODULES}) + set(COMMAND_TEST "true") + elseif(CROSS_ANDROID) + + # Android specific configuration options + # Note: Additional modules can be disabled here if needed + # set(CONFIGURE_BERKELEYDB_MODULES ${CONFIGURE_BERKELEYDB_MODULES} no-hw) + + # Initialize compiler flags from CMake settings + set(CFLAGS ${CMAKE_C_FLAGS}) + set(CXXFLAGS ${CMAKE_CXX_FLAGS}) + + # Silence warnings about unused arguments (Clang specific) + set(CFLAGS "${CMAKE_C_FLAGS} -Qunused-arguments") + set(CXXFLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") + + # Required environment configuration is already set (by e.g. ndk) so no need to fiddle around with all the options ... + if (NOT ANDROID) + message(FATAL_ERROR "Use NDK cmake toolchain or cmake android autoconfig") + endif() + + if (ARMEABI_V7A) + set(BERKELEYDB_PLATFORM "--host armv7") +# set(CONFIGURE_BERKELEYDB_PARAMS ${CONFIGURE_BERKELEYDB_PARAMS} "-march=armv7-a") + else() + if (CMAKE_ANDROID_ARCH_ABI MATCHES "arm64-v8a") + set(BERKELEYDB_PLATFORM "--host arm") + else() + set(BERKELEYDB_PLATFORM "--host ${CMAKE_ANDROID_ARCH_ABI}") + endif() + endif() + + set(ANDROID_STRING "android") + if (CMAKE_ANDROID_ARCH_ABI MATCHES "64") + set(ANDROID_STRING "${ANDROID_STRING}64") + endif() + + # copy over both sysroots to a common sysroot (workaround OpenSSL failing without one single sysroot) + string(REPLACE "-clang" "" ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME}) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/${ANDROID_PLATFORM_LEVEL}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/ PATTERN *.*) + file(COPY ${CMAKE_SYSROOT}/usr/include DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/) + + # Convert all CMake compiler options to environment variables + # This is required because the configure script reads from environment + set(CROSS_SYSROOT ${CMAKE_CURRENT_BINARY_DIR}/sysroot/) + set(AS ${CMAKE_ASM_COMPILER}) + set(AR ${CMAKE_AR}) + set(LD ${CMAKE_LINKER}) + set(LDFLAGS ${CMAKE_MODULE_LINKER_FLAGS}) + + # Have to surround variables with double quotes, otherwise they will be merged together without any separator + # Construct compiler commands with all necessary flags and options + set(CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_C_COMPILER_TARGET}") + set(CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_CXX_COMPILER_TARGET}") + + message(STATUS "AS: ${AS}") + message(STATUS "AR: ${AR}") + message(STATUS "LD: ${LD}") + message(STATUS "LDFLAGS: ${LDFLAGS}") + message(STATUS "CC: ${CC}") + message(STATUS "CXX: ${CXX}") + message(STATUS "ANDROID_TOOLCHAIN_ROOT: ${ANDROID_TOOLCHAIN_ROOT}") + + set(COMMAND_CONFIGURE ../dist/configure ${CONFIGURE_BERKELEYDB_PARAMS} ${BERKELEYDB_PLATFORM} ${CONFIGURE_BERKELEYDB_MODULES}) + set(COMMAND_TEST "true") + set(CONFIGURE_DIR build_android) + else() # detect host system automatically + set(COMMAND_CONFIGURE ../dist/configure ${CONFIGURE_BERKELEYDB_PARAMS} ${CONFIGURE_BERKELEYDB_MODULES}) + set(CONFIGURE_DIR build_unix) + endif() + + # Add ExternalProject target for building BerkeleyDB from source + # This downloads, patches, configures, builds, and installs BerkeleyDB + ExternalProject_Add(berkeleydb + # Note: Alternative URLs can be used for testing + # URL https://download.oracle.com/otn/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + # URL file:///home/spectre/db-6.2.38.zip + URL ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + ${BERKELEYDB_CHECK_HASH} + UPDATE_COMMAND "" + + # Apply patches for atomic operations and string literal fixes + PATCH_COMMAND patch -p2 -d ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb < ${CMAKE_CURRENT_SOURCE_DIR}/patches/db-atomic.patch + COMMAND patch -p1 -d ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb < ${CMAKE_CURRENT_SOURCE_DIR}/patches/fix-string-is-not-a-string-literal.patch + + # Update config.guess and config.sub as they're too old to detect aarch64 + # These files are used by autotools to detect the build system + COMMAND rm -f ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.guess ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.sub + COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/patches/config.guess ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.guess + COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/patches/config.sub ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.sub + COMMAND chmod +x ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.guess ${BERKELEYDB_PREFIX}/berkeleydb-prefix/src/berkeleydb/dist/config.sub + + # Configure the build + CONFIGURE_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${COMMAND_CONFIGURE} + + # Build with parallel jobs + BUILD_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} -j ${NUM_JOBS} + BUILD_BYPRODUCTS ${BERKELEYDB_LIBDB_PATH} + + # Install the built library + INSTALL_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${PERL_PATH_FIX_INSTALL} + COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} DESTDIR=${CMAKE_CURRENT_BINARY_DIR} install + # Force CMake reload to pick up the newly built library + COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} ${CMAKE_BINARY_DIR} + + # Enable logging for debugging + LOG_INSTALL 1 + LOG_CONFIGURE 1 + ) + + # set git config values to berkeleydb requirements (no impact on linux though) +# ExternalProject_Add_Step(berkeleydb setGitConfig +# COMMAND ${GIT_EXECUTABLE} config --global core.autocrlf false +# COMMAND ${GIT_EXECUTABLE} config --global core.eol lf +# DEPENDEES +# DEPENDERS download +# ALWAYS ON +# ) + + # Set, don't abort if it fails (due to variables being empty). To realize this we must only call git if the configs + # are set globally, otherwise do a no-op command ("echo 1", since "true" is not available everywhere) +# if (GIT_CORE_AUTOCRLF) +# set (GIT_CORE_AUTOCRLF_CMD ${GIT_EXECUTABLE} config --global core.autocrlf ${GIT_CORE_AUTOCRLF}) +# else() +# set (GIT_CORE_AUTOCRLF_CMD echo) +# endif() +# if (GIT_CORE_EOL) +# set (GIT_CORE_EOL_CMD ${GIT_EXECUTABLE} config --global core.eol ${GIT_CORE_EOL}) +# else() +# set (GIT_CORE_EOL_CMD echo) +# endif() + ## + + # Set git config values to previous values +# ExternalProject_Add_Step(berkeleydb restoreGitConfig +# # Unset first (is required, since old value could be omitted, which wouldn't take any effect in "set" +# COMMAND ${GIT_EXECUTABLE} config --global --unset core.autocrlf +# COMMAND ${GIT_EXECUTABLE} config --global --unset core.eol +# +# COMMAND ${GIT_CORE_AUTOCRLF_CMD} +# COMMAND ${GIT_CORE_EOL_CMD} +# +# DEPENDEES download +# DEPENDERS configure +# ALWAYS ON +# ) + + # Write environment variables to file for cross-compilation + # This file is read by the Python building_env.py script to set up the build environment + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + if (NOT _variableName MATCHES "lines") + set(OUT_FILE "${OUT_FILE}${_variableName}=\"${${_variableName}}\"\n") + endif() + endforeach() + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/buildenv.txt ${OUT_FILE}) + + # Set the imported library location property + set_target_properties(bdb_lib PROPERTIES IMPORTED_LOCATION ${BERKELEYDB_LIBDB_PATH}) +endif() diff --git a/external/berkeleydb-cmake/patches/.gitignore b/external/berkeleydb-cmake/patches/.gitignore new file mode 100644 index 0000000000..8b055cc833 --- /dev/null +++ b/external/berkeleydb-cmake/patches/.gitignore @@ -0,0 +1,2 @@ +!config.guess +!config.sub diff --git a/external/berkeleydb-cmake/patches/config.guess b/external/berkeleydb-cmake/patches/config.guess new file mode 100644 index 0000000000..e02a2ae472 --- /dev/null +++ b/external/berkeleydb-cmake/patches/config.guess @@ -0,0 +1,2005 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2020 Free Software Foundation, Inc. + +timestamp='2020-09-19' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + +me=$(echo "$0" | sed -e 's,.*/,,') + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2020 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0; do + case $1 in + --time-stamp | --time* | -t) + echo "$timestamp" + exit + ;; + --version | -v) + echo "$version" + exit + ;; + --help | --h* | -h) + echo "$usage" + exit + ;; + --) # Stop option processing + shift + break + ;; + -) # Use stdin as input. + break ;; + -*) + echo "$me: invalid option $1$help" >&2 + exit 1 + ;; + *) + break + ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp"; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null); } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2; } || + { + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + exit 1 + } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) + echo "int x;" >"$dummy.c" + for driver in cc gcc c89 c99; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if test -f /.attbin/uname; then + PATH=$PATH:/.attbin + export PATH +fi + +UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown +UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown +UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown +UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux | GNU | GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + set_cc_for_build + cat <<-EOF >"$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + #include + #ifdef __DEFINED_va_list + LIBC=musl + #else + LIBC=gnu + #endif + #endif + EOF + eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in +*:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || + "/sbin/$sysctl" 2>/dev/null || + "/usr/sbin/$sysctl" 2>/dev/null || + echo unknown)) + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') + endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm* | i386 | m68k | ns32k | sh3* | sparc | vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null | + grep -q __ELF__; then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi-}" + exit + ;; +*:Bitrig:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit + ;; +*:OpenBSD:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit + ;; +*:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit + ;; +*:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit + ;; +*:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit + ;; +*:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit + ;; +*:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit + ;; +macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit + ;; +*:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit + ;; +*:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit + ;; +*:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit + ;; +*:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit + ;; +mips:OSF1:*.*) + echo mips-dec-osf1 + exit + ;; +alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') + ;; + *5.*) + UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha + ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha + ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha + ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 + ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 + ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 + ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 + ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 + ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 + ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 + ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 + ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 + ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 + ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 + ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 + ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode + ;; +Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit + ;; +*:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit + ;; +*:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit + ;; +*:OS/390:*:*) + echo i370-ibm-openedition + exit + ;; +*:z/VM:*:*) + echo s390-ibm-zvmoe + exit + ;; +*:OS400:*:*) + echo powerpc-ibm-os400 + exit + ;; +arm:RISC*:1.[012]*:* | arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit + ;; +arm*:riscos:*:* | arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit + ;; +SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit + ;; +Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "$( (/bin/universe) 2>/dev/null)" = att; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit + ;; +NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit + ;; +DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit + ;; +DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case $(/usr/bin/uname -p) in + sparc) + echo sparc-icl-nx7 + exit + ;; + esac + ;; +s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit + ;; +i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if test "$CC_FOR_BUILD" != no_compiler_found; then + if ( + echo '#ifdef __amd64' + echo IS_64BIT_ARCH + echo '#endif' + ) | + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep IS_64BIT_ARCH >/dev/null; then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +sun4*:SunOS:*:*) + case "$(/usr/bin/arch -k)" in + Series* | S4*) + UNAME_RELEASE=$(uname -v) + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"$(echo "$UNAME_RELEASE" | sed -e 's/-/_/')" + exit + ;; +sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit + ;; +sun*:*:4.2BSD:*) + UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "$(/bin/arch)" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit + ;; +aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit + ;; +# The situation for MiNT is a little confusing. The machine name +# can be virtually everything (everything which is not +# "atarist" or "atariste" at least should have a processor +# > m68000). The system name ranges from "MiNT" over "FreeMiNT" +# to the lowercase version "mint" (or "freemint"). Finally +# the system name "TOS" denotes a system which is actually not +# MiNT. But MiNT is downward compatible to TOS, so this should +# be no problem. +atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit + ;; +atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit + ;; +*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit + ;; +milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit + ;; +hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit + ;; +*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit + ;; +m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit + ;; +powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit + ;; +RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit + ;; +RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit + ;; +VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit + ;; +2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit + ;; +mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' <"$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && + SYSTEM_NAME=$("$dummy" "$dummyarg") && + { + echo "$SYSTEM_NAME" + exit + } + echo mips-mips-riscos"$UNAME_RELEASE" + exit + ;; +Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit + ;; +Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit + ;; +Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit + ;; +Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit + ;; +m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit + ;; +m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit + ;; +m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit + ;; +AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=$(/usr/bin/uname -p) + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110; then + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || + test "$TARGET_BINARY_INTERFACE"x = x; then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit + ;; +M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit + ;; +M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit + ;; +XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit + ;; +Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit + ;; +*:IRIX*:*:*) + echo mips-sgi-irix"$(echo "$UNAME_RELEASE" | sed -e 's/-/_/g')" + exit + ;; +????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' +i*86:AIX:*:*) + echo i386-ibm-aix + exit + ;; +ia64:AIX:*:*) + if test -x /usr/bin/oslevel; then + IBM_REV=$(/usr/bin/oslevel) + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit + ;; +*:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' <"$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy"); then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit + ;; +*:AIX:*:[4567]) + IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if test -x /usr/bin/lslpp; then + IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit + ;; +*:AIX:*:*) + echo rs6000-ibm-aix + exit + ;; +ibmrt:4.4BSD:* | romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit + ;; +ibmrt:*BSD:* | romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit + ;; # report: romp-ibm BSD 4.3 +*:BOSX:*:*) + echo rs6000-bull-bosx + exit + ;; +DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit + ;; +9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit + ;; +hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit + ;; +9000/[34678]??:HP-UX:*:*) + HPUX_REV=$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//') + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if test -x /usr/bin/getconf; then + sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) + sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' <"$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") + test -z "$HP_ARCH" && HP_ARCH=hppa + fi + ;; + esac + if test "$HP_ARCH" = hppa2.0w; then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__; then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit + ;; +ia64:HP-UX:*:*) + HPUX_REV=$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//') + echo ia64-hp-hpux"$HPUX_REV" + exit + ;; +3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' <"$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && + { + echo "$SYSTEM_NAME" + exit + } + echo unknown-hitachi-hiuxwe2 + exit + ;; +9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit + ;; +9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit + ;; +*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit + ;; +hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit + ;; +hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit + ;; +i*86:OSF1:*:*) + if test -x /usr/sbin/sysversion; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit + ;; +parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit + ;; +C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit + ;; +C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc; then + echo c32-convex-bsd + else + echo c2-convex-bsd + fi + exit + ;; +C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit + ;; +C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit + ;; +C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit + ;; +CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit + ;; +CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" | + sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit + ;; +CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit + ;; +CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit + ;; +CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit + ;; +*:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit + ;; +F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) + FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') + FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit + ;; +5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') + FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit + ;; +i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit + ;; +sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit + ;; +*:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit + ;; +arm:FreeBSD:*:*) + UNAME_PROCESSOR=$(uname -p) + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null | + grep -q __ARM_PCS_VFP; then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE} | sed -e 's/[-(].*//')"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE} | sed -e 's/[-(].*//')"-gnueabihf + fi + exit + ;; +*:FreeBSD:*:*) + UNAME_PROCESSOR=$(/usr/bin/uname -p) + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 + ;; + i386) + UNAME_PROCESSOR=i586 + ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE" | sed -e 's/[-(].*//')" + exit + ;; +i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit + ;; +*:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit + ;; +*:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit + ;; +*:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit + ;; +i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit + ;; +*:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit + ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit + ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit + ;; + esac + ;; +i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit + ;; +amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-pc-cygwin + exit + ;; +prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" + exit + ;; +*:GNU:*:*) + # the GNU system + echo "$(echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE" | sed -e 's,/.*$,,')" + exit + ;; +*:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE" | sed -e 's/[-(].*//')-$LIBC" + exit + ;; +*:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix + exit + ;; +aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +alpha:Linux:*:*) + case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0; then LIBC=gnulibc1; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null | + grep -q __ARM_EABI__; then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null | + grep -q __ARM_PCS_VFP; then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit + ;; +avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit + ;; +crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit + ;; +e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit + ;; +ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' <"$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" + test "x$CPU" != x && { + echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI" + exit + } + ;; +mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit + ;; +or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit + ;; +parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit + ;; +parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit + ;; +ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit + ;; +ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit + ;; +ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit + ;; +ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit + ;; +riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit + ;; +sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit + ;; +x86_64:Linux:*:*) + set_cc_for_build + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + if ( + echo '#ifdef __ILP32__' + echo IS_X32 + echo '#endif' + ) | + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep IS_X32 >/dev/null; then + LIBCABI="$LIBC"x32 + fi + fi + echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" + exit + ;; +xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit + ;; +i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit + ;; +i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit + ;; +i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit + ;; +i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit + ;; +i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit + ;; +i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit + ;; +i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit + ;; +i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit + ;; +i*86:*:4.*:*) + UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit + ;; +i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case $(/bin/uname -X | grep "^Machine") in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent* | *Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" + exit + ;; +i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null; then + UNAME_REL=$( (/bin/uname -X | grep Release | sed -e 's/.*= //')) + (/bin/uname -X | grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X | grep '^Machine.*Pentium' >/dev/null) && + UNAME_MACHINE=i586 + (/bin/uname -X | grep '^Machine.*Pent *II' >/dev/null) && + UNAME_MACHINE=i686 + (/bin/uname -X | grep '^Machine.*Pentium Pro' >/dev/null) && + UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit + ;; +pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit + ;; +Intel:Mach:3*:*) + echo i386-pc-mach3 + exit + ;; +paragon:*:*:*) + echo i860-intel-osf1 + exit + ;; +i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit + ;; +mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit + ;; +mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit + ;; +M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit + ;; +M68*:*:R3V[5678]*:*) + test -r /sysV68 && { + echo 'm68k-motorola-sysv' + exit + } + ;; +3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid && + OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' /dev/null | grep 86 >/dev/null && + { + echo i486-ncr-sysv4.3"$OS_REL" + exit + } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null && + { + echo i586-ncr-sysv4.3"$OS_REL" + exit + } + ;; +3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null && + { + echo i486-ncr-sysv4 + exit + } + ;; +NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid && + OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' /dev/null | grep 86 >/dev/null && + { + echo i486-ncr-sysv4.3"$OS_REL" + exit + } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null && + { + echo i586-ncr-sysv4.3"$OS_REL" + exit + } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null && + { + echo i586-ncr-sysv4.3"$OS_REL" + exit + } + ;; +m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit + ;; +mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit + ;; +TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit + ;; +rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit + ;; +PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit + ;; +SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit + ;; +RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit + ;; +RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit + ;; +*:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null; then + UNAME_MACHINE=$( (uname -p) 2>/dev/null) + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit + ;; +PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit + ;; +*:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit + ;; +*:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit + ;; +i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit + ;; +*:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit + ;; +mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit + ;; +news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit + ;; +R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if test -d /usr/nec; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit + ;; +BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit + ;; +BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit + ;; +BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit + ;; +BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit + ;; +x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit + ;; +SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit + ;; +SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit + ;; +Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit + ;; +*:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit + ;; +arm64:Darwin:*:*) + echo aarch64-apple-darwin"$UNAME_RELEASE" + exit + ;; +*:Darwin:*:*) + UNAME_PROCESSOR=$(uname -p) + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select >/dev/null 2>/dev/null && + ! xcode-select --print-path >/dev/null 2>/dev/null; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if ( + echo '#ifdef __LP64__' + echo IS_64BIT_ARCH + echo '#endif' + ) | + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep IS_64BIT_ARCH >/dev/null; then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if ( + echo '#ifdef __POWERPC__' + echo IS_PPC + echo '#endif' + ) | + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep IS_PPC >/dev/null; then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit + ;; +*:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=$(uname -p) + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit + ;; +*:QNX:*:4*) + echo i386-pc-qnx + exit + ;; +NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit + ;; +NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit + ;; +NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit + ;; +NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit + ;; +NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit + ;; +*:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit + ;; +BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit + ;; +DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit + ;; +*:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + # shellcheck disable=SC2154 + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit + ;; +*:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit + ;; +*:TENEX:*:*) + echo pdp10-unknown-tenex + exit + ;; +KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit + ;; +XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit + ;; +*:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit + ;; +*:ITS:*:*) + echo pdp10-unknown-its + exit + ;; +SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit + ;; +*:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE" | sed -e 's/[-(].*//')" + exit + ;; +*:*VMS:*:*) + UNAME_MACHINE=$( (uname -p) 2>/dev/null) + case "$UNAME_MACHINE" in + A*) + echo alpha-dec-vms + exit + ;; + I*) + echo ia64-dec-vms + exit + ;; + V*) + echo vax-dec-vms + exit + ;; + esac + ;; +*:XENIX:*:SysV) + echo i386-pc-xenix + exit + ;; +i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" + exit + ;; +i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit + ;; +i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit + ;; +x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit + ;; +amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit + ;; +*:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit + ;; +esac + +# No uname command or uname output not recognized. +set_cc_for_build +cat >"$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && + { + echo "$SYSTEM_NAME" + exit + } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { + echo "$ISP-apollo-$SYSTYPE" + exit +} + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in +mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 <&2 </dev/null || echo unknown) +uname -r = $( (uname -r) 2>/dev/null || echo unknown) +uname -s = $( (uname -s) 2>/dev/null || echo unknown) +uname -v = $( (uname -v) 2>/dev/null || echo unknown) + +/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) +/bin/uname -X = $( (/bin/uname -X) 2>/dev/null) + +hostinfo = $( (hostinfo) 2>/dev/null) +/bin/universe = $( (/bin/universe) 2>/dev/null) +/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) +/bin/arch = $( (/bin/arch) 2>/dev/null) +/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) +/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF +fi + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/external/berkeleydb-cmake/patches/config.sub b/external/berkeleydb-cmake/patches/config.sub new file mode 100644 index 0000000000..8167d0871e --- /dev/null +++ b/external/berkeleydb-cmake/patches/config.sub @@ -0,0 +1,1853 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2020 Free Software Foundation, Inc. + +timestamp='2020-10-13' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2020 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac + ;; + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac + ;; +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond + ;; + op50n) + cpu=hppa1.1 + vendor=oki + ;; + op60c) + cpu=hppa1.1 + vendor=oki + ;; + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + basic_os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + basic_os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $basic_os in + irix*) + ;; + *) + basic_os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + basic_os=nextstep2 + ;; + *) + basic_os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + basic_os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` + ;; + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <&2 + exit 1 + ;; + esac + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $vendor in + digital*) + vendor=dec + ;; + commodore*) + vendor=cbm + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if test x$basic_os != x +then + +# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo $basic_os | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo $basic_os | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + IFS="-" read kernel os <&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) + ;; + uclinux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) + vendor=acorn + ;; + *-sunos*) + vendor=sun + ;; + *-cnk* | *-aix*) + vendor=ibm + ;; + *-beos*) + vendor=be + ;; + *-hpux*) + vendor=hp + ;; + *-mpeix*) + vendor=hp + ;; + *-hiux*) + vendor=hitachi + ;; + *-unos*) + vendor=crds + ;; + *-dgux*) + vendor=dg + ;; + *-luna*) + vendor=omron + ;; + *-genix*) + vendor=ns + ;; + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) + vendor=sequent + ;; + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) + vendor=wrs + ;; + *-aux*) + vendor=apple + ;; + *-hms*) + vendor=hitachi + ;; + *-mpw* | *-macos*) + vendor=apple + ;; + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + vendor=atari + ;; + *-vos*) + vendor=stratus + ;; + esac + ;; +esac + +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/external/berkeleydb-cmake/patches/db-atomic.patch b/external/berkeleydb-cmake/patches/db-atomic.patch new file mode 100644 index 0000000000..99d03e9156 --- /dev/null +++ b/external/berkeleydb-cmake/patches/db-atomic.patch @@ -0,0 +1,141 @@ +diff --git a/src/dbinc/atomic.h b/src/dbinc/atomic.h +index 6a858f7..9f338dc 100644 +--- a/src/dbinc/atomic.h ++++ b/src/dbinc/atomic.h +@@ -70,7 +70,7 @@ typedef struct { + * These have no memory barriers; the caller must include them when necessary. + */ + #define atomic_read(p) ((p)->value) +-#define atomic_init(p, val) ((p)->value = (val)) ++#define atomic_init_db(p, val) ((p)->value = (val)) + + #ifdef HAVE_ATOMIC_SUPPORT + +@@ -144,7 +144,7 @@ typedef LONG volatile *interlocked_val; + #define atomic_inc(env, p) __atomic_inc(p) + #define atomic_dec(env, p) __atomic_dec(p) + #define atomic_compare_exchange(env, p, o, n) \ +- __atomic_compare_exchange((p), (o), (n)) ++ __atomic_compare_exchange_db((p), (o), (n)) + static inline int __atomic_inc(db_atomic_t *p) + { + int temp; +@@ -176,7 +176,7 @@ static inline int __atomic_dec(db_atomic_t *p) + * http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html + * which configure could be changed to use. + */ +-static inline int __atomic_compare_exchange( ++static inline int __atomic_compare_exchange_db( + db_atomic_t *p, atomic_value_t oldval, atomic_value_t newval) + { + atomic_value_t was; +@@ -206,7 +206,7 @@ static inline int __atomic_compare_exchange( + #define atomic_dec(env, p) (--(p)->value) + #define atomic_compare_exchange(env, p, oldval, newval) \ + (DB_ASSERT(env, atomic_read(p) == (oldval)), \ +- atomic_init(p, (newval)), 1) ++ atomic_init_db(p, (newval)), 1) + #else + #define atomic_inc(env, p) __atomic_inc(env, p) + #define atomic_dec(env, p) __atomic_dec(env, p) +diff --git a/src/mp/mp_fget.c b/src/mp/mp_fget.c +index 16de695..d0dcc29 100644 +--- a/src/mp/mp_fget.c ++++ b/src/mp/mp_fget.c +@@ -649,7 +649,7 @@ alloc: /* Allocate a new buffer header and data space. */ + + /* Initialize enough so we can call __memp_bhfree. */ + alloc_bhp->flags = 0; +- atomic_init(&alloc_bhp->ref, 1); ++ atomic_init_db(&alloc_bhp->ref, 1); + #ifdef DIAGNOSTIC + if ((uintptr_t)alloc_bhp->buf & (sizeof(size_t) - 1)) { + __db_errx(env, DB_STR("3025", +@@ -955,7 +955,7 @@ alloc: /* Allocate a new buffer header and data space. */ + MVCC_MPROTECT(bhp->buf, mfp->pagesize, + PROT_READ); + +- atomic_init(&alloc_bhp->ref, 1); ++ atomic_init_db(&alloc_bhp->ref, 1); + MUTEX_LOCK(env, alloc_bhp->mtx_buf); + alloc_bhp->priority = bhp->priority; + alloc_bhp->pgno = bhp->pgno; +diff --git a/src/mp/mp_mvcc.c b/src/mp/mp_mvcc.c +index 770bad8..e28cce0 100644 +--- a/src/mp/mp_mvcc.c ++++ b/src/mp/mp_mvcc.c +@@ -276,7 +276,7 @@ __memp_bh_freeze(dbmp, infop, hp, bhp, need_frozenp) + #else + memcpy(frozen_bhp, bhp, SSZA(BH, buf)); + #endif +- atomic_init(&frozen_bhp->ref, 0); ++ atomic_init_db(&frozen_bhp->ref, 0); + if (mutex != MUTEX_INVALID) + frozen_bhp->mtx_buf = mutex; + else if ((ret = __mutex_alloc(env, MTX_MPOOL_BH, +@@ -428,7 +428,7 @@ __memp_bh_thaw(dbmp, infop, hp, frozen_bhp, alloc_bhp) + #endif + alloc_bhp->mtx_buf = mutex; + MUTEX_LOCK(env, alloc_bhp->mtx_buf); +- atomic_init(&alloc_bhp->ref, 1); ++ atomic_init_db(&alloc_bhp->ref, 1); + F_CLR(alloc_bhp, BH_FROZEN); + } + +diff --git a/src/mp/mp_region.c b/src/mp/mp_region.c +index 4952030..47645f8 100644 +--- a/src/mp/mp_region.c ++++ b/src/mp/mp_region.c +@@ -245,7 +245,7 @@ __memp_init(env, dbmp, reginfo_off, htab_buckets, max_nreg) + MTX_MPOOL_FILE_BUCKET, 0, &htab[i].mtx_hash)) != 0) + return (ret); + SH_TAILQ_INIT(&htab[i].hash_bucket); +- atomic_init(&htab[i].hash_page_dirty, 0); ++ atomic_init_db(&htab[i].hash_page_dirty, 0); + } + + /* +@@ -302,7 +302,7 @@ no_prealloc: + } else + hp->mtx_hash = mtx_base + (i % dbenv->mp_mtxcount); + SH_TAILQ_INIT(&hp->hash_bucket); +- atomic_init(&hp->hash_page_dirty, 0); ++ atomic_init_db(&hp->hash_page_dirty, 0); + #ifdef HAVE_STATISTICS + hp->hash_io_wait = 0; + hp->hash_frozen = hp->hash_thawed = hp->hash_frozen_freed = 0; +diff --git a/src/mutex/mut_method.c b/src/mutex/mut_method.c +index 09353b0..177353c 100644 +--- a/src/mutex/mut_method.c ++++ b/src/mutex/mut_method.c +@@ -474,7 +474,7 @@ atomic_compare_exchange(env, v, oldval, newval) + MUTEX_LOCK(env, mtx); + ret = atomic_read(v) == oldval; + if (ret) +- atomic_init(v, newval); ++ atomic_init_db(v, newval); + MUTEX_UNLOCK(env, mtx); + + return (ret); +diff --git a/src/mutex/mut_tas.c b/src/mutex/mut_tas.c +index 106b161..fc4de9d 100644 +--- a/src/mutex/mut_tas.c ++++ b/src/mutex/mut_tas.c +@@ -47,7 +47,7 @@ __db_tas_mutex_init(env, mutex, flags) + + #ifdef HAVE_SHARED_LATCHES + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) +- atomic_init(&mutexp->sharecount, 0); ++ atomic_init_db(&mutexp->sharecount, 0); + else + #endif + if (MUTEX_INIT(&mutexp->tas)) { +@@ -536,7 +536,7 @@ __db_tas_mutex_unlock(env, mutex) + F_CLR(mutexp, DB_MUTEX_LOCKED); + /* Flush flag update before zeroing count */ + MEMBAR_EXIT(); +- atomic_init(&mutexp->sharecount, 0); ++ atomic_init_db(&mutexp->sharecount, 0); + } else { + DB_ASSERT(env, sharecount > 0); + MEMBAR_EXIT(); \ No newline at end of file diff --git a/external/berkeleydb-cmake/patches/fix-string-is-not-a-string-literal.patch b/external/berkeleydb-cmake/patches/fix-string-is-not-a-string-literal.patch new file mode 100644 index 0000000000..6f90a760ef --- /dev/null +++ b/external/berkeleydb-cmake/patches/fix-string-is-not-a-string-literal.patch @@ -0,0 +1,29 @@ +--- a/txn/txn.c 2010-04-12 20:25:37.000000000 +0000 ++++ b/txn/txn.c 2019-11-22 19:42:03.584526294 +0000 +@@ -77,8 +77,6 @@ + static int __txn_undo __P((DB_TXN *)); + static void __txn_set_txn_lsnp __P((DB_TXN *, DB_LSN **, DB_LSN **)); + +-static char *TxnAlloc = "Unable to allocate a transaction handle"; +- + /* + * __txn_begin_pp -- + * ENV->txn_begin pre/post processing. +@@ -168,7 +166,7 @@ + + *txnpp = NULL; + if ((ret = __os_calloc(env, 1, sizeof(DB_TXN), &txn)) != 0) { +- __db_errx(env, TxnAlloc); ++ __db_errx(env, "Unable to allocate a transaction handle"); + return (ret); + } + +@@ -315,7 +313,7 @@ + int ret; + + if ((ret = __os_calloc(env, 1, sizeof(DB_TXN), &txn)) != 0) { +- __db_errx(env, TxnAlloc); ++ __db_errx(env, "Unable to allocate a transaction handle"); + return (ret); + } + diff --git a/external/berkeleydb-cmake/scripts/building_env.py b/external/berkeleydb-cmake/scripts/building_env.py new file mode 100644 index 0000000000..92cf76490f --- /dev/null +++ b/external/berkeleydb-cmake/scripts/building_env.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# building_env.py - Build environment setup script for BerkeleyDB +# +# Creates a building environment for BerkeleyDB: +# - Sets working directory +# - On Windows: uses MSYS bash for command execution (BerkeleyDB's scripts need an UNIX-like environment with perl) +# - Handles cross-compilation environment setup for Android + +from subprocess import PIPE, Popen +from sys import argv +import os +import re + +env = os.environ +l = [] + +os_s = argv[1] # operating system +offset = 2 # 0: this script's path, 1: operating system + +if os_s == "WIN32": + offset = 4 # 2: MSYS_BASH_PATH, 3: CMAKE_MAKE_PROGRAM + + # + bash = argv[2] + msys_path = os.path.dirname(bash) + mingw_path = os.path.dirname(argv[3]) + + # append ; to PATH if needed + if not env['PATH'].endswith(";"): + env['PATH'] += ";" + + # include path of msys binaries (perl, cd etc.) and building tools (gcc, ld etc.) + env['PATH'] = ";".join([msys_path, mingw_path])+";"+env['PATH'] + env['MAKEFLAGS'] = '' # otherwise: internal error: invalid --jobserver-fds string `gmake_semaphore_1824' + + +binary_berkeleydb_dir_source = argv[offset]+"/" # downloaded berkeleydb source dir +l.extend(argv[offset+1:]) # routed commands + +l[0] = '"'+l[0]+'"' + +# ensure target dir exists for mingw cross +target_dir = binary_berkeleydb_dir_source+"/../../../usr/local/bin" +if not os.path.exists(target_dir): + os.makedirs(target_dir) + +# Read environment from file if cross-compiling for Android +if os_s == "LINUX_CROSS_ANDROID": + expr = re.compile(r'^(.*?)="(.*?)"', re.MULTILINE | re.DOTALL) + # Note: Using string concatenation for relative paths with ../ + env_file_path = binary_berkeleydb_dir_source + "/../../../../buildenv.txt" + + # Use modern Python file handling with context manager + with open(env_file_path, "r", encoding='utf-8') as f: + content = f.read() + + for k, v in expr.findall(content): + if "\n" in k.strip(): + print('Skipping multiline key') + elif k != "PATH": + env[k] = v.replace('"', '') + else: + # Prepend to PATH to ensure cross-compilation tools are found first + env[k] = v.replace('"', '') + ":" + env[k] + +# Execute the build command in the appropriate environment +proc = None +if os_s == "WIN32": + # We must emulate a UNIX environment to build BerkeleyDB using MinGW/MSYS + proc = Popen(bash, env=env, cwd=binary_berkeleydb_dir_source, stdin=PIPE, universal_newlines=True) + proc.communicate(input=" ".join(l) + " || exit $?") +else: + # On Unix-like systems, execute directly with shell + proc = Popen(" ".join(l) + " || exit $?", shell=True, env=env, cwd=binary_berkeleydb_dir_source) + proc.communicate() + +# Exit with the return code from the build command +exit(proc.returncode) diff --git a/external/libxz-cmake/CMakeLists.txt b/external/libxz-cmake/CMakeLists.txt new file mode 100755 index 0000000000..217676a5c0 --- /dev/null +++ b/external/libxz-cmake/CMakeLists.txt @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# CMakeLists.txt - Main CMake configuration for XZ/LZMA library build system +# +# This file sets up the XZ library (liblzma) build configuration, including: +# - Project configuration and minimum CMake version +# - Cache variables for build customization +# - Interface library target for linking +# - External project integration for building XZ from source + +cmake_minimum_required(VERSION 3.2) +project(libxz-cmake + VERSION 1.0.0 + DESCRIPTION "CMake build system for XZ/LZMA library" + LANGUAGES C +) + +# Cache variables for build configuration +set(LIBLZMA_ARCHIVE_LOCATION OFF CACHE STRING "Location of XZLib archive") +set(LIBLZMA_BUILD_VERSION OFF CACHE STRING "XZLib version to build") +set(CROSS_ANDROID OFF CACHE BOOL "Cross-compiling for Android?") +set(CROSS OFF CACHE BOOL "Cross-compiling?") +set(CROSS_TARGET OFF CACHE STRING "Cross-compilation target") + +# Allow including our modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +# Create interface library target for linking against liblzma +# This provides a clean interface for consumers of the library +add_library(liblzma INTERFACE) + +# Set up imported static library target +# This will be populated with the actual library location after build +add_library(lib_lzma STATIC IMPORTED GLOBAL) + +# Link the imported library to the interface target +target_link_libraries(liblzma INTERFACE lib_lzma) + +# Set up build prefix and paths +# All build artifacts will be installed under this prefix +set(LIBLZMA_PREFIX ${CMAKE_CURRENT_BINARY_DIR}) +message(STATUS "LIBLZMA_PREFIX: ${LIBLZMA_PREFIX}") + +# Path to the built liblzma static library +set(LIBLZMA_PATH ${LIBLZMA_PREFIX}/usr/local/lib/liblzma.a) +message(STATUS "LIBLZMA_PATH ${LIBLZMA_PATH}") + +# Include the build script that handles the actual XZ library build process +include(BuildXZLib) + +# Set the imported library location property +# This tells CMake where to find the built library +set_target_properties(lib_lzma PROPERTIES IMPORTED_LOCATION ${LIBLZMA_PATH}) + +# Set include directories for consumers of the liblzma target +target_include_directories(liblzma BEFORE INTERFACE ${LIBLZMA_PREFIX}/usr/local/include) + +# Ensure the external project is built before the imported target is used +add_dependencies(lib_lzma libxzExternal) diff --git a/external/libxz-cmake/cmake/BuildXZLib.cmake b/external/libxz-cmake/cmake/BuildXZLib.cmake new file mode 100755 index 0000000000..2dd65765c7 --- /dev/null +++ b/external/libxz-cmake/cmake/BuildXZLib.cmake @@ -0,0 +1,276 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# BuildXZLib.cmake - CMake module for building XZ/LZMA library from source +# +# This module handles the complete build process for XZ library, including: +# - Platform detection (Windows, Unix, Android cross-compilation) +# - Build tool detection (make, MSYS bash for Windows) +# - Configuration of build parameters for different platforms +# - External project setup for downloading and building XZ +# - Environment setup for cross-compilation scenarios + +include(ProcessorCount) +include(ExternalProject) + +# Find required dependencies +find_package(Git REQUIRED) +# Use modern Python3 find module (PythonInterp is deprecated) +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Find patch utility (required for applying patches) +find_program(PATCH_PROGRAM patch) +if (NOT PATCH_PROGRAM) + message(FATAL_ERROR "Cannot find patch utility. This is only required for Android cross-compilation but due to script complexity " + "the requirement is always enforced") +endif() + +# Determine number of parallel jobs for building +ProcessorCount(NUM_JOBS) +if (NUM_JOBS EQUAL 0) + set(NUM_JOBS 1) +endif() + +# Default to Unix-like OS, will be overridden for Windows/Android +set(OS "UNIX") + +# Set up archive hash verification if provided +if (LIBXZ_ARCHIVE_HASH) + set(LIBLZMA_CHECK_HASH URL_HASH SHA256=${LIBXZ_ARCHIVE_HASH}) +endif() + +# Skip build if library already exists +if (EXISTS ${LIBLZMA_PATH}) + message(STATUS "Not building XZLib again. Remove ${LIBLZMA_PATH} for rebuild") +else() + # Platform-specific build tool detection + if (WIN32 AND NOT CROSS) + # Windows needs special treatment, but neither cygwin nor msys, since they provide an UNIX-like environment + if (MINGW) + set(OS "WIN32") + message(WARNING "Building on windows is experimental") + + # Find MSYS bash for executing Unix-like commands + find_program(MSYS_BASH "bash.exe" + PATHS "C:/Msys/" "C:/MinGW/msys/" + PATH_SUFFIXES "/1.0/bin/" "/bin/" + DOC "Path to MSYS installation" + ) + if (NOT MSYS_BASH) + message(FATAL_ERROR "Specify MSYS installation path") + endif() + + set(MINGW_MAKE ${CMAKE_MAKE_PROGRAM}) + message(WARNING "Assuming your make program is a sibling of your compiler (resides in same directory)") + elseif(NOT (CYGWIN OR MSYS)) + message(FATAL_ERROR "Unsupported compiler infrastructure") + endif() + + set(MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM}) + elseif(NOT UNIX) + message(FATAL_ERROR "Unsupported platform") + else() + # On Unix-like systems, we can only use GNU make, no exotic things like Ninja + # (MSYS always uses GNU make) + find_program(MAKE_PROGRAM make) + if (NOT MAKE_PROGRAM) + message(FATAL_ERROR "Could not find 'make' program") + endif() + endif() + + # save old git values for core.autocrlf and core.eol + #execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.autocrlf OUTPUT_VARIABLE GIT_CORE_AUTOCRLF OUTPUT_STRIP_TRAILING_WHITESPACE) + #execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.eol OUTPUT_VARIABLE GIT_CORE_EOL OUTPUT_STRIP_TRAILING_WHITESPACE) + + # On windows we need to replace path to perl since CreateProcess(..) cannot handle unix paths + if (WIN32 AND NOT CROSS) + set(PERL_PATH_FIX_INSTALL sed -i -- 's/\\/usr\\/bin\\/perl/perl/g' Makefile) + else() + set(PERL_PATH_FIX_INSTALL true) + endif() + + # CROSS and CROSS_ANDROID cannot both be set (because of internal reasons) + if (CROSS AND CROSS_ANDROID) + # if user set CROSS_ANDROID and CROSS we assume he wants CROSS_ANDROID, so set CROSS to OFF + set(CROSS OFF) + endif() + + if (CROSS_ANDROID) + set(OS "LINUX_CROSS_ANDROID") + endif() + + # Python helper script for correct building environment + # This script sets up the proper environment for building on different platforms + set(BUILD_ENV_TOOL ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/building_env.py ${OS} ${MSYS_BASH} ${MINGW_MAKE}) + + # Disable everything we don't need (only build the library, not utilities) + set(CONFIGURE_LIBLZMA_MODULES + --disable-doc + --disable-scripts + --disable-xz + --disable-xzdec + --disable-lzmadec + --disable-lzmainfo + --disable-lzma-links + ) + + # Additional configure script parameters + # Enable both shared and static libraries + set(CONFIGURE_LIBLZMA_PARAMS --enable-shared --enable-static) + + # Configure build commands based on compilation target + if (CROSS) + # Standard cross-compilation configuration + set(COMMAND_CONFIGURE ../dist/configure ${CONFIGURE_LIBLZMA_PARAMS} --cross-compile-prefix=${CROSS_PREFIX} ${CROSS_TARGET} ${CONFIGURE_LIBLZMA_MODULES} --prefix=/usr/local/) + set(COMMAND_TEST "true") + elseif(CROSS_ANDROID) + + # Android specific configuration options + # Note: Additional modules can be disabled here if needed + # set(CONFIGURE_LIBLZMA_MODULES ${CONFIGURE_LIBLZMA_MODULES} no-hw) + + # Initialize compiler flags from CMake settings + set(CFLAGS ${CMAKE_C_FLAGS}) + set(CXXFLAGS ${CMAKE_CXX_FLAGS}) + + # Silence warnings about unused arguments (Clang specific) + set(CFLAGS "${CMAKE_C_FLAGS} -Qunused-arguments") + set(CXXFLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") + + # Required environment configuration is already set (by e.g. ndk) so no need to fiddle around with all the options ... + if (NOT ANDROID) + message(FATAL_ERROR "Use NDK cmake toolchain or cmake android autoconfig") + endif() + + if (ARMEABI_V7A) + set(LIBLZMA_PLATFORM "--host armv7") + #set(CONFIGURE_LIBLZMA_PARAMS ${CONFIGURE_LIBLZMA_PARAMS} "-march=armv7-a") + else() + if (CMAKE_ANDROID_ARCH_ABI MATCHES "arm64-v8a") + set(LIBLZMA_PLATFORM "--host=aarch64-linux-android") + else() + set(LIBLZMA_PLATFORM "--host=${CMAKE_ANDROID_ARCH_ABI}") + endif() + endif() + + set(ANDROID_STRING "android") + if (CMAKE_ANDROID_ARCH_ABI MATCHES "64") + set(ANDROID_STRING "${ANDROID_STRING}64") + endif() + + # copy over both sysroots to a common sysroot (workaround OpenSSL failing without one single sysroot) + string(REPLACE "-clang" "" ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME}) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/${ANDROID_PLATFORM_LEVEL}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/ PATTERN *.*) + file(COPY ${CMAKE_SYSROOT}/usr/include DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/) + + # Convert all CMake compiler options to environment variables + # This is required because the configure script reads from environment + set(CROSS_SYSROOT ${CMAKE_CURRENT_BINARY_DIR}/sysroot/) + set(AS ${CMAKE_ASM_COMPILER}) + set(AR ${CMAKE_AR}) + set(LD ${CMAKE_LINKER}) + set(LDFLAGS ${CMAKE_MODULE_LINKER_FLAGS}) + + # Have to surround variables with double quotes, otherwise they will be merged together without any separator + # Construct compiler commands with all necessary flags and options + set(CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_C_COMPILER_TARGET}") + set(CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_CXX_COMPILER_TARGET}") + + message(STATUS "AS: ${AS}") + message(STATUS "AR: ${AR}") + message(STATUS "LD: ${LD}") + message(STATUS "LDFLAGS: ${LDFLAGS}") + message(STATUS "CC: ${CC}") + message(STATUS "CXX: ${CXX}") + message(STATUS "ANDROID_TOOLCHAIN_ROOT: ${ANDROID_TOOLCHAIN_ROOT}") + + set(COMMAND_AUTOGEN ./autogen.sh) + set(COMMAND_CONFIGURE ./configure --prefix=/usr/local/ ${CONFIGURE_LIBLZMA_PARAMS} ${LIBLZMA_PLATFORM} ${CONFIGURE_LIBLZMA_MODULES}) + set(COMMAND_TEST "true") + else() # detect host system automatically + set(COMMAND_AUTOGEN ./autogen.sh) + set(COMMAND_CONFIGURE ./configure --prefix=/usr/local/ ${CONFIGURE_LIBLZMA_PARAMS} ${CONFIGURE_LIBLZMA_MODULES}) + endif() + + # Add ExternalProject target for building XZ library from source + # This downloads, configures, builds, and installs XZ + ExternalProject_Add(libxzExternal + URL ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz + ${LIBLZMA_CHECK_HASH} + UPDATE_COMMAND "" + # Run autogen.sh to generate configure script + COMMAND ${COMMAND_AUTOGEN} + # Configure the build + CONFIGURE_COMMAND ${BUILD_ENV_TOOL} ${COMMAND_CONFIGURE} + # Build with parallel jobs + BUILD_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} -j ${NUM_JOBS} + BUILD_BYPRODUCTS ${LIBLZMA_PATH} + # Install the built library + INSTALL_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${PERL_PATH_FIX_INSTALL} + COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} DESTDIR=${CMAKE_CURRENT_BINARY_DIR} install + # Force CMake reload to pick up the newly built library + COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} ${CMAKE_BINARY_DIR} + # Copy installed files to parent directory for easier access + COMMAND cp -r ${LIBLZMA_PREFIX}/usr/ ${LIBLZMA_PREFIX}/.. + + # Enable logging for debugging + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 + ) + + # set git config values to liblzma requirements (no impact on linux though) + # ExternalProject_Add_Step(liblzma setGitConfig + # COMMAND ${GIT_EXECUTABLE} config --global core.autocrlf false + # COMMAND ${GIT_EXECUTABLE} config --global core.eol lf + # DEPENDEES + # DEPENDERS download + # ALWAYS ON + # ) + + # Set, don't abort if it fails (due to variables being empty). To realize this we must only call git if the configs + # are set globally, otherwise do a no-op command ("echo 1", since "true" is not available everywhere) + # if (GIT_CORE_AUTOCRLF) + # set (GIT_CORE_AUTOCRLF_CMD ${GIT_EXECUTABLE} config --global core.autocrlf ${GIT_CORE_AUTOCRLF}) + # else() + # set (GIT_CORE_AUTOCRLF_CMD echo) + # endif() + # if (GIT_CORE_EOL) + # set (GIT_CORE_EOL_CMD ${GIT_EXECUTABLE} config --global core.eol ${GIT_CORE_EOL}) + # else() + # set (GIT_CORE_EOL_CMD echo) + # endif() + ## + + # Set git config values to previous values + # ExternalProject_Add_Step(liblzma restoreGitConfig + # # Unset first (is required, since old value could be omitted, which wouldn't take any effect in "set" + # COMMAND ${GIT_EXECUTABLE} config --global --unset core.autocrlf + # COMMAND ${GIT_EXECUTABLE} config --global --unset core.eol + # + # COMMAND ${GIT_CORE_AUTOCRLF_CMD} + # COMMAND ${GIT_CORE_EOL_CMD} + # + # DEPENDEES download + # DEPENDERS configure + # ALWAYS ON + # ) + + # Write environment variables to file for cross-compilation + # This file is read by the Python building_env.py script to set up the build environment + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + if (NOT _variableName MATCHES "lines") + set(OUT_FILE "${OUT_FILE}${_variableName}=\"${${_variableName}}\"\n") + endif() + endforeach() + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/buildenv.txt ${OUT_FILE}) + + # Set the imported library location property + set_target_properties(lib_lzma PROPERTIES IMPORTED_LOCATION ${LIBLZMA_PATH}) +endif() diff --git a/external/libxz-cmake/scripts/building_env.py b/external/libxz-cmake/scripts/building_env.py new file mode 100755 index 0000000000..4f4ca3c8a5 --- /dev/null +++ b/external/libxz-cmake/scripts/building_env.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# building_env.py - Build environment setup script for XZ/LZMA library +# +# Creates a building environment for XZ library: +# - Sets working directory +# - On Windows: uses MSYS bash for command execution (XZ's scripts need an UNIX-like environment) +# - Handles cross-compilation environment setup for Android + +from subprocess import PIPE, Popen +from sys import argv +import os +import re + +env = os.environ +l = [] + +os_s = argv[1] # operating system +offset = 2 # 0: this script's path, 1: operating system + +if os_s == "WIN32": + offset = 4 # 2: MSYS_BASH_PATH, 3: CMAKE_MAKE_PROGRAM + + # + bash = argv[2] + msys_path = os.path.dirname(bash) + mingw_path = os.path.dirname(argv[3]) + + # append ; to PATH if needed + if not env['PATH'].endswith(";"): + env['PATH'] += ";" + + # include path of msys binaries (perl, cd etc.) and building tools (gcc, ld etc.) + env['PATH'] = ";".join([msys_path, mingw_path])+";"+env['PATH'] + env['MAKEFLAGS'] = '' # otherwise: internal error: invalid --jobserver-fds string `gmake_semaphore_1824' + + +binary_berkeleydb_dir_source = argv[offset]+"/" # downloaded berkeleydb source dir +l.extend(argv[offset+1:]) # routed commands + +l[0] = '"'+l[0]+'"' + +# ensure target dir exists for mingw cross +target_dir = binary_berkeleydb_dir_source+"/../../../usr/local/bin" +if not os.path.exists(target_dir): + os.makedirs(target_dir) + +# Read environment from file if cross-compiling for Android +if os_s == "LINUX_CROSS_ANDROID": + expr = re.compile(r'^(.*?)="(.*?)"', re.MULTILINE | re.DOTALL) + env_file_path = os.path.join(binary_berkeleydb_dir_source, "../../../buildenv.txt") + + # Use modern Python file handling with context manager + with open(env_file_path, "r", encoding='utf-8') as f: + content = f.read() + + for k, v in expr.findall(content): + if "\n" in k.strip(): + print('Skipping multiline key') + elif k != "PATH": + env[k] = v.replace('"', '') + else: + # Prepend to PATH to ensure cross-compilation tools are found first + env[k] = v.replace('"', '') + ":" + env[k] + +# Execute the build command in the appropriate environment +proc = None +if os_s == "WIN32": + # We must emulate a UNIX environment to build XZ using MinGW/MSYS + proc = Popen(bash, env=env, cwd=binary_berkeleydb_dir_source, stdin=PIPE, universal_newlines=True) + proc.communicate(input=" ".join(l) + " || exit $?") +else: + # On Unix-like systems, execute directly with shell + proc = Popen(" ".join(l) + " || exit $?", shell=True, env=env, cwd=binary_berkeleydb_dir_source) + proc.communicate() + +# Exit with the return code from the build command +exit(proc.returncode) diff --git a/external/tor-cmake/CMakeLists.txt b/external/tor-cmake/CMakeLists.txt new file mode 100755 index 0000000000..bd47cae249 --- /dev/null +++ b/external/tor-cmake/CMakeLists.txt @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# CMakeLists.txt - Main CMake configuration for Tor library build system +# +# This file sets up the Tor library build configuration, including: +# - Project configuration and minimum CMake version +# - Cache variables for build customization +# - Interface library target for linking +# - External project integration for building Tor from source + +cmake_minimum_required(VERSION 3.2) +project(tor-cmake + VERSION 1.0.0 + DESCRIPTION "CMake build system for Tor library" + LANGUAGES C +) + +# Cache variables for build configuration +set(TOR_ARCHIVE_LOCATION OFF CACHE STRING "Location of Tor archive") +set(TOR_BUILD_VERSION OFF CACHE STRING "Tor version to build") +set(CROSS_ANDROID OFF CACHE BOOL "Cross-compiling for Android?") +set(CROSS OFF CACHE BOOL "Cross-compiling?") +set(CROSS_TARGET OFF CACHE STRING "Cross-compilation target") + +# Allow including our modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") + +# Create interface library target for linking against Tor +# This provides a clean interface for consumers of the library +add_library(libtor INTERFACE) + +# Set up imported static library target +# This will be populated with the actual library location after build +add_library(lib_tor STATIC IMPORTED GLOBAL) + +# Link the imported library to the interface target +target_link_libraries(libtor INTERFACE lib_tor) + +# Set up build prefix and paths +# All build artifacts will be installed under this prefix +set(TOR_LIBTOR_PREFIX ${CMAKE_CURRENT_BINARY_DIR}) +message(STATUS "TOR_LIBTOR_PREFIX: ${TOR_LIBTOR_PREFIX}") + +# Path to the built Tor binary/library +set(TOR_LIBTOR_PATH ${TOR_LIBTOR_PREFIX}/usr/local/bin/tor) +message(STATUS "TOR_LIBTOR_PATH ${TOR_LIBTOR_PATH}") + +# Include the build script that handles the actual Tor build process +include(BuildTor) + +# Set the imported library location property +# This tells CMake where to find the built library +set_target_properties(lib_tor PROPERTIES IMPORTED_LOCATION ${TOR_LIBTOR_PATH}) + +# Set include directories for consumers of the libtor target +target_include_directories(libtor BEFORE INTERFACE ${TOR_LIBTOR_PREFIX}/usr/local/include) + +# Note: Additional include paths can be added here if needed +#set(TOR_INCLUDE_PATH +# ${TOR_LIBTOR_PREFIX}/libtorExternal-prefix/src/libtorExternal/ +# ${TOR_LIBTOR_PREFIX}/libtorExternal-prefix/src/libtorExternal/src/app/main/ +# ${TOR_LIBTOR_PREFIX}/libtorExternal-prefix/src/libtorExternal/src/feature/api/ +# PARENT_SCOPE +# ) + +# Ensure the external project is built before the imported target is used +add_dependencies(lib_tor libtorExternal) diff --git a/external/tor-cmake/cmake/BuildTor.cmake b/external/tor-cmake/cmake/BuildTor.cmake new file mode 100755 index 0000000000..54949d940f --- /dev/null +++ b/external/tor-cmake/cmake/BuildTor.cmake @@ -0,0 +1,311 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# BuildTor.cmake - CMake module for building Tor from source +# +# This module handles the complete build process for Tor, including: +# - Platform detection (Windows, Unix, Android cross-compilation) +# - Build tool detection (make, MSYS bash for Windows) +# - Configuration of build parameters for different platforms +# - External project setup for downloading and building Tor +# - Environment setup for cross-compilation scenarios + +include(ProcessorCount) +include(ExternalProject) + +# Find required dependencies +find_package(Git REQUIRED) +# Use modern Python3 find module (PythonInterp is deprecated) +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Find patch utility (required for applying patches) +find_program(PATCH_PROGRAM patch) +if (NOT PATCH_PROGRAM) + message(FATAL_ERROR "Cannot find patch utility. This is only required for Android cross-compilation but due to script complexity " + "the requirement is always enforced") +endif() + +# Determine number of parallel jobs for building +ProcessorCount(NUM_JOBS) +if (NUM_JOBS EQUAL 0) + set(NUM_JOBS 1) +endif() + +# Default to Unix-like OS, will be overridden for Windows/Android +set(OS "UNIX") + +# Set up archive hash verification if provided +if (TOR_ARCHIVE_HASH) + set(TOR_CHECK_HASH URL_HASH SHA256=${TOR_ARCHIVE_HASH}) +endif() + +# Skip build if library already exists +if (EXISTS ${TOR_LIBTOR_PATH}) + message(STATUS "Not building Tor again. Remove ${TOR_LIBTOR_PATH} for rebuild") +else() + # Platform-specific build tool detection + if (WIN32 AND NOT CROSS) + # Windows needs special treatment, but neither cygwin nor msys, since they provide an UNIX-like environment + if (MINGW) + set(OS "WIN32") + message(WARNING "Building on windows is experimental") + + # Find MSYS bash for executing Unix-like commands + find_program(MSYS_BASH "bash.exe" + PATHS "C:/Msys/" "C:/MinGW/msys/" + PATH_SUFFIXES "/1.0/bin/" "/bin/" + DOC "Path to MSYS installation" + ) + if (NOT MSYS_BASH) + message(FATAL_ERROR "Specify MSYS installation path") + endif() + + set(MINGW_MAKE ${CMAKE_MAKE_PROGRAM}) + message(WARNING "Assuming your make program is a sibling of your compiler (resides in same directory)") + elseif(NOT (CYGWIN OR MSYS)) + message(FATAL_ERROR "Unsupported compiler infrastructure") + endif() + + set(MAKE_PROGRAM ${CMAKE_MAKE_PROGRAM}) + elseif(NOT UNIX) + message(FATAL_ERROR "Unsupported platform") + else() + # On Unix-like systems, we can only use GNU make, no exotic things like Ninja + # (MSYS always uses GNU make) + find_program(MAKE_PROGRAM make) + if (NOT MAKE_PROGRAM) + message(FATAL_ERROR "Could not find 'make' program") + endif() + endif() + + # save old git values for core.autocrlf and core.eol + #execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.autocrlf OUTPUT_VARIABLE GIT_CORE_AUTOCRLF OUTPUT_STRIP_TRAILING_WHITESPACE) + #execute_process(COMMAND ${GIT_EXECUTABLE} config --global --get core.eol OUTPUT_VARIABLE GIT_CORE_EOL OUTPUT_STRIP_TRAILING_WHITESPACE) + + # On windows we need to replace path to perl since CreateProcess(..) cannot handle unix paths + if (WIN32 AND NOT CROSS) + set(PERL_PATH_FIX_INSTALL sed -i -- 's/\\/usr\\/bin\\/perl/perl/g' Makefile) + else() + set(PERL_PATH_FIX_INSTALL true) + endif() + + # CROSS and CROSS_ANDROID cannot both be set (because of internal reasons) + if (CROSS AND CROSS_ANDROID) + # if user set CROSS_ANDROID and CROSS we assume he wants CROSS_ANDROID, so set CROSS to OFF + set(CROSS OFF) + endif() + + if (CROSS_ANDROID) + set(OS "LINUX_CROSS_ANDROID") + endif() + + # Python helper script for correct building environment + # This script sets up the proper environment for building on different platforms + set(BUILD_ENV_TOOL ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/building_env.py ${OS} ${MSYS_BASH} ${MINGW_MAKE}) + + # Copy headers to library install location during build, so Tor could find them +# file(COPY ${libevent_SOURCE_DIR}/include DESTINATION ${TOR_LIBTOR_PREFIX}/../libevent/) +# file(COPY ${libzstd_SOURCE_DIR}/../../../lib/zstd.h DESTINATION ${TOR_LIBTOR_PREFIX}/../libzstd/build/cmake/include/) + + # Configure build commands based on compilation target + if (CROSS) + # Standard cross-compilation configuration + set(COMMAND_CONFIGURE ./configure ${CONFIGURE_TOR_PARAMS} --cross-compile-prefix=${CROSS_PREFIX} ${CROSS_TARGET} --prefix=/usr/local/) + set(COMMAND_TEST "true") + elseif(CROSS_ANDROID) + + # Initialize compiler flags from CMake settings + set(CFLAGS ${CMAKE_C_FLAGS}) + set(CXXFLAGS ${CMAKE_CXX_FLAGS}) + + # Silence warnings about unused arguments (Clang specific) + # Use gold linker for better Android compatibility + set(CFLAGS "${CMAKE_C_FLAGS} -Qunused-arguments -fuse-ld=gold") + set(CXXFLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fuse-ld=gold") + + # Required environment configuration is already set (by e.g. ndk) so no need to fiddle around with all the options ... + if (NOT ANDROID) + message(FATAL_ERROR "Use NDK cmake toolchain or cmake android autoconfig") + endif() + + # Additional configure script parameters for Android build + # These configure Tor with Android-specific options and dependencies + set(CONFIGURE_TOR_PARAMS + ZSTD_CFLAGS='-I${TOR_LIBTOR_PREFIX}/../libzstd/build/cmake/include' + ZSTD_LIBS='-L${TOR_LIBTOR_PREFIX}/../libzstd/build/cmake/lib -lzstd' + LZMA_CFLAGS='-I${TOR_LIBTOR_PREFIX}/../usr/local/include' + LZMA_LIBS='-L${TOR_LIBTOR_PREFIX}/../usr/local/lib -llzma' + --enable-android + --enable-lzma + --enable-pic + --enable-restart-debugging + --with-libevent-dir=${TOR_LIBTOR_PREFIX}/../usr/local + --with-openssl-dir=${TOR_LIBTOR_PREFIX}/../usr/local + --with-zlib-dir=${TOR_LIBTOR_PREFIX}/sysroot/usr + --enable-zstd + --enable-static-tor + --disable-module-dirauth + --disable-tool-name-check + --disable-asciidoc + ) + + if (ARMEABI_V7A) + set(TOR_PLATFORM "--host armv7") + #set(CONFIGURE_TOR_PARAMS ${CONFIGURE_TOR_PARAMS} "-march=armv7-a") + else() + if (CMAKE_ANDROID_ARCH_ABI MATCHES "arm64-v8a") + set(TOR_PLATFORM "--host=aarch64-linux-android") + else() + set(TOR_PLATFORM "--host=${CMAKE_ANDROID_ARCH_ABI}") + endif() + endif() + + set(ANDROID_STRING "android") + if (CMAKE_ANDROID_ARCH_ABI MATCHES "64") + set(ANDROID_STRING "${ANDROID_STRING}64") + endif() + + # copy over both sysroots to a common sysroot (workaround OpenSSL failing without one single sysroot) + string(REPLACE "-clang" "" ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME}) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/${ANDROID_PLATFORM_LEVEL}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/) + file(COPY ${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ANDROID_TOOLCHAIN_NAME}/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/lib/ PATTERN *.*) + file(COPY ${CMAKE_SYSROOT}/usr/include DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/sysroot/usr/) + + # Convert all CMake compiler options to environment variables + # This is required because the configure script reads from environment + set(CROSS_SYSROOT ${CMAKE_CURRENT_BINARY_DIR}/sysroot/) + set(AS ${CMAKE_ASM_COMPILER}) + set(AR ${CMAKE_AR}) + set(LD ${CMAKE_LINKER}) + set(LDFLAGS ${CMAKE_MODULE_LINKER_FLAGS}) + + # Have to surround variables with double quotes, otherwise they will be merged together without any separator + # Construct compiler commands with all necessary flags and options + set(CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_C_COMPILER_TARGET}") + set(CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN}${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN} ${CFLAGS} -target ${CMAKE_CXX_COMPILER_TARGET}") + + message(STATUS "AS: ${AS}") + message(STATUS "AR: ${AR}") + message(STATUS "LD: ${LD}") + message(STATUS "LDFLAGS: ${LDFLAGS}") + message(STATUS "CC: ${CC}") + message(STATUS "CXX: ${CXX}") + message(STATUS "ANDROID_TOOLCHAIN_ROOT: ${ANDROID_TOOLCHAIN_ROOT}") + + set(COMMAND_AUTOGEN ./autogen.sh) + set(COMMAND_CONFIGURE ./configure --prefix=/usr/local/ ${CONFIGURE_TOR_PARAMS} ${TOR_PLATFORM}) + set(COMMAND_TEST "true") + else() # detect host system automatically + + # Additional configure script parameters for native Unix build + # Note: ZSTD and LZMA options are commented out but can be enabled if needed + # ZSTD_CFLAGS='-I${TOR_LIBTOR_PREFIX}/../libzstd/build/cmake/include' + # ZSTD_LIBS='-L${TOR_LIBTOR_PREFIX}/../libzstd/build/cmake/lib -lzstd' + # LZMA_CFLAGS='-I${TOR_LIBTOR_PREFIX}/../usr/local/include' + # LZMA_LIBS='-L${TOR_LIBTOR_PREFIX}/../usr/local/lib -llzma' + set(CONFIGURE_TOR_PARAMS + CFLAGS='-fuse-ld=gold' + --enable-lzma + --enable-pic + --enable-restart-debugging + --with-libevent-dir=${TOR_LIBTOR_PREFIX}/../usr/local + --with-openssl-dir=${TOR_LIBTOR_PREFIX}/../usr/local + --with-zlib-dir=/usr/lib/x86_64-linux-gnu + --enable-zstd + --enable-static-tor + --disable-module-dirauth + --disable-tool-name-check + --disable-asciidoc + ) + + set(COMMAND_AUTOGEN ./autogen.sh) + set(COMMAND_CONFIGURE ./configure --prefix=/usr/local/ ${CONFIGURE_TOR_PARAMS} && "echo '#define HAVE_ZSTD_ESTIMATECSTREAMSIZE 1' >> ${TOR_LIBTOR_PREFIX}/libtorExternal-prefix/src/libtorExternal/orconfig.h") + endif() + + # Add ExternalProject target for building Tor from source + # This downloads, patches, configures, builds, and installs Tor + ExternalProject_Add(libtorExternal + URL ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz + ${TOR_CHECK_HASH} + UPDATE_COMMAND "" + # Run autogen.sh to generate configure script + COMMAND ${COMMAND_AUTOGEN} + # Note: Dependencies can be added here if needed + # DEPENDS ssl_lib zstd event + + # Apply patches for Android compatibility and OpenSSL fixes + PATCH_COMMAND ${PATCH_PROGRAM} -p1 --forward -r - < ${CMAKE_CURRENT_SOURCE_DIR}/patches/Tor-001-disable-deprecated-android-log.patch || true + COMMAND ${PATCH_PROGRAM} -p1 --forward -r - < ${CMAKE_CURRENT_SOURCE_DIR}/patches/Tor-002-fix-openssl-checks.patch || true + + # Configure the build + CONFIGURE_COMMAND ${BUILD_ENV_TOOL} ${COMMAND_CONFIGURE} + # Build with parallel jobs + BUILD_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} -j ${NUM_JOBS} + BUILD_BYPRODUCTS ${TOR_LIBTOR_PATH} + # Install the built library + INSTALL_COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${PERL_PATH_FIX_INSTALL} + COMMAND ${BUILD_ENV_TOOL} /${CONFIGURE_DIR} ${MAKE_PROGRAM} DESTDIR=${TOR_LIBTOR_PREFIX}/.. install + # Force CMake reload to pick up the newly built library + COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} ${CMAKE_BINARY_DIR} + + # Enable logging for debugging + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 + ) +# ExternalProject_Add_StepDependencies(libtorExternal install openssl libeventExternal libzExternal) + + # set git config values to libtor requirements (no impact on linux though) + # ExternalProject_Add_Step(libtor setGitConfig + # COMMAND ${GIT_EXECUTABLE} config --global core.autocrlf false + # COMMAND ${GIT_EXECUTABLE} config --global core.eol lf + # DEPENDEES + # DEPENDERS download + # ALWAYS ON + # ) + + # Set, don't abort if it fails (due to variables being empty). To realize this we must only call git if the configs + # are set globally, otherwise do a no-op command ("echo 1", since "true" is not available everywhere) + # if (GIT_CORE_AUTOCRLF) + # set (GIT_CORE_AUTOCRLF_CMD ${GIT_EXECUTABLE} config --global core.autocrlf ${GIT_CORE_AUTOCRLF}) + # else() + # set (GIT_CORE_AUTOCRLF_CMD echo) + # endif() + # if (GIT_CORE_EOL) + # set (GIT_CORE_EOL_CMD ${GIT_EXECUTABLE} config --global core.eol ${GIT_CORE_EOL}) + # else() + # set (GIT_CORE_EOL_CMD echo) + # endif() + ## + + # Set git config values to previous values + # ExternalProject_Add_Step(libtor restoreGitConfig + # # Unset first (is required, since old value could be omitted, which wouldn't take any effect in "set" + # COMMAND ${GIT_EXECUTABLE} config --global --unset core.autocrlf + # COMMAND ${GIT_EXECUTABLE} config --global --unset core.eol + # + # COMMAND ${GIT_CORE_AUTOCRLF_CMD} + # COMMAND ${GIT_CORE_EOL_CMD} + # + # DEPENDEES download + # DEPENDERS configure + # ALWAYS ON + # ) + + # Write environment variables to file for cross-compilation + # This file is read by the Python building_env.py script to set up the build environment + get_cmake_property(_variableNames VARIABLES) + foreach (_variableName ${_variableNames}) + if (NOT _variableName MATCHES "lines") + set(OUT_FILE "${OUT_FILE}${_variableName}=\"${${_variableName}}\"\n") + endif() + endforeach() + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/buildenv.txt ${OUT_FILE}) + + # Set the imported library location property + set_target_properties(lib_tor PROPERTIES IMPORTED_LOCATION ${TOR_LIBTOR_PATH}) +endif() diff --git a/external/tor-cmake/patches/Tor-001-disable-deprecated-android-log.patch b/external/tor-cmake/patches/Tor-001-disable-deprecated-android-log.patch new file mode 100644 index 0000000000..c1f310e953 --- /dev/null +++ b/external/tor-cmake/patches/Tor-001-disable-deprecated-android-log.patch @@ -0,0 +1,14 @@ +diff --git a/configure.ac b/configure.ac +--- a/configure.ac ++++ b/configure.ac +@@ -243,8 +243,8 @@ + AC_DEFINE([USE_ANDROID], [1], [Compile with Android specific features enabled]) + + dnl Check if the Android log library is available. +- AC_CHECK_HEADERS([android/log.h]) +- AC_SEARCH_LIBS(__android_log_write, [log]) ++ #AC_CHECK_HEADERS([android/log.h]) ++ #AC_SEARCH_LIBS(__android_log_write, [log]) + + fi + diff --git a/external/tor-cmake/patches/Tor-002-fix-openssl-checks.patch b/external/tor-cmake/patches/Tor-002-fix-openssl-checks.patch new file mode 100644 index 0000000000..9968cf08e9 --- /dev/null +++ b/external/tor-cmake/patches/Tor-002-fix-openssl-checks.patch @@ -0,0 +1,12 @@ +diff --git a/tor/configure.ac b/tor/configure.ac +--- a/configure.ac ++++ b/configure.ac +@@ -919,7 +919,7 @@ + dnl We look for SSL_cipher_get_id() because it is present in + dnl OpenSSL >=1.0.1, because it is not deprecated, and because Tor + dnl depends on it. +- [if (getenv("THIS_SHOULDNT_BE_SET_X201803")) SSL_CIPHER_get_id((void *)0);], [], ++ [;], [], + [/usr/local/opt/openssl /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /opt/openssl]) + + dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay() diff --git a/external/tor-cmake/scripts/building_env.py b/external/tor-cmake/scripts/building_env.py new file mode 100755 index 0000000000..8750cbcbb5 --- /dev/null +++ b/external/tor-cmake/scripts/building_env.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Inspired by The ViaDuck Project for building OpenSSL +# +# building_env.py - Build environment setup script for Tor +# +# Creates a building environment for Tor: +# - Sets working directory +# - On Windows: uses MSYS bash for command execution (Tor's scripts need an UNIX-like environment) +# - Handles cross-compilation environment setup for Android + +from subprocess import PIPE, Popen +from sys import argv +import os +import re + +env = os.environ +l = [] + +os_s = argv[1] # operating system +offset = 2 # 0: this script's path, 1: operating system + +if os_s == "WIN32": + offset = 4 # 2: MSYS_BASH_PATH, 3: CMAKE_MAKE_PROGRAM + + # + bash = argv[2] + msys_path = os.path.dirname(bash) + mingw_path = os.path.dirname(argv[3]) + + # append ; to PATH if needed + if not env['PATH'].endswith(";"): + env['PATH'] += ";" + + # include path of msys binaries (perl, cd etc.) and building tools (gcc, ld etc.) + env['PATH'] = ";".join([msys_path, mingw_path])+";"+env['PATH'] + env['MAKEFLAGS'] = '' # otherwise: internal error: invalid --jobserver-fds string `gmake_semaphore_1824' + + +binary_berkeleydb_dir_source = argv[offset]+"/" # downloaded berkeleydb source dir +l.extend(argv[offset+1:]) # routed commands + +l[0] = '"'+l[0]+'"' + +# ensure target dir exists for mingw cross +target_dir = binary_berkeleydb_dir_source+"/../../../usr/local/bin" +if not os.path.exists(target_dir): + os.makedirs(target_dir) + +# Read environment from file if cross-compiling for Android +if os_s == "LINUX_CROSS_ANDROID": + expr = re.compile(r'^(.*?)="(.*?)"', re.MULTILINE | re.DOTALL) + env_file_path = os.path.join(binary_berkeleydb_dir_source, "../../../buildenv.txt") + + # Use modern Python file handling with context manager + with open(env_file_path, "r", encoding='utf-8') as f: + content = f.read() + + for k, v in expr.findall(content): + if "\n" in k.strip(): + print('Skipping multiline key') + elif k != "PATH": + env[k] = v.replace('"', '') + else: + # Prepend to PATH to ensure cross-compilation tools are found first + env[k] = v.replace('"', '') + ":" + env[k] + +# Execute the build command in the appropriate environment +proc = None +if os_s == "WIN32": + # We must emulate a UNIX environment to build Tor using MinGW/MSYS + proc = Popen(bash, env=env, cwd=binary_berkeleydb_dir_source, stdin=PIPE, universal_newlines=True) + proc.communicate(input=" ".join(l) + " || exit $?") +else: + # On Unix-like systems, execute directly with shell + proc = Popen(" ".join(l) + " || exit $?", shell=True, env=env, cwd=binary_berkeleydb_dir_source) + proc.communicate() + +# Exit with the return code from the build command +exit(proc.returncode) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000000..5032bba809 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,982 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AX_REQUIRE_DEFINED([AC_MSG_WARN]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) + m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])]) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus <= 201402L + +#error "This is not a C++17 compiler" + +#else + +#if defined(__clang__) + #define REALLY_CLANG +#else + #if defined(__GNUC__) + #define REALLY_GCC + #endif +#endif + +#include +#include +#include + +namespace cxx17 +{ + +#if !defined(REALLY_CLANG) + namespace test_constexpr_lambdas + { + + // TODO: test it with clang++ from git + + constexpr int foo = [](){return 42;}(); + + } +#endif // !defined(REALLY_CLANG) + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + +#if !defined(REALLY_CLANG) + namespace test_template_argument_deduction_for_class_templates + { + + // TODO: test it with clang++ from git + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } +#endif // !defined(REALLY_CLANG) + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + +#if !defined(REALLY_CLANG) + namespace test_structured_bindings + { + + // TODO: test it with clang++ from git + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } +#endif // !defined(REALLY_CLANG) + +#if !defined(REALLY_CLANG) + namespace test_exception_spec_type_system + { + + // TODO: test it with clang++ from git + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } +#endif // !defined(REALLY_CLANG) + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus <= 201402L + +]]) diff --git a/m4/ax_subdirs_configure.m4 b/m4/ax_subdirs_configure.m4 new file mode 100644 index 0000000000..55e16c6b8f --- /dev/null +++ b/m4/ax_subdirs_configure.m4 @@ -0,0 +1,337 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_subdirs_configure.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_SUBDIRS_CONFIGURE( [subdirs], [mandatory arguments], [possibly merged arguments], [replacement arguments], [forbidden arguments]) +# +# DESCRIPTION +# +# AX_SUBDIRS_CONFIGURE attempts to be the equivalent of AC_CONFIG_SUBDIRS +# with customizable options for configure scripts. +# +# Run the configure script for each directory from the comma-separated m4 +# list 'subdirs'. This macro can be used multiple times. All arguments of +# this macro must be comma-separated lists. +# +# All command line arguments from the parent configure script will be +# given to the subdirectory configure script after the following +# modifications (in that order): +# +# 1. The arguments from the 'mandatory arguments' list shall always be +# appended to the argument list. +# +# 2. The arguments from the 'possibly merged arguments' list shall be +# added if not present in the arguments of the parent configure script or +# merged with the existing argument otherwise. +# +# 3. The arguments from the 'replacement arguments' list shall be added if +# not present in the arguments of the parent configure script or replace +# the existing argument otherwise. +# +# 4. The arguments from the 'forbidden arguments' list shall always be +# removed from the argument list. +# +# The lists 'mandatory arguments' and 'forbidden arguments' can hold any +# kind of argument. The 'possibly merged arguments' and 'replacement +# arguments' expect their arguments to be of the form --option-name=value. +# +# This macro aims to remain as close as possible to the AC_CONFIG_SUBDIRS +# macro. It corrects the paths for '--cache-file' and '--srcdir' and adds +# '--disable-option-checking' and '--silent' if necessary. +# +# This macro also sets the output variable subdirs_extra to the list of +# directories recorded with AX_SUBDIRS_CONFIGURE. This variable can be +# used in Makefile rules or substituted in configured files. +# +# This macro shall do nothing more than managing the arguments of the +# configure script. Just like when using AC_CONFIG_SUBDIRS, it is up to +# the user to check any requirements or define and substitute any required +# variable for the remainder of the project. +# +# Configure scripts recorded with AX_SUBDIRS_CONFIGURE may be executed +# before configure scripts recorded with AC_CONFIG_SUBDIRS. +# +# Without additional arguments, the behaviour of AX_SUBDIRS_CONFIGURE +# should be identical to the behaviour of AC_CONFIG_SUBDIRS, apart from +# the contents of the variables subdirs and subdirs_extra (except that +# AX_SUBDIRS_CONFIGURE expects a comma-separated m4 list): +# +# AC_CONFIG_SUBDIRS([something]) +# AX_SUBDIRS_CONFIGURE([something]) +# +# This macro may be called multiple times. +# +# Usage example: +# +# Let us assume our project has 4 dependencies, namely A, B, C and D. Here +# are some characteristics of our project and its dependencies: +# +# - A does not require any special option. +# +# - we want to build B with an optional feature which can be enabled with +# its configure script's option '--enable-special-feature'. +# +# - B's configure script is strange and has an option '--with-B=build'. +# After close inspection of its documentation, we don't want B to receive +# this option. +# +# - C and D both need B. +# +# - Just like our project, C and D can build B themselves with the option +# '--with-B=build'. +# +# - We want C and D to use the B we build instead of building it +# themselves. +# +# Our top-level configure script will be called as follows: +# +# $ --with-A=build --with-B=build --with-C=build \ +# --with-D=build --some-option +# +# Thus we have to make sure that: +# +# - neither B, C or D receive the option '--with-B=build' +# +# - C and D know where to find the headers and libraries of B. +# +# Under those conditions, we can use the AC_CONFIG_SUBDIRS macro for A, +# but need to use AX_SUBDIRS_CONFIGURE for B, C and D: +# +# - B must receive '--enable-special-feature' but cannot receive +# '--with-B=build' +# +# - C and D cannot receive '--with-B=build' (or else it would be built +# thrice) and need to be told where to find B (since we are building it, +# it would probably not be available in standard paths). +# +# Here is a configure.ac snippet that solves our problem: +# +# AC_CONFIG_SUBDIRS([dependencies/A]) +# AX_SUBDIRS_CONFIGURE( +# [dependencies/B], [--enable-special-feature], [], [], +# [--with-B=build]) +# AX_SUBDIRS_CONFIGURE( +# [[dependencies/C],[dependencies/D]], +# [], +# [[CPPFLAGS=-I${ac_top_srcdir}/dependencies/B -I${ac_top_builddir}/dependencies/B], +# [LDFLAGS=-L${ac_abs_top_builddir}/dependencies/B/.libs]], +# [--with-B=system], +# []) +# +# If using automake, the following can be added to the Makefile.am (we use +# both $(subdirs) and $(subdirs_extra) since our example above used both +# AC_CONFIG_SUBDIRS and AX_SUBDIRS_CONFIGURE): +# +# SUBDIRS = $(subdirs) $(subdirs_extra) +# +# LICENSE +# +# Copyright (c) 2017 Harenome Ranaivoarivony-Razanajato +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# Under Section 7 of GPL version 3, you are granted additional permissions +# described in the Autoconf Configure Script Exception, version 3.0, as +# published by the Free Software Foundation. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . + +#serial 3 + +AC_DEFUN([AX_SUBDIRS_CONFIGURE], +[ + dnl Calls to AC_CONFIG_SUBDIRS perform preliminary steps and build a list + dnl '$subdirs' which is used later by _AC_OUTPUT_SUBDIRS (used by AC_OUTPUT) + dnl to actually run the configure scripts. + dnl This macro performs similiar preliminary steps but uses + dnl AC_CONFIG_COMMANDS_PRE to delay the final tasks instead of building an + dnl intermediary list and relying on another macro. + dnl + dnl Since each configure script can get different options, a special variable + dnl named 'ax_sub_configure_args_' is constructed for each + dnl subdirectory. + + # Various preliminary checks. + AC_REQUIRE([AC_DISABLE_OPTION_CHECKING]) + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) + AS_LITERAL_IF([$1], [], + [AC_DIAGNOSE([syntax], [$0: you should use literals])]) + + m4_foreach(subdir_path, [$1], + [ + ax_dir="subdir_path" + + dnl Build the argument list in a similiar fashion to AC_CONFIG_SUBDIRS. + dnl A few arguments found in the final call to the configure script are not + dnl added here because they rely on variables that may not yet be available + dnl (see below the part that is similiar to _AC_OUTPUT_SUBDIRS). + # Do not complain, so a configure script can configure whichever parts of a + # large source tree are present. + if test -d "$srcdir/$ax_dir"; then + _AC_SRCDIRS(["$ax_dir"]) + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ax_args= + ax_prev= + eval "set x $ac_configure_args" + shift + for ax_arg; do + if test -n "$ax_prev"; then + ax_prev= + continue + fi + case $ax_arg in + -cache-file | --cache-file | --cache-fil | --cache-fi | --cache-f \ + | --cache- | --cache | --cach | --cac | --ca | --c) + ax_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ + | --c=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ax_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ax_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* \ + | --p=*) + ;; + --disable-option-checking) + ;; + *) case $ax_arg in + *\'*) ax_arg=$(AS_ECHO(["$ax_arg"]) | sed "s/'/'\\\\\\\\''/g");; + esac + AS_VAR_APPEND([ax_args], [" '$ax_arg'"]) ;; + esac + done + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ax_args="--disable-option-checking $ax_args" + # Options that must be added as they are provided. + m4_ifnblank([$2], [m4_foreach(opt, [$2], [AS_VAR_APPEND(ax_args, " 'opt'") + ])]) + # New options that may need to be merged with existing options. + m4_ifnblank([$3], [m4_foreach(opt, [$3], + [ax_candidate="opt" + ax_candidate_flag="${ax_candidate%%=*}" + ax_candidate_content="${ax_candidate#*=}" + if test "x$ax_candidate" != "x" -a "x$ax_candidate_flag" != "x"; then + if echo "$ax_args" | grep -- "${ax_candidate_flag}=" >/dev/null 2>&1; then + [ax_args=$(echo $ax_args | sed "s,\(${ax_candidate_flag}=[^']*\),\1 ${ax_candidate_content},")] + else + AS_VAR_APPEND(ax_args, " 'opt'") + fi + fi + ])]) + # New options that must replace existing options. + m4_ifnblank([$4], [m4_foreach(opt, [$4], + [ax_candidate="opt" + ax_candidate_flag="${ax_candidate%%=*}" + ax_candidate_content="${ax_candidate#*=}" + if test "x$ax_candidate" != "x" -a "x$ax_candidate_flag" != "x"; then + if echo "$ax_args" | grep -- "${ax_candidate_flag}=" >/dev/null 2>&1; then + [ax_args=$(echo $ax_args | sed "s,${ax_candidate_flag}=[^']*,${ax_candidate},")] + else + AS_VAR_APPEND(ax_args, " 'opt'") + fi + fi + ])]) + # Options that must be removed. + m4_ifnblank([$5], [m4_foreach(opt, [$5], [ax_args=$(echo $ax_args | sed "s,'opt',,") + ])]) + AS_VAR_APPEND([ax_args], [" '--srcdir=$ac_srcdir'"]) + + # Add the subdirectory to the list of target subdirectories. + ax_subconfigures="$ax_subconfigures $ax_dir" + # Save the argument list for this subdirectory. + dnl $1 is a path to some subdirectory: m4_bpatsubsts() is used to convert + dnl $1 into a valid shell variable name. + dnl For instance, "ax_sub_configure_args_path/to/subdir" becomes + dnl "ax_sub_configure_args_path_to_subdir". + ax_var=$(printf "$ax_dir" | tr -c "0-9a-zA-Z_" "_") + eval "ax_sub_configure_args_$ax_var=\"$ax_args\"" + eval "ax_sub_configure_$ax_var=\"yes\"" + else + AC_MSG_WARN([could not find source tree for $ax_dir]) + fi + + dnl Add some more arguments to the argument list and then actually run the + dnl configure script. This is mostly what happens in _AC_OUTPUT_SUBDIRS + dnl except it does not iterate over an intermediary list. + AC_CONFIG_COMMANDS_PRE( + dnl This very line can not be quoted! m4_foreach has some work here. + ax_dir="subdir_path" + [ + # Convert the path to the subdirectory into a shell variable name. + ax_var=$(printf "$ax_dir" | tr -c "0-9a-zA-Z_" "_") + ax_configure_ax_var=$(eval "echo \"\$ax_sub_configure_$ax_var\"") + if test "$no_recursion" != "yes" -a "x$ax_configure_ax_var" = "xyes"; then + AC_SUBST([subdirs_extra], ["$subdirs_extra $ax_dir"]) + ax_msg="=== configuring in $ax_dir ($(pwd)/$ax_dir)" + _AS_ECHO_LOG([$ax_msg]) + _AS_ECHO([$ax_msg]) + AS_MKDIR_P(["$ax_dir"]) + _AC_SRCDIRS(["$ax_dir"]) + + ax_popdir=$(pwd) + cd "$ax_dir" + + # Check for guested configure; otherwise get Cygnus style configure. + if test -f "$ac_srcdir/configure.gnu"; then + ax_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ax_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ax_sub_configure=$ac_aux_dir/configure + else + AC_MSG_WARN([no configuration information is in $ax_dir]) + ax_sub_configure= + fi + + if test -n "$ax_sub_configure"; then + # Get the configure arguments for the current configure. + eval "ax_sub_configure_args=\"\$ax_sub_configure_args_${ax_var}\"" + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ax_arg="--prefix=$prefix" + case $ax_arg in + *\'*) ax_arg=$(AS_ECHO(["$ax_arg"]) | sed "s/'/'\\\\\\\\''/g");; + esac + ax_sub_configure_args="'$ax_arg' $ax_sub_configure_args" + if test "$silent" = yes; then + ax_sub_configure_args="--silent $ax_sub_configure_args" + fi + # Make the cache file name correct relative to the subdirectory. + case $cache_file in + [[\\/]]* | ?:[[\\/]]* ) + ax_sub_cache_file=$cache_file ;; + *) # Relative name. + ax_sub_cache_file=$ac_top_build_prefix$cache_file ;; + esac + + AC_MSG_NOTICE([running $SHELL $ax_sub_configure $ax_sub_configure_args --cache-file=$ac_sub_cache_file]) + eval "\$SHELL \"$ax_sub_configure\" $ax_sub_configure_args --cache-file=\"$ax_sub_cache_file\"" \ + || AC_MSG_ERROR([$ax_sub_configure failed for $ax_dir]) + fi + + cd "$ax_popdir" + fi + ]) + ]) +]) diff --git a/m4/boost.m4 b/m4/boost.m4 new file mode 100644 index 0000000000..dae504502d --- /dev/null +++ b/m4/boost.m4 @@ -0,0 +1,1574 @@ +# boost.m4: Locate Boost headers and libraries for autoconf-based projects. +# Copyright (C) 2007-2011, 2014 Benoit Sigoure +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Additional permission under section 7 of the GNU General Public +# License, version 3 ("GPLv3"): +# +# If you convey this file as part of a work that contains a +# configuration script generated by Autoconf, you may do so under +# terms of your choice. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +m4_define([_BOOST_SERIAL], [m4_translit([ +# serial 26 +], [# +], [])]) + +# Original sources can be found at http://github.com/tsuna/boost.m4 +# You can fetch the latest version of the script by doing: +# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 + +# ------ # +# README # +# ------ # + +# This file provides several macros to use the various Boost libraries. +# The first macro is BOOST_REQUIRE. It will simply check if it's possible to +# find the Boost headers of a given (optional) minimum version and it will +# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to +# your configure so that users can specify non standard locations. +# If the user's environment contains BOOST_ROOT and --with-boost was not +# specified, --with-boost=$BOOST_ROOT is implicitly used. +# For more README and documentation, go to http://github.com/tsuna/boost.m4 +# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, +# simply read the README, it will show you what to do step by step. + +m4_pattern_forbid([^_?(BOOST|Boost)_]) + + +# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------- +# Same as AC_EGREP_CPP, but leave the result in conftest.i. +# +# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded +# in double-quotes, so escape your double quotes. +# +# It could be useful to turn this into a macro which extracts the +# value of any macro. +m4_define([_BOOST_SED_CPP], +[AC_LANG_PUSH([C++])dnl +AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_SED])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) +AS_IF([dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +dnl Beware of Windows end-of-lines, for instance if we are running +dnl some Windows programs under Wine. In that case, boost/version.hpp +dnl is certainly using "\r\n", but the regular Unix shell will only +dnl strip `\n' with backquotes, not the `\r'. This results in +dnl boost_cv_lib_version='1_37\r' for instance, which breaks +dnl everything else. +dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK +dnl +dnl Beware that GCC 5, when expanding macros, may embed # line directives +dnl a within single line: +dnl +dnl # 1 "conftest.cc" +dnl # 1 "" +dnl # 1 "" +dnl # 1 "conftest.cc" +dnl # 1 "/opt/local/include/boost/version.hpp" 1 3 +dnl # 2 "conftest.cc" 2 +dnl boost-lib-version = +dnl # 2 "conftest.cc" 3 +dnl "1_56" +dnl +dnl So get rid of the # and empty lines, and glue the remaining ones together. +(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + grep -v '#' | + grep -v '^[[[:space:]]]*$' | + tr -d '\r' | + tr -s '\n' ' ' | + $SED -n -e "$1" >conftest.i 2>&1], + [$3], + [$4]) +rm -rf conftest* +AC_LANG_POP([C++])dnl +])# _BOOST_SED_CPP + + + +# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------- +# Look for Boost. If version is given, it must either be a literal of the form +# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a +# variable "$var". +# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with +# the required version, it does not check for any of the Boost libraries. +# On # success, defines HAVE_BOOST. On failure, calls the optional +# ACTION-IF-NOT-FOUND action if one was supplied. +# Otherwise aborts with an error message. +AC_DEFUN_ONCE([BOOST_REQUIRE], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_GREP])dnl +echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD +boost_save_IFS=$IFS +boost_version_req=$1 +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` +boost_version_req_string=$[1].$[2].$[3] +AC_ARG_WITH([boost], + [AS_HELP_STRING([--with-boost=DIR], + [prefix of Boost $1 @<:@guess@:>@])])dnl +AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) + with_boost=$BOOST_ROOT + else + AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) + fi +fi +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], + ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl +boost_save_CPPFLAGS=$CPPFLAGS + AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], + [boost_cv_inc_path], + [boost_cv_inc_path=no +AC_LANG_PUSH([C++])dnl +m4_pattern_allow([^BOOST_VERSION$])dnl + AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif +]])]) + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # + # Any ${boost_dir}/boost-x_xx directories are searched in reverse version + # order followed by ${boost_dir}. The final '.' is a sentinel for + # searching $boost_dir" itself. Entries are whitespace separated. + # + # I didn't indent this loop on purpose (to avoid over-indented code) + boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ + && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ + && echo .` + for boost_inc in $boost_layout_system_search_list + do + if test x"$boost_inc" != x.; then + boost_inc="$boost_dir/$boost_inc" + else + boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list + fi + if test x"$boost_inc" != x; then + # We are going to check whether the version of Boost installed + # in $boost_inc is usable by running a compilation that + # #includes it. But if we pass a -I/some/path in which Boost + # is not installed, the compiler will just skip this -I and + # use other locations (either from CPPFLAGS, or from its list + # of system include directories). As a result we would use + # header installed on the machine instead of the /some/path + # specified by the user. So in that precise case (trying + # $boost_inc), make sure the version.hpp exists. + # + # Use test -e as there can be symlinks. + test -e "$boost_inc/boost/version.hpp" || continue + CPPFLAGS="$CPPFLAGS -I$boost_inc" + fi + AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +AC_LANG_POP([C++])dnl + ]) + case $boost_cv_inc_path in #( + no) + boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" + m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], + [AC_MSG_NOTICE([$boost_errmsg])]) + $2 + ;;#( + yes) + BOOST_CPPFLAGS= + ;;#( + *) + AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl + ;; + esac + if test x"$boost_cv_inc_path" != xno; then + AC_DEFINE([HAVE_BOOST], [1], + [Defined if the requested minimum BOOST version is satisfied]) + AC_CACHE_CHECK([for Boost's header version], + [boost_cv_lib_version], + [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl + _BOOST_SED_CPP([[/^boost-lib-version = /{s///;s/[\" ]//g;p;q;}]], + [#include +boost-lib-version = BOOST_LIB_VERSION], + [boost_cv_lib_version=`cat conftest.i`])]) + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[[!0-9]]*) + AC_MSG_ERROR([invalid value: boost_major_version='$boost_major_version']) + ;; + esac +fi +CPPFLAGS=$boost_save_CPPFLAGS +])# BOOST_REQUIRE + + +# BOOST_STATIC() +# -------------- +# Add the "--enable-static-boost" configure argument. If this argument is given +# on the command line, static versions of the libraries will be looked up. +AC_DEFUN([BOOST_STATIC], + [AC_ARG_ENABLE([static-boost], + [AS_HELP_STRING([--enable-static-boost], + [Prefer the static boost libraries over the shared ones [no]])], + [enable_static_boost=yes], + [enable_static_boost=no])])# BOOST_STATIC + + +# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) +# -------------------------------------------------------------------------- +# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for +# some parts of the Boost library which are only made of headers and don't +# require linking (such as Boost.Foreach). +# +# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be +# found in the first place, in which case by default a notice is issued to the +# user. Presumably if we haven't died already it's because it's OK to not have +# Boost, which is why only a notice is issued instead of a hard error. +# +# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in +# case of success # (where HEADER-NAME is written LIKE_THIS, e.g., +# HAVE_BOOST_FOREACH_HPP). +AC_DEFUN([BOOST_FIND_HEADER], +[AC_REQUIRE([BOOST_REQUIRE])dnl +if test x"$boost_cv_inc_path" = xno; then + m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) +else +AC_LANG_PUSH([C++])dnl +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CHECK_HEADER([$1], + [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], + [Define to 1 if you have <$1>])])], + [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) +CPPFLAGS=$boost_save_CPPFLAGS +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_HEADER + + +# BOOST_FIND_LIBS([COMPONENT-NAME], [CANDIDATE-LIB-NAMES], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# -------------------------------------------------------------- +# Look for the Boost library COMPONENT-NAME (e.g., `thread', for +# libboost_thread) under the possible CANDIDATE-LIB-NAMES (e.g., +# "thread_win32 thread"). Check that HEADER-NAME works and check that +# libboost_LIB-NAME can link with the code CXX-TEST. The optional +# argument CXX-PROLOGUE can be used to include some C++ code before +# the `main' function. +# +# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). +# +# Boost libraries typically come compiled with several flavors (with different +# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one +# or more of the following letters: sgdpn (in that order). s = static +# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, +# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' +# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can +# start with `mt-' to indicate that there is a preference for multi-thread +# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp +# ... If you want to make sure you have a specific version of Boost +# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. +AC_DEFUN([BOOST_FIND_LIBS], +[AC_REQUIRE([BOOST_REQUIRE])dnl +AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl +AC_REQUIRE([BOOST_STATIC])dnl +AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl +if test x"$boost_cv_inc_path" = xno; then + AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) +else +dnl The else branch is huge and wasn't intended on purpose. +AC_LANG_PUSH([C++])dnl +AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl +AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl +AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl +AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl +BOOST_FIND_HEADER([$4]) +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], + [_BOOST_FIND_LIBS($@)]) +case $Boost_lib in #( + (no) _AC_MSG_LOG_CONFTEST + AC_MSG_ERROR([cannot find the flags to link with Boost $1]) + ;; +esac +AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl +AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl +CPPFLAGS=$boost_save_CPPFLAGS +AS_VAR_POPDEF([Boost_lib])dnl +AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl +AS_VAR_POPDEF([Boost_lib_LDPATH])dnl +AS_VAR_POPDEF([Boost_lib_LIBS])dnl +AC_LANG_POP([C++])dnl +fi +]) + + +# BOOST_FIND_LIB([LIB-NAME], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# -------------------------------------------------------------- +# Backward compatibility wrapper for BOOST_FIND_LIBS. +AC_DEFUN([BOOST_FIND_LIB], +[BOOST_FIND_LIBS([$1], $@)]) + + +# _BOOST_FIND_LIBS([LIB-NAME], [CANDIDATE-LIB-NAMES], +# [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# -------------------------------------------------------------- +# Real implementation of BOOST_FIND_LIBS: rely on these local macros: +# Boost_lib, Boost_lib_LDFLAGS, Boost_lib_LDPATH, Boost_lib_LIBS +# +# The algorithm is as follows: first look for a given library name +# according to the user's PREFERRED-RT-OPT. For each library name, we +# prefer to use the ones that carry the tag (toolset name). Each +# library is searched through the various standard paths were Boost is +# usually installed. If we can't find the standard variants, we try +# to enforce -mt (for instance on MacOSX, libboost_thread.dylib +# doesn't exist but there's -obviously- libboost_thread-mt.dylib). +AC_DEFUN([_BOOST_FIND_LIBS], +[Boost_lib=no + case "$3" in #( + (mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + (mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$3" : 'Xmt-*\(.*\)'`;; #( + (*) boost_mt=; boost_rtopt=$3;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + (*d*) boost_rt_d=$boost_rtopt;; #( + (*[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + (*) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) + boost_save_ac_objext=$ac_objext + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$4> +$6], [$5])]) +dnl Optimization hacks: compiling C++ is slow, especially with Boost. What +dnl we're trying to do here is guess the right combination of link flags +dnl (LIBS / LDFLAGS) to use a given library. This can take several +dnl iterations before it succeeds and is thus *very* slow. So what we do +dnl instead is that we compile the code first (and thus get an object file, +dnl typically conftest.o). Then we try various combinations of link flags +dnl until we succeed to link conftest.o in an executable. The problem is +dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always +dnl remove all the temporary files including conftest.o. So the trick here +dnl is to temporarily change the value of ac_objext so that conftest.o is +dnl preserved accross tests. This is obviously fragile and I will burn in +dnl hell for not respecting Autoconf's documented interfaces, but in the +dnl mean time, it optimizes the macro by a factor of 5 to 30. +dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left +dnl empty because the test file is generated only once above (before we +dnl start the for loops). + AC_COMPILE_IFELSE([], + [ac_objext=do_not_rm_me_plz], + [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the following nested for loops, only the 2 +# innermost ones matter. +for boost_lib_ in $2; do +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_lib in \ + boost_$boost_lib_$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + boost_$boost_lib_$boost_tag_$boost_rtopt_$boost_ver_ \ + boost_$boost_lib_$boost_tag_$boost_mt_$boost_ver_ \ + boost_$boost_lib_$boost_tag_$boost_ver_ + do + # Avoid testing twice the same lib + case $boost_failed_libs in #( + (*@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + # Don't waste time with directories that don't exist. + if test x"$boost_ldpath" != x && test ! -e "$boost_ldpath"; then + continue + fi + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + (*?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$Boost_lib_LIBS" || continue;; #( + (*) # No: use -lboost_foo to find the shared library. + Boost_lib_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$Boost_lib_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" +dnl First argument of AC_LINK_IFELSE left empty because the test file is +dnl generated only once above (before we start the for loops). + _BOOST_AC_LINK_IFELSE([], + [Boost_lib=yes], [Boost_lib=no]) + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$Boost_lib" = xyes; then + # Check or used cached result of whether or not using -R or + # -rpath makes sense. Some implementations of ld, such as for + # Mac OSX, require -rpath but -R is the flag known to work on + # other systems. https://github.com/tsuna/boost.m4/issues/19 + AC_CACHE_VAL([boost_cv_rpath_link_ldflag], + [case $boost_ldpath in + '') # Nothing to do. + boost_cv_rpath_link_ldflag= + boost_rpath_link_ldflag_found=yes;; + *) + for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_save_LIBS $Boost_lib_LIBS" + _BOOST_AC_LINK_IFELSE([], + [boost_rpath_link_ldflag_found=yes + break], + [boost_rpath_link_ldflag_found=no]) + done + ;; + esac + AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], + [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + ]) + test x"$boost_ldpath" != x && + Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + Boost_lib_LDPATH="$boost_ldpath" + break 7 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +done # boost_lib_ +rm -f conftest.$ac_objext +]) + + + +# --------------------------------------- # +# Checks for the various Boost libraries. # +# --------------------------------------- # + +# List of boost libraries: http://www.boost.org/libs/libraries.htm +# The page http://beta.boost.org/doc/libs is useful: it gives the first release +# version of each library (among other things). + +# BOOST_DEFUN(LIBRARY, CODE) +# -------------------------- +# Define BOOST_ as a macro that runs CODE. +# +# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. +m4_define([BOOST_DEFUN], +[m4_indir([AC_DEFUN], + m4_toupper([BOOST_$1]), +[m4_pushdef([BOOST_Library], [$1])dnl +$2 +m4_popdef([BOOST_Library])dnl +]) +]) + +# BOOST_ARRAY() +# ------------- +# Look for Boost.Array +BOOST_DEFUN([Array], +[BOOST_FIND_HEADER([boost/array.hpp])]) + + +# BOOST_ASIO() +# ------------ +# Look for Boost.Asio (new in Boost 1.35). +BOOST_DEFUN([Asio], +[AC_REQUIRE([BOOST_SYSTEM])dnl +BOOST_FIND_HEADER([boost/asio.hpp])]) + + +# BOOST_ASSIGN() +# ------------- +# Look for Boost.Assign +BOOST_DEFUN([Assign], +[BOOST_FIND_HEADER([boost/assign.hpp])]) + + +# BOOST_BIND() +# ------------ +# Look for Boost.Bind. +BOOST_DEFUN([Bind], +[BOOST_FIND_HEADER([boost/bind/bind.hpp])]) + + +# BOOST_CHRONO() +# -------------- +# Look for Boost.Chrono. +BOOST_DEFUN([Chrono], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then + BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([chrono], [$1], + [boost/chrono.hpp], + [boost::chrono::thread_clock d;]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + BOOST_CHRONO_LIBS="$BOOST_CHRONO_LIBS $BOOST_SYSTEM_LIBS" +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_CHRONO + + +# BOOST_CONTEXT([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Context. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +# +# * This library was introduced in Boost 1.51.0 +# * The signatures of make_fcontext() and jump_fcontext were changed in 1.56.0 +# * A dependency on boost_thread appears in 1.57.0 +BOOST_DEFUN([Context], +[boost_context_save_LIBS=$LIBS + boost_context_save_LDFLAGS=$LDFLAGS +if test $boost_major_version -ge 157; then + BOOST_THREAD([$1]) + m4_pattern_allow([^BOOST_THREAD_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_THREAD_LIBS" + LDFLAGS="$LDFLAGS $BOOST_THREAD_LDFLAGS" +fi +BOOST_FIND_LIB([context], [$1], + [boost/context/all.hpp],[[ + +// creates a stack +void * stack_pointer = new void*[4096]; +std::size_t const size = sizeof(void*[4096]); + +#if BOOST_VERSION <= 105100 +ctx::make_fcontext(&fc, f); +return ctx::jump_fcontext(&fcm, &fc, 3) == 6; + +#else + +fc = ctx::make_fcontext(stack_pointer, size, f); +return ctx::jump_fcontext(&fcm, fc, 3) == 6; + +#endif + + +]],[dnl + +#include +#if BOOST_VERSION <= 105100 + +namespace ctx = boost::ctx; + +static ctx::fcontext_t fcm, fc; + +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, &fcm, i * 2); +} + +#elif BOOST_VERSION <= 105500 + +namespace ctx = boost::context; + +// context +static ctx::fcontext_t fcm, *fc; + +// context-function +static void f(intptr_t i) { + ctx::jump_fcontext(fc, &fcm, i * 2); +} + +#else + +namespace ctx = boost::context; + +// context +static ctx::fcontext_t fcm, fc; + +// context-function +static void f(intptr_t i) { + ctx::jump_fcontext(&fc, fcm, i * 2); +} +#endif +]) +LIBS=$boost_context_save_LIBS +LDFLAGS=$boost_context_save_LDFLAGS +])# BOOST_CONTEXT + + +# BOOST_CONVERSION() +# ------------------ +# Look for Boost.Conversion (cast / lexical_cast) +BOOST_DEFUN([Conversion], +[BOOST_FIND_HEADER([boost/cast.hpp]) +BOOST_FIND_HEADER([boost/lexical_cast.hpp]) +])# BOOST_CONVERSION + + +# BOOST_COROUTINE([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Coroutine. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.53.0 +BOOST_DEFUN([Coroutine], +[ +boost_coroutine_save_LIBS=$LIBS +boost_coroutine_save_LDFLAGS=$LDFLAGS +# Link-time dependency from coroutine to context +BOOST_CONTEXT([$1]) +# Starting from Boost 1.55 a dependency on Boost.System is added +if test $boost_major_version -ge 155; then + BOOST_SYSTEM([$1]) +fi +m4_pattern_allow([^BOOST_(CONTEXT|SYSTEM)_(LIBS|LDFLAGS)]) +LIBS="$LIBS $BOOST_CONTEXT_LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_CONTEXT_LDFLAGS" + +# in 1.53 coroutine was a header only library +if test $boost_major_version -eq 153; then + BOOST_FIND_HEADER([boost/coroutine/coroutine.hpp]) +else + BOOST_FIND_LIB([coroutine], [$1], + [boost/coroutine/coroutine.hpp], + [ + #include + #if BOOST_VERSION <= 105500 + boost::coroutines::coroutine coro; coro.get(); + #else + boost::coroutines::asymmetric_coroutine::pull_type coro; coro.get(); + #endif + ]) +fi +# Link-time dependency from coroutine to context, existed only in 1.53, in 1.54 +# coroutine doesn't use context from its headers but from its library. +if test $boost_major_version -eq 153 || test $enable_static_boost = yes && test $boost_major_version -ge 154; then + BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_CONTEXT_LIBS" + BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_CONTEXT_LDFLAGS" +fi +if test $enable_static_boost = yes && test $boost_major_version -ge 155; then + BOOST_COROUTINE_LIBS="$BOOST_COROUTINE_LIBS $BOOST_SYSTEM_LIBS" + BOOST_COROUTINE_LDFLAGS="$BOOST_COROUTINE_LDFLAGS $BOOST_SYSTEM_LDFLAGS" +fi +LIBS=$boost_coroutine_save_LIBS +LDFLAGS=$boost_coroutine_save_LDFLAGS +])# BOOST_COROUTINE + + +# BOOST_CRC() +# ----------- +# Look for Boost.CRC +BOOST_DEFUN([CRC], +[BOOST_FIND_HEADER([boost/crc.hpp]) +])# BOOST_CRC + + +# BOOST_DATE_TIME([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Date_Time], +[BOOST_FIND_LIB([date_time], [$1], + [boost/date_time/posix_time/posix_time.hpp], + [boost::posix_time::ptime t;]) +])# BOOST_DATE_TIME + + +# BOOST_FILESYSTEM([PREFERRED-RT-OPT]) +# ------------------------------------ +# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +# Do not check for boost/filesystem.hpp because this file was introduced in +# 1.34. +BOOST_DEFUN([Filesystem], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then + BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([filesystem], [$1], + [boost/filesystem/path.hpp], [boost::filesystem::path p;]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + BOOST_FILESYSTEM_LIBS="$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_FILESYSTEM + + +# BOOST_FLYWEIGHT() +# ----------------- +# Look for Boost.Flyweight. +BOOST_DEFUN([Flyweight], +[dnl There's a hidden dependency on pthreads. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +BOOST_FIND_HEADER([boost/flyweight.hpp]) +AC_SUBST([BOOST_FLYWEIGHT_LIBS], [$boost_cv_pthread_flag]) +]) + + +# BOOST_FOREACH() +# --------------- +# Look for Boost.Foreach. +BOOST_DEFUN([Foreach], +[BOOST_FIND_HEADER([boost/foreach.hpp])]) + + +# BOOST_FORMAT() +# -------------- +# Look for Boost.Format. +# Note: we can't check for boost/format/format_fwd.hpp because the header isn't +# standalone. It can't be compiled because it triggers the following error: +# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' +# does not name a type +BOOST_DEFUN([Format], +[BOOST_FIND_HEADER([boost/format.hpp])]) + + +# BOOST_FUNCTION() +# ---------------- +# Look for Boost.Function +BOOST_DEFUN([Function], +[BOOST_FIND_HEADER([boost/function.hpp])]) + + +# BOOST_GEOMETRY() +# ---------------- +# Look for Boost.Geometry (new since 1.47.0). +BOOST_DEFUN([Geometry], +[BOOST_FIND_HEADER([boost/geometry.hpp]) +])# BOOST_GEOMETRY + + +# BOOST_GRAPH([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Graph], +[boost_graph_save_LIBS=$LIBS +boost_graph_save_LDFLAGS=$LDFLAGS +# Link-time dependency from graph to regex was added as of 1.40.0. +if test $boost_major_version -ge 140; then + BOOST_REGEX([$1]) + m4_pattern_allow([^BOOST_REGEX_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_REGEX_LIBS" + LDFLAGS="$LDFLAGS $BOOST_REGEX_LDFLAGS" +fi +BOOST_FIND_LIB([graph], [$1], + [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) +LIBS=$boost_graph_save_LIBS +LDFLAGS=$boost_graph_save_LDFLAGS +])# BOOST_GRAPH + + +# BOOST_IOSTREAMS([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([IOStreams], +[BOOST_FIND_LIB([iostreams], [$1], + [boost/iostreams/device/file_descriptor.hpp], + [boost::iostreams::file_descriptor fd; fd.close();]) +])# BOOST_IOSTREAMS + + +# BOOST_HASH() +# ------------ +# Look for Boost.Functional/Hash +BOOST_DEFUN([Hash], +[BOOST_FIND_HEADER([boost/functional/hash.hpp])]) + + +# BOOST_LAMBDA() +# -------------- +# Look for Boost.Lambda +BOOST_DEFUN([Lambda], +[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) + + +# BOOST_LOCALE() +# -------------- +# Look for Boost.Locale +BOOST_DEFUN([Locale], +[ +boost_locale_save_LIBS=$LIBS +boost_locale_save_LDFLAGS=$LDFLAGS +# require SYSTEM for boost-1.50.0 and up +if test $boost_major_version -ge 150; then + BOOST_SYSTEM([$1]) + m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl + LIBS="$LIBS $BOOST_SYSTEM_LIBS" + LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +fi # end of the Boost.System check. +BOOST_FIND_LIB([locale], [$1], + [boost/locale.hpp], + [[boost::locale::generator gen; std::locale::global(gen(""));]]) +LIBS=$boost_locale_save_LIBS +LDFLAGS=$boost_locale_save_LDFLAGS +])# BOOST_LOCALE + +# BOOST_LOG([PREFERRED-RT-OPT]) +# ----------------------------- +# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log], +[boost_log_save_LIBS=$LIBS +boost_log_save_LDFLAGS=$LDFLAGS +BOOST_SYSTEM([$1]) +BOOST_FILESYSTEM([$1]) +BOOST_DATE_TIME([$1]) +m4_pattern_allow([^BOOST_(SYSTEM|FILESYSTEM|DATE_TIME)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_DATE_TIME_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_DATE_TIME_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([log], [$1], + [boost/log/core/core.hpp], + [boost::log::attribute a; a.get_value();]) +LIBS=$boost_log_save_LIBS +LDFLAGS=$boost_log_save_LDFLAGS +])# BOOST_LOG + + +# BOOST_LOG_SETUP([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Log. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log_Setup], +[boost_log_setup_save_LIBS=$LIBS +boost_log_setup_save_LDFLAGS=$LDFLAGS +BOOST_LOG([$1]) +m4_pattern_allow([^BOOST_LOG_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_LOG_LIBS" +LDFLAGS="$LDFLAGS $BOOST_LOG_LDFLAGS" +BOOST_FIND_LIB([log_setup], [$1], + [boost/log/utility/setup/from_settings.hpp], + [boost::log::basic_settings bs; bs.empty();]) +LIBS=$boost_log_setup_save_LIBS +LDFLAGS=$boost_log_setup_save_LDFLAGS +])# BOOST_LOG_SETUP + + +# BOOST_MATH() +# ------------ +# Look for Boost.Math +# TODO: This library isn't header-only but it comes in multiple different +# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, +# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, +# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the +# right thing anyway. +BOOST_DEFUN([Math], +[BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) + + +# BOOST_MPI([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost MPI. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. Uses MPICXX variable if it is +# set, otherwise tries CXX +# +BOOST_DEFUN([MPI], +[boost_save_CXX=${CXX} +boost_save_CXXCPP=${CXXCPP} +if test x"${MPICXX}" != x; then + CXX=${MPICXX} + CXXCPP="${MPICXX} -E" +fi +BOOST_FIND_LIB([mpi], [$1], + [boost/mpi.hpp], + [int argc = 0; + char **argv = 0; + boost::mpi::environment env(argc,argv);]) +CXX=${boost_save_CXX} +CXXCPP=${boost_save_CXXCPP} +])# BOOST_MPI + + +# BOOST_MULTIARRAY() +# ------------------ +# Look for Boost.MultiArray +BOOST_DEFUN([MultiArray], +[BOOST_FIND_HEADER([boost/multi_array.hpp])]) + + +# BOOST_NUMERIC_UBLAS() +# -------------------------- +# Look for Boost.NumericUblas (Basic Linear Algebra) +BOOST_DEFUN([Numeric_Ublas], +[BOOST_FIND_HEADER([boost/numeric/ublas/vector.hpp]) +])# BOOST_NUMERIC_UBLAS + + +# BOOST_NUMERIC_CONVERSION() +# -------------------------- +# Look for Boost.NumericConversion (policy-based numeric conversion) +BOOST_DEFUN([Numeric_Conversion], +[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) +])# BOOST_NUMERIC_CONVERSION + + +# BOOST_OPTIONAL() +# ---------------- +# Look for Boost.Optional +BOOST_DEFUN([Optional], +[BOOST_FIND_HEADER([boost/optional.hpp])]) + + +# BOOST_PREPROCESSOR() +# -------------------- +# Look for Boost.Preprocessor +BOOST_DEFUN([Preprocessor], +[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) + + +# BOOST_RANGE() +# -------------------- +# Look for Boost.Range +BOOST_DEFUN([Range], +[BOOST_FIND_HEADER([boost/range/adaptors.hpp])]) + +# BOOST_UNORDERED() +# ----------------- +# Look for Boost.Unordered +BOOST_DEFUN([Unordered], +[BOOST_FIND_HEADER([boost/unordered_map.hpp])]) + + +# BOOST_UUID() +# ------------ +# Look for Boost.Uuid +BOOST_DEFUN([Uuid], +[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) + + +# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) +# ----------------------------------------- +# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Program_Options], +[BOOST_FIND_LIB([program_options], [$1], + [boost/program_options.hpp], + [boost::program_options::options_description d("test");]) +])# BOOST_PROGRAM_OPTIONS + + + +# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) +# ------------------------------------ +# Save VARIABLE, and define it via `python-config --FLAG`. +# Substitute BOOST_PYTHON_VARIABLE. +m4_define([_BOOST_PYTHON_CONFIG], +[AC_SUBST([BOOST_PYTHON_$1], + [`python-config --$2 2>/dev/null`])dnl +boost_python_save_$1=$$1 +$1="$$1 $BOOST_PYTHON_$1"]) + + +# BOOST_PYTHON([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Python], +[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) +_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) +_BOOST_PYTHON_CONFIG([LIBS], [libs]) +m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl +BOOST_FIND_LIBS([python], [python python3], [$1], + [boost/python.hpp], + [], [BOOST_PYTHON_MODULE(empty) {}]) +CPPFLAGS=$boost_python_save_CPPFLAGS +LDFLAGS=$boost_python_save_LDFLAGS +LIBS=$boost_python_save_LIBS +])# BOOST_PYTHON + + +# BOOST_REF() +# ----------- +# Look for Boost.Ref +BOOST_DEFUN([Ref], +[BOOST_FIND_HEADER([boost/ref.hpp])]) + + +# BOOST_REGEX([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Regex], +[BOOST_FIND_LIB([regex], [$1], + [boost/regex.hpp], + [boost::regex exp("*"); boost::regex_match("foo", exp);]) +])# BOOST_REGEX + + +# BOOST_SERIALIZATION([PREFERRED-RT-OPT]) +# --------------------------------------- +# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Serialization], +[BOOST_FIND_LIB([serialization], [$1], + [boost/archive/text_oarchive.hpp], + [std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o);]) +])# BOOST_SERIALIZATION + + +# BOOST_SIGNALS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Signals], +[BOOST_FIND_LIB([signals], [$1], + [boost/signal.hpp], + [boost::signal s;]) +])# BOOST_SIGNALS + + +# BOOST_SIGNALS2() +# ---------------- +# Look for Boost.Signals2 (new since 1.39.0). +BOOST_DEFUN([Signals2], +[BOOST_FIND_HEADER([boost/signals2.hpp]) +])# BOOST_SIGNALS2 + + +# BOOST_SMART_PTR() +# ----------------- +# Look for Boost.SmartPtr +BOOST_DEFUN([Smart_Ptr], +[BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) +BOOST_FIND_HEADER([boost/shared_ptr.hpp]) +]) + + +# BOOST_STATICASSERT() +# -------------------- +# Look for Boost.StaticAssert +BOOST_DEFUN([StaticAssert], +[BOOST_FIND_HEADER([boost/static_assert.hpp])]) + + +# BOOST_STRING_ALGO() +# ------------------- +# Look for Boost.StringAlgo +BOOST_DEFUN([String_Algo], +[BOOST_FIND_HEADER([boost/algorithm/string.hpp]) +]) + + +# BOOST_SYSTEM([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.35.0. +BOOST_DEFUN([System], +[BOOST_FIND_LIB([system], [$1], + [boost/system/error_code.hpp], + [boost::system::error_code e; e.clear();]) +])# BOOST_SYSTEM + + +# BOOST_TEST([PREFERRED-RT-OPT]) +# ------------------------------ +# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Test], +[m4_pattern_allow([^BOOST_CHECK$])dnl +BOOST_FIND_LIB([unit_test_framework], [$1], + [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], + [using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; }]) +])# BOOST_TEST + + +# BOOST_THREAD([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Thread], +[dnl Having the pthread flag is required at least on GCC3 where +dnl boost/thread.hpp would complain if we try to compile without +dnl -pthread on GNU/Linux. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +boost_thread_save_LIBS=$LIBS +boost_thread_save_LDFLAGS=$LDFLAGS +boost_thread_save_CPPFLAGS=$CPPFLAGS +# Link-time dependency from thread to system was added as of 1.49.0. +if test $boost_major_version -ge 149; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" + +# When compiling for the Windows platform, the threads library is named +# differently. This suffix doesn't exist in new versions of Boost, or +# possibly new versions of GCC on mingw I am assuming it's Boost's change for +# now and I am setting version to 1.48, for lack of knowledge as to when this +# change occurred. +if test $boost_major_version -lt 148; then + case $host_os in + (*mingw*) boost_thread_lib_ext=_win32;; + esac +fi +BOOST_FIND_LIBS([thread], [thread$boost_thread_lib_ext], + [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;]) + +case $host_os in + (*mingw*) boost_thread_w32_socket_link=-lws2_32;; +esac + +BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag $boost_thread_w32_socket_link" +BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" +BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" +LIBS=$boost_thread_save_LIBS +LDFLAGS=$boost_thread_save_LDFLAGS +CPPFLAGS=$boost_thread_save_CPPFLAGS +])# BOOST_THREAD + +AU_ALIAS([BOOST_THREADS], [BOOST_THREAD]) + + +# BOOST_TOKENIZER() +# ----------------- +# Look for Boost.Tokenizer +BOOST_DEFUN([Tokenizer], +[BOOST_FIND_HEADER([boost/tokenizer.hpp])]) + + +# BOOST_TRIBOOL() +# --------------- +# Look for Boost.Tribool +BOOST_DEFUN([Tribool], +[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) +BOOST_FIND_HEADER([boost/logic/tribool.hpp]) +]) + + +# BOOST_TUPLE() +# ------------- +# Look for Boost.Tuple +BOOST_DEFUN([Tuple], +[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) + + +# BOOST_TYPETRAITS() +# -------------------- +# Look for Boost.TypeTraits +BOOST_DEFUN([TypeTraits], +[BOOST_FIND_HEADER([boost/type_traits.hpp])]) + + +# BOOST_UTILITY() +# --------------- +# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, +# etc.) +BOOST_DEFUN([Utility], +[BOOST_FIND_HEADER([boost/utility.hpp])]) + + +# BOOST_VARIANT() +# --------------- +# Look for Boost.Variant. +BOOST_DEFUN([Variant], +[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) +BOOST_FIND_HEADER([boost/variant.hpp])]) + + +# BOOST_POINTER_CONTAINER() +# ------------------------ +# Look for Boost.PointerContainer +BOOST_DEFUN([Pointer_Container], +[BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) +])# BOOST_POINTER_CONTAINER + + +# BOOST_WAVE([PREFERRED-RT-OPT]) +# ------------------------------ +# NOTE: If you intend to use Wave/Spirit with thread support, make sure you +# call BOOST_THREAD first. +# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Wave], +[AC_REQUIRE([BOOST_FILESYSTEM])dnl +AC_REQUIRE([BOOST_DATE_TIME])dnl +boost_wave_save_LIBS=$LIBS +boost_wave_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ +$BOOST_THREAD_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ +$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" +BOOST_FIND_LIB([wave], [$1], + [boost/wave.hpp], + [boost::wave::token_id id; get_token_name(id);]) +LIBS=$boost_wave_save_LIBS +LDFLAGS=$boost_wave_save_LDFLAGS +])# BOOST_WAVE + + +# BOOST_XPRESSIVE() +# ----------------- +# Look for Boost.Xpressive (new since 1.36.0). +BOOST_DEFUN([Xpressive], +[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) + + +# ----------------- # +# Internal helpers. # +# ----------------- # + + +# _BOOST_PTHREAD_FLAG() +# --------------------- +# Internal helper for BOOST_THREAD. Computes boost_cv_pthread_flag +# which must be used in CPPFLAGS and LIBS. +# +# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, +# boost/thread.hpp will trigger a #error if -pthread isn't used: +# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support +# is not turned on. Please set the correct command line options for +# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" +# +# Based on ACX_PTHREAD: http://autoconf-archive.cryp.to/acx_pthread.html +AC_DEFUN([_BOOST_PTHREAD_FLAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_LANG_PUSH([C++])dnl +AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], +[ boost_cv_pthread_flag= + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + case $host_os in #( + *solaris*) + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( + *) + boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ + -pthreads -mthreads -lpthread --thread-safe -mt";; + esac + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) + for boost_pthread_flag in '' $boost_pthread_flags; do + boost_pthread_ok=false +dnl Re-use the test file already generated. + boost_pthreads__save_LIBS=$LIBS + LIBS="$LIBS $boost_pthread_flag" + AC_LINK_IFELSE([], + [if grep ".*$boost_pthread_flag" conftest.err; then + echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD + else + boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag + fi]) + LIBS=$boost_pthreads__save_LIBS + $boost_pthread_ok && break + done +]) +AC_LANG_POP([C++])dnl +])# _BOOST_PTHREAD_FLAG + + +# _BOOST_gcc_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_gcc_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl + +# _BOOST_mingw_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_mingw_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC && \ + (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw$1$2"])dnl + + +# _BOOST_FIND_COMPILER_TAG() +# -------------------------- +# Internal. When Boost is installed without --layout=system, each library +# filename will hold a suffix that encodes the compiler used during the +# build. The Boost build system seems to call this a `tag'. +AC_DEFUN([_BOOST_FIND_COMPILER_TAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], + [boost_cv_lib_tag], +[boost_cv_lib_tag=unknown +if test x$boost_cv_inc_path != xno; then + AC_LANG_PUSH([C++])dnl + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + for i in \ + _BOOST_mingw_test(6, 2) \ + _BOOST_gcc_test(6, 2) \ + _BOOST_mingw_test(6, 1) \ + _BOOST_gcc_test(6, 1) \ + _BOOST_mingw_test(6, 0) \ + _BOOST_gcc_test(6, 0) \ + _BOOST_mingw_test(5, 3) \ + _BOOST_gcc_test(5, 3) \ + _BOOST_mingw_test(5, 2) \ + _BOOST_gcc_test(5, 2) \ + _BOOST_mingw_test(5, 1) \ + _BOOST_gcc_test(5, 1) \ + _BOOST_mingw_test(5, 0) \ + _BOOST_gcc_test(5, 0) \ + _BOOST_mingw_test(4, 10) \ + _BOOST_gcc_test(4, 10) \ + _BOOST_mingw_test(4, 9) \ + _BOOST_gcc_test(4, 9) \ + _BOOST_mingw_test(4, 8) \ + _BOOST_gcc_test(4, 8) \ + _BOOST_mingw_test(4, 7) \ + _BOOST_gcc_test(4, 7) \ + _BOOST_mingw_test(4, 6) \ + _BOOST_gcc_test(4, 6) \ + _BOOST_mingw_test(4, 5) \ + _BOOST_gcc_test(4, 5) \ + _BOOST_mingw_test(4, 4) \ + _BOOST_gcc_test(4, 4) \ + _BOOST_mingw_test(4, 3) \ + _BOOST_gcc_test(4, 3) \ + _BOOST_mingw_test(4, 2) \ + _BOOST_gcc_test(4, 2) \ + _BOOST_mingw_test(4, 1) \ + _BOOST_gcc_test(4, 1) \ + _BOOST_mingw_test(4, 0) \ + _BOOST_gcc_test(4, 0) \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + _BOOST_gcc_test(3, 4) \ + _BOOST_gcc_test(3, 3) \ + "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ + "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ + _BOOST_gcc_test(3, 2) \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + _BOOST_gcc_test(3, 1) \ + _BOOST_gcc_test(3, 0) \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined __unix__) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + _BOOST_gcc_test(2, 95) \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` + boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif +]])], [boost_cv_lib_tag=$boost_tag; break], []) + done +AC_LANG_POP([C++])dnl + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + boost_tag_x= + case $host_os in #( + darwin*) + if test $boost_major_version -ge 136; then + # The `x' added in r46793 of Boost. + boost_tag_x=x + fi;; + esac + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" + ;; #( + unknown) + AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) + boost_cv_lib_tag= + ;; + esac +fi])dnl end of AC_CACHE_CHECK +])# _BOOST_FIND_COMPILER_TAG + + +# _BOOST_GUESS_WHETHER_TO_USE_MT() +# -------------------------------- +# Compile a small test to try to guess whether we should favor MT (Multi +# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. +AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], +[# Check whether we do better use `mt' even though we weren't ask to. +AC_LANG_PUSH([C++])dnl +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif +]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) +AC_LANG_POP([C++])dnl +]) + +# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# ------------------------------------------------------------------- +# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, +# will break when Autoconf changes its internals. Requires that you manually +# rm -f conftest.$ac_objext in between to really different tests, otherwise +# you will try to link a conftest.o left behind by a previous test. +# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this +# macro). +# +# Don't use "break" in the actions, as it would short-circuit some code +# this macro runs after the actions. +m4_define([_BOOST_AC_LINK_IFELSE], +[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl +rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) +AS_IF([_AC_DO_STDERR($ac_link) && { + test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext +dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. + }], + [$2], + [if $boost_use_source; then + _AC_MSG_LOG_CONFTEST + fi + $3]) +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) +dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), +dnl as it would interfere with the next link command. +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl +])# _BOOST_AC_LINK_IFELSE + +# Local Variables: +# mode: autoconf +# End: diff --git a/m4/libtool.m4 b/m4/libtool.m4 new file mode 100644 index 0000000000..10ab2844c4 --- /dev/null +++ b/m4/libtool.m4 @@ -0,0 +1,8388 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +]) + +# serial 58 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS=$ltmain + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_PREPARE_CC_BASENAME +# ----------------------- +m4_defun([_LT_PREPARE_CC_BASENAME], [ +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in @S|@*""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} +])# _LT_PREPARE_CC_BASENAME + + +# _LT_CC_BASENAME(CC) +# ------------------- +# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, +# but that macro is also expanded into generated libtool script, which +# arranges for $SED and $ECHO to be set by different means. +m4_defun([_LT_CC_BASENAME], +[m4_require([_LT_PREPARE_CC_BASENAME])dnl +AC_REQUIRE([_LT_DECL_SED])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl +func_cc_basename $1 +cc_basename=$func_cc_basename_result +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl +dnl +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl +m4_require([_LT_CMD_TRUNCATE])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options that allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld=$lt_cv_prog_gnu_ld + +old_CC=$CC +old_CFLAGS=$CFLAGS + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from 'configure', and 'config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# 'config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain=$ac_aux_dir/ltmain.sh +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the 'libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to 'config.status' so that its +# declaration there will have the same value as in 'configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags='_LT_TAGS'dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into 'config.status', and then the shell code to quote escape them in +# for loops in 'config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# '#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test 0 = "$lt_write_fail" && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +'$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2011 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test 0 != $[#] +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try '$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try '$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test yes = "$silent" && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options that allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}"; then + setopt NO_GLOB_SUBST + fi + + cfgfile=${ofile}T + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL +# Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +_LT_COPYING +_LT_LIBTOOL_TAGS + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +_LT_PREPARE_MUNGE_PATH_LIST +_LT_PREPARE_CC_BASENAME + +# ### END FUNCTIONS SHARED WITH CONFIGURE + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test set != "${COLLECT_NAMES+set}"; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Go], [_LT_LANG(GO)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +m4_ifndef([AC_PROG_GO], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_GO. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +m4_defun([AC_PROG_GO], +[AC_LANG_PUSH(Go)dnl +AC_ARG_VAR([GOC], [Go compiler command])dnl +AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl +_AC_ARG_VAR_LDFLAGS()dnl +AC_CHECK_TOOL(GOC, gccgo) +if test -z "$GOC"; then + if test -n "$ac_tool_prefix"; then + AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) + fi +fi +if test -z "$GOC"; then + AC_CHECK_PROG(GOC, gccgo, gccgo, false) +fi +])#m4_defun +])#m4_ifndef + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([AC_PROG_GO], + [LT_LANG(GO)], + [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "$LT_MULTI_MODULE"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS=$save_LDFLAGS + ]) + + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&AS_MESSAGE_LOG_FD + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[[012]][[,.]]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test yes = "$lt_cv_apple_cc_single_mod"; then + _lt_dar_single_mod='$single_module' + fi + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' + fi + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES([TAG]) +# --------------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test yes = "$lt_cv_ld_force_load"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], + [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined + case $cc_basename in + ifort*|nagfor*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + m4_if([$1], [CXX], +[ if test yes != "$lt_cv_apple_cc_single_mod"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script that will find a shell with a builtin +# printf (that we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case $ECHO in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], + [Search for dependent libraries within DIR (or the compiler's sysroot + if not specified).])], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([$with_sysroot]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and where our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test no = "$enable_libtool_lock" || enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE=32 + ;; + *ELF-64*) + HPUX_IA64_MODE=64 + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test yes = "$lt_cv_prog_gnu_ld"; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac + ;; + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test yes != "$lt_cv_cc_needs_belf"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS=$SAVE_CFLAGS + fi + ;; +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks=$enable_libtool_lock +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test yes = "[$]$2"; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS +]) + +if test yes = "[$]$2"; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring=ABCD + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n "$lt_cv_sys_max_cmd_len"; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes = "$cross_compiling"; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test yes != "$enable_dlopen"; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen=load_add_on + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen=LoadLibrary + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ + lt_cv_dlopen=dyld + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen=shl_load], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen=dlopen], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test no = "$lt_cv_dlopen"; then + enable_dlopen=no + else + enable_dlopen=yes + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS=$LDFLAGS + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS=$LIBS + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test yes = "$lt_cv_dlopen_self"; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links=nottested +if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test no = "$hard_links"; then + AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", + [Define to the sub-directory where libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then + + # We can hardcode non-existent directories. + if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && + test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || + test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then + # Fast installation is not supported + enable_fast_install=no +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_PREPARE_MUNGE_PATH_LIST +# --------------------------- +# Make sure func_munge_path_list() is defined correctly. +m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], +[[# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x@S|@2 in + x) + ;; + *:) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" + ;; + x:*) + eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" + ;; + *) + eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" + ;; + esac +} +]])# _LT_PREPARE_PATH_LIST + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test yes = "$GCC"; then + case $host_os in + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary... + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo = "/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=.so +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +AC_ARG_VAR([LT_SYS_LIBRARY_PATH], +[User-defined run-time library search path.]) + +case $host_os in +aix3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='$libname$release$shared_ext$major' + ;; + +aix[[4-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test ia64 = "$host_cpu"; then + # AIX 5 supports IA64 + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a[(]lib.so.V[)]' + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='$libname$shared_ext' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[23]].*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2.*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 + fi + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +linux*android*) + version_type=none # Android doesn't support versioned libraries. + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd* | bitrig*) + version_type=sunos + sys_lib_dlsearch_path_spec=/usr/lib + need_lib_prefix=no + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +os2*) + libname_spec='$name' + version_type=windows + shrext_cmds=.dll + need_version=no + need_lib_prefix=no + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test yes = "$with_gnu_ld"; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=sco + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test yes = "$with_gnu_ld"; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test no = "$dynamic_linker" && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test yes = "$GCC"; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec +fi + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec +fi + +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], + [Detected run-time system search path for libraries]) +_LT_DECL([], [configure_time_lt_sys_library_path], [2], + [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program that can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$1"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD=$lt_cv_path_MAGIC_CMD + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD + ;; +esac]) +MAGIC_CMD=$lt_cv_path_MAGIC_CMD +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program that can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test no = "$withval" || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test yes = "$GCC"; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return, which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD=$ac_prog + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test yes = "$with_gnu_ld"; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD=$ac_dir/$ac_prog + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], +[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi]) +rm -f conftest.i conftest2.i conftest.out]) +])# _LT_PATH_DD + + +# _LT_CMD_TRUNCATE +# ---------------- +# find command to truncate a binary pipe +m4_defun([_LT_CMD_TRUNCATE], +[m4_require([_LT_PATH_DD]) +AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], +[printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) +_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], + [Command to truncate a binary pipe]) +])# _LT_CMD_TRUNCATE + + +# _LT_CHECK_MAGIC_METHOD +# ---------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_MAGIC_METHOD], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +AC_CACHE_CHECK([how to recognize dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# 'unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + if ( file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM=$NM +else + lt_nm_to_check=${ac_tool_prefix}nm + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS=$lt_save_ifs + test -z "$ac_dir" && ac_dir=. + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break 2 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break 2 + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS=$lt_save_ifs + done + : ${lt_cv_path_NM=no} +fi]) +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test : != "$DUMPBIN"; then + NM=$DUMPBIN + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# _LT_DLL_DEF_P([FILE]) +# --------------------- +# True iff FILE is a Windows DLL '.def' file. +# Keep in sync with func_dll_def_p in the libtool script +AC_DEFUN([_LT_DLL_DEF_P], +[dnl + test DEF = "`$SED -n dnl + -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace + -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments + -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl + -e q dnl Only consider the first "real" line + $1`" dnl +])# _LT_DLL_DEF_P + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM=-lm) + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test ia64 = "$host_cpu"; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test yes = "$pipe_works"; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], + [Transform the output of nm into a list of symbols to manually relocate]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([nm_interface], [lt_cv_nm_interface], [1], + [The name lister interface]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64, which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test yes = "$GCC"; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" + fi + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test ia64 = "$host_cpu"; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + case $host_os in + os2*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' + ;; + esac + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + # old Intel for x86_64, which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ F* | *Sun*Fortran*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + *Intel*\ [[CF]]*Compiler*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + *Portland\ Group*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms that do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test yes != "$GCC"; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd* | bitrig*) + with_gnu_ld=no + ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='$wl' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test ia64 != "$host_cpu"; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test linux-dietlibc = "$host_os"; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test no = "$tmp_diet" + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + tcc*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then + aix_use_runtimelinking=yes + break + fi + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GCC"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2.*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + + hpux10*) + if test yes,no = "$GCC,$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test yes,no = "$GCC,$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS=$save_LDFLAGS]) + if test yes = "$lt_cv_irix_exported_symbol"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi + _LT_TAGVAR(link_all_deplibs, $1)=no + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + _LT_TAGVAR(ld_shlibs, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + osf3*) + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test yes = "$GCC"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test yes = "$GCC"; then + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='$wl' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. GCC discards it without '$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test yes = "$GCC"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test sequent = "$host_vendor"; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + if test yes = "$GCC"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test sni = "$host_vendor"; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test yes,yes = "$GCC,$enable_shared"; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting $shlibpath_var if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC=$CC +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report what library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC=$lt_save_CC +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test no != "$CXX" && + ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || + (test g++ != "$CXX"))); then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_caught_CXX_error"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test yes = "$GXX"; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test yes = "$GXX"; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test yes = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='$wl' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test ia64 = "$host_cpu"; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag= + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + ;; + esac + + if test yes = "$GXX"; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`$CC -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test yes = "$aix_use_runtimelinking"; then + shared_flag=$shared_flag' $wl-G' + fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' + else + # not using gcc + if test ia64 = "$host_cpu"; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' + else + shared_flag='$wl-bM:SRE' + fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + # The "-G" linker flag allows undefined symbols. + _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag + else + if test ia64 = "$host_cpu"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared + # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + shrext_cmds=.dll + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd2.*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test yes = "$GXX"; then + if test no = "$with_gnu_ld"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + if test yes = "$supports_anon_versioning"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd* | bitrig*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands '-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test yes,no = "$GXX,$with_gnu_ld"; then + _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require '-G' NOT '-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We CANNOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no + + _LT_TAGVAR(GCC, $1)=$GXX + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test yes != "$_lt_caught_CXX_error" + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case @S|@2 in + .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; + *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF +package foo +func foo() { +} +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $prev$p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test x-L = "$p" || + test x-R = "$p"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test no = "$pre_test_object_deps_done"; then + case $prev in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)=$prev$p + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test no = "$pre_test_object_deps_done"; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)=$p + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)=$p + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test no = "$F77"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_F77"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$G77 + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_F77" + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test no = "$FC"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test yes != "$_lt_disable_FC"; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test no = "$can_build_shared" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test yes = "$enable_shared" && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test yes = "$enable_shared" || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu + _LT_TAGVAR(LD, $1)=$LD + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test yes != "$_lt_disable_FC" + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_GO_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Go compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_GO_CONFIG], +[AC_REQUIRE([LT_PROG_GO])dnl +AC_LANG_SAVE + +# Source file extension for Go test sources. +ac_ext=go + +# Object file extension for compiled Go test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="package main; func main() { }" + +# Code to be used in simple link tests +lt_simple_link_test_code='package main; func main() { }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GOC-"gccgo"} +CFLAGS=$GOFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)=$LD +_LT_CC_BASENAME([$compiler]) + +# Go did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GO_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to 'libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code=$lt_simple_compile_test_code + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_GO +# ---------- +AC_DEFUN([LT_PROG_GO], +[AC_CHECK_TOOL(GOC, gccgo,) +]) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f "$lt_ac_sed" && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test 10 -lt "$lt_ac_count" && break + lt_ac_count=`expr $lt_ac_count + 1` + if test "$lt_ac_count" -gt "$lt_ac_max"; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine what file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 new file mode 100644 index 0000000000..94b0829766 --- /dev/null +++ b/m4/ltoptions.m4 @@ -0,0 +1,437 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 8 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option '$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl 'shared' nor 'disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], + [_LT_WITH_AIX_SONAME([aix])]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the 'shared' and +# 'disable-shared' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the 'static' and +# 'disable-static' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the 'fast-install' +# and 'disable-fast-install' LT_INIT options. +# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for pkg in $enableval; do + IFS=$lt_save_ifs + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the 'disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_AIX_SONAME([DEFAULT]) +# ---------------------------------- +# implement the --with-aix-soname flag, and support the `aix-soname=aix' +# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT +# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. +m4_define([_LT_WITH_AIX_SONAME], +[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl +shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[[5-9]]*,yes) + AC_MSG_CHECKING([which variant of shared library versioning to provide]) + AC_ARG_WITH([aix-soname], + [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], + [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], + [case $withval in + aix|svr4|both) + ;; + *) + AC_MSG_ERROR([Unknown argument to --with-aix-soname]) + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname], + [AC_CACHE_VAL([lt_cv_with_aix_soname], + [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) + with_aix_soname=$lt_cv_with_aix_soname]) + AC_MSG_RESULT([$with_aix_soname]) + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + +_LT_DECL([], [shared_archive_member_spec], [0], + [Shared archive member basename, for filename based shared library versioning on AIX])dnl +])# _LT_WITH_AIX_SONAME + +LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) +LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the 'pic-only' and 'no-pic' +# LT_INIT options. +# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac], + [pic_mode=m4_default([$1], [default])]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the 'pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4 new file mode 100644 index 0000000000..48bc9344a4 --- /dev/null +++ b/m4/ltsugar.m4 @@ -0,0 +1,124 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59, which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 new file mode 100644 index 0000000000..fa04b52a3b --- /dev/null +++ b/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 4179 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4.6]) +m4_define([LT_PACKAGE_REVISION], [2.4.6]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4.6' +macro_revision='2.4.6' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000000..c6b26f88f6 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,99 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software +# Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/release-notes.txt b/release-notes.txt deleted file mode 100644 index 1e6cf6fe4a..0000000000 --- a/release-notes.txt +++ /dev/null @@ -1,160 +0,0 @@ - -Shadowcoin Release Notes - - -Version 1.3.3.0 - - - Added BIP44 support - - - Added BIP39 support - - - Added smaller ring signatures - https://bitcointalk.org/index.php?topic=972541.msg10619684 - - - The goal for this release is to implement a framework for BIP32 - on which to build, the more interesting features possible with bip32 keys can - be implemented later. For this release we aim to implement a hierarchical - deterministic wallet - which means you can recover all the keys in a wallet - using only the master key. - - - Added basic BIP32 support - - - - Each extended key can derive 2^31 normal child keys and 2^31 hardened - child keys. - - - - - All new keys are deterministically generated from a master key. - - The complete wallet state (except key labels) can be recreated from - a single master key. - - - When the wallet is first started a new master bip32 key will be generated - from the master key, internal (child 1) and external (child 0) chains are - derived from the master key. - - The wallet will only generate a master key automatically once. - If the first master key is removed a new key will need to be imported - manually for the wallet to be able to generate keys. - - - - New prefix for base58 data - - extended key identifiers are represented in the same way as normal - shadow addresses, to prevent confusion a new prefix has been added. - Extended key identifiers begin with 'x' on live, on testnet with 'X' - - - New rpc function extkey, alias: bip32 - - - path - The path is a backslash deliminated string of digits. - m/3/4h/5 - Only backslashes, digits and m, h and ' may occur in the path. - - The tokens m and 0 can only be first or last in the path. - - - examples: - - extkey - - returns the child key according to the path - - extkey gen - - generates new key from random data - - extkey - Match bip32.org keys: bip32 gen "pass" 50000 "Bitcoin seed" - - - Notes - - The change address of anon transactions is picked as the first stealth - address of default account else the first legacy stealth address. - - - Added Gitian build descriptors - - See contrib/gitian-descriptors/README - - - SMSG ScanBlock harvest public keys from coinstake transactions - - - Added "Txn Type" field to txnreport - - - Added 'env' parameter to getinfo - - returns more environment specific information - - - Added simple command line interface to shadowcoind - - enabled with new parameter "cli" when not started as a daemon - - - Added createmultisig rpc command - - createmultisig does the same as existing command addmultisigaddress - except that the resulting address and script are not added to the wallet. - - - decoderawtransaction scriptPubKey includes the hex representation - - hex of a prevout scriptPubKey is required for signrawtransaction - - - signrawtransaction works when private keys are passed in as parameters - - adds redeemScript to the tempKeystore - - - Added option to disable SMSG scanning of incoming blocks. - - smsgoptions set scanIncoming false - - - smsgoptions command is now case insensitive - - smsgoptions list takes a bool parameter to list option descriptions - - - dumpprivkey takes a pubkey as input - - - More unit tests enabled - - The coin_selection_tests sometimes fail, it's related to the nSpendTime - parameter and isn't a real error. - - - Gui improvements - - Lock icon goes orange when system unlocked for staking only. - - Table pagination icons limited to 5. - - - - -Version 1.3.2.0 - - - Implemented PoS V2 - - - - Removed Thin mode staking - The network relies on full nodes for security. - Staking should be a reward for maintaining a full node. - - - - Removed hash from DiskBlockIndex - hash is saved in the key, no need to save it twice, 32 bytes saved per block - Key prefix "blockindex" changed to "bidx", 36 bytes saved per block - - - The TXDB version has been raised to 70510. - - On first boot the nodes will wipe any database before 70509 and initialise - a reindex, which will reload the TXDB from the stored blockchain. - - For Databases of verson 70509 an migration will run, significantly faster - than a reindex. All existing nodes should be on txdb version 70509. - - Thin nodes don't store the blockchain and will need to redownload. - - Note: Reindexing the chain could cause your failed stake transactions to be - detected as occuring during the reindex, and displayed at the top of the - transaction list. They can be removed by running clearwallettransactions - followed by reloadanondata. - - - - - Enabled unit tests - Compile: make -f makefile.unix test_shadow - Run: ./test_shadow --log_level=all - - - - - - printstakemodifier, printcoinstake and printcoinage are replaced by debugpos - - - - - - - - - - - - - diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 0000000000..9138d92c30 --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +.buildconfig diff --git a/scripts/build-boost-for-android.sh b/scripts/build-boost-for-android.sh new file mode 100755 index 0000000000..5219f8dd1f --- /dev/null +++ b/scripts/build-boost-for-android.sh @@ -0,0 +1,129 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +ANDROID_NDK_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Android +ANDROID_NDK_ROOT=${ANDROID_NDK_ARCHIVE_LOCATION}/android-ndk-${ANDROID_NDK_VERSION} +ANDROID_ARCH=arm64 +ANDROID_API=22 +BOOST_LIBS_TO_BUILD=chrono + +helpMe() { + echo " + + Helper script to build Boost for Android. + + Usage: + ${0} [options] + + Optional parameters: + -a + -l + -n + Path to ndk directory. + -p + -v + Boost version to build. Default: ${BOOST_VERSION} + -h Show this help + + " +} + +HOST_SYSTEM='linux' + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) + HOST_SYSTEM='darwin' +else + CORES_TO_USE=1 +fi + +while getopts a:l:n:p:v:h? option; do + case ${option} in + a) ANDROID_ARCH="${OPTARG}";; + c) CORES_TO_USE="${OPTARG}";; + l) BOOST_LIBS_TO_BUILD="${OPTARG}";; + n) ANDROID_NDK_ROOT="${OPTARG}";; + p) ANDROID_API="${OPTARG}";; + v) BOOST_VERSION="${OPTARG}";; + h|?) helpMe && exit 0;; + *) die 90 "invalid option \"${OPTARG}\"";; + esac +done + +info " -> Boost $BOOST_VERSION..." +cd "${callDir}" + +case "${ANDROID_ARCH}" in + arm64) + jamEntry1="7.0~arm64" + jamEntry2="aarch64" + ;; + *) + jamEntry1="${ANDROID_ARCH}" + jamEntry2="${ANDROID_ARCH}" + ;; +esac + +info " -> Generating config..." +echo "path-constant ndk : ${ANDROID_NDK_ROOT} ;" > "${ANDROID_ARCH}-config.jam" +if [[ "${ANDROID_ARCH}" == "armv7a" ]]; then + echo "using clang : ${jamEntry1} : \$(ndk)/toolchains/llvm/prebuilt/${HOST_SYSTEM}-x86_64/bin/${jamEntry2}-linux-androideabi${ANDROID_API}-clang++ ;" >> "${ANDROID_ARCH}-config.jam" +else + echo "using clang : ${jamEntry1} : \$(ndk)/toolchains/llvm/prebuilt/${HOST_SYSTEM}-x86_64/bin/${jamEntry2}-linux-android${ANDROID_API}-clang++ ;" >> "${ANDROID_ARCH}-config.jam" +fi + +info " -> Bootstrapping..." +#./bootstrap.sh #--with-toolset=clang +./bootstrap.sh #--with-libraries=${BOOST_LIBS_TO_BUILD} + +info " -> Building boost with './b2 -d+2 \ + -j ${CORES_TO_USE} \ + --reconfigure \ + target-os=android \ + toolset=clang-${jamEntry1} \ + link=static \ + variant=release \ + threading=multi \ + cxxflags="-std=c++14 -fPIC" \ + --with-${BOOST_LIBS_TO_BUILD//,/ --with-} \ + --user-config="${ANDROID_ARCH}-config.jam" \ + --prefix="$(pwd)/../boost_${BOOST_VERSION//./_}" \ + install'" +./b2 -d+2 \ + -j "${CORES_TO_USE}" \ + --reconfigure \ + target-os=android \ + toolset=clang-"${jamEntry1}" \ + link=static \ + variant=release \ + threading=multi \ + cxxflags="-std=c++14 -fPIC" \ + --with-${BOOST_LIBS_TO_BUILD//,/ --with-} \ + --user-config="${ANDROID_ARCH}"-config.jam \ + --prefix="$(pwd)"/../boost_"${BOOST_VERSION//./_}" \ + install +info " -> Done!" +#read a diff --git a/scripts/cmake-build-android_arm64.sh b/scripts/cmake-build-android_arm64.sh new file mode 100755 index 0000000000..0e10d70d01 --- /dev/null +++ b/scripts/cmake-build-android_arm64.sh @@ -0,0 +1,1123 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-22 HLXEasy +# +# This script can be used to build Alias for Android using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## +##### ### # Android # ### ################################################### +ANDROID_NDK_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Android +ANDROID_NDK_ROOT=${ANDROID_NDK_ARCHIVE_LOCATION}/android-ndk-${ANDROID_NDK_VERSION} +ANDROID_TOOLCHAIN_CMAKE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake +ANDROID_ARCH=arm64 +ANDROID_ABI=arm64-v8a +ANDROID_API=26 + +##### ### # Android Qt # ### ################################################ +ANDROID_QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION_ANDROID}/android +ANDROID_QT_LIBRARYDIR=${ANDROID_QT_DIR}/lib + +##### ### # Boost # ### ##################################################### +# Location of Boost will be resolved by trying to find required Boost libs +BOOST_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Boost +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # Qt # ### ######################################################## +# Location of Qt will be resolved by trying to find required Qt libs +QT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Qt +QT_REQUIRED_LIBS='Core Widgets WebView WebChannel WebSockets QuickWidgets Quick Gui Qml Network' + +##### ### # BerkeleyDB # ### ################################################ +# Location of archive will be resolved like this: +# ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz +BERKELEYDB_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/BerkeleyDB + +##### ### # OpenSSL # ### ################################################### +# Location of archive will be resolved like this: +# ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz +#OPENSSL_ARCHIVE_LOCATION=https://mirror.viaduck.org/openssl +OPENSSL_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/OpenSSL + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor + +BUILD_DIR=cmake-build-cmdline-android${ANDROID_API}_${ANDROID_ARCH} + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. This includes also Android NDK. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + BerkeleyDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -s Use Qt from system + -t Build with included Tor + -h Show this help + + " +} + +# ===== Start of openssl functions =========================================== +checkOpenSSLArchive() { + if [[ -e "${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using OpenSSL archive ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + else + OPENSSL_ARCHIVE_URL=https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz + info " -> Downloading OpenSSL archive ${OPENSSL_ARCHIVE_URL}" + if [[ ! -e ${OPENSSL_ARCHIVE_LOCATION} ]]; then + mkdir -p ${OPENSSL_ARCHIVE_LOCATION} + fi + cd ${OPENSSL_ARCHIVE_LOCATION} + wget ${OPENSSL_ARCHIVE_URL} + cd - >/dev/null + fi +} + +# For OpenSSL we're using a fork of https://github.com/viaduck/openssl-cmake +# with some slight modifications for Alias +checkOpenSSLClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d openssl-cmake ]]; then + info " -> Updating openssl-cmake clone" + cd openssl-cmake + git pull --prune + else + info " -> Cloning openssl-cmake" + git clone --branch alias https://github.com/aliascash/openssl-cmake.git openssl-cmake + fi + cd "${currentDir}" +} + +checkOpenSSLBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished openssl build and install" + else + die ${rtc} " => OpenSSL build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkOpenSSL() { + info "" + info "OpenSSL:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a, skip build" + else + checkOpenSSLArchive + checkOpenSSLClone + checkOpenSSLBuild + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDBArchive() { + if [[ -e "${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using BerkeleyDB archive ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" + else + BERKELEYDB_ARCHIVE_URL=https://download.oracle.com/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + info " -> Downloading BerkeleyDB archive ${BERKELEYDB_ARCHIVE_URL}" + if [[ ! -e ${BERKELEYDB_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BERKELEYDB_ARCHIVE_LOCATION} + fi + cd ${BERKELEYDB_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BERKELEYDB_ARCHIVE_LOCATION}" + wget ${BERKELEYDB_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkBerkeleyDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished BerkeleyDB (libdb) build and install" + else + die ${rtc} " => BerkeleyDB (libdb) build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a, skip build" + else + checkBerkeleyDBArchive + checkBerkeleyDBBuild + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoostArchive() { + local currentDir=$(pwd) + if [[ ! -e ${BOOST_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BOOST_ARCHIVE_LOCATION} + fi + cd ${BOOST_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BOOST_ARCHIVE_LOCATION}" + if [[ ! -e "boost_${BOOST_VERSION//./_}.tar.gz" ]]; then + info " -> Downloading Boost archive" + wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION//./_}.tar.gz + else + info " -> Using existing Boost archive" + fi + + info " -> Verifying Boost archive checksum" + determinedChecksum=$(sha256sum boost_${BOOST_VERSION//./_}.tar.gz | awk '{ print $1 }') + info " Expected checksum: ${BOOST_ARCHIVE_HASH}" + info " Determined checksum: ${determinedChecksum}" + if [[ "${BOOST_ARCHIVE_HASH}" != "${determinedChecksum}" ]] ; then + die 2 " => Checksum of downloaded Boost archive not matching expected value!" + else + info " -> Checksum OK" + fi +} + +buildBoost() { + info " -> Building Boost on ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Cleanup before extraction" + rm -rf boost_${BOOST_VERSION//./_} + info " -> Extracting Boost archive" + tar xzf ${BOOST_ARCHIVE_LOCATION}/boost_${BOOST_VERSION//./_}.tar.gz + info " -> Building Boost" + cd boost_${BOOST_VERSION//./_} || die 1 "Unable to cd into boost_${BOOST_VERSION//./_}" + "${ownLocation}"/build-boost-for-android.sh -v ${BOOST_VERSION} -a ${ANDROID_ARCH} -p ${ANDROID_API} -n ${ANDROID_NDK_ROOT} -l "${BOOST_REQUIRED_LIBS// /,}" + cd "${currentDir}" || die 1 "Unable to cd into ${currentDir}" +} + +checkBoost() { + info "" + info "Boost:" + info " -> Searching required static Boost libs" + BOOST_ROOT=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_} + BOOST_INCLUDEDIR=${BOOST_ROOT}/include + BOOST_LIBRARYDIR=${BOOST_ROOT}/lib + boostBuildRequired=false + if [[ -d ${BOOST_LIBRARYDIR} ]]; then + for currentBoostDependency in ${BOOST_REQUIRED_LIBS}; do + if [[ -e ${BOOST_LIBRARYDIR}/libboost_${currentBoostDependency}.a ]]; then + info " -> ${currentBoostDependency}: OK" + else + warning " => ${currentBoostDependency}: Not found!" + boostBuildRequired=true + fi + done + else + warning " => Boost library directory ${BOOST_LIBRARYDIR} not found!" + boostBuildRequired=true + fi + if ${boostBuildRequired} ; then + checkBoostArchive + buildBoost + else + info " => All Boost requirements found" + fi +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${ANDROID_QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + for currentQtDependency in ${QT_REQUIRED_LIBS}; do + if [[ -n $(find ${ANDROID_QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}_${ANDROID_ABI}.so") ]]; then + info " -> ${currentQtDependency}: OK" + else + warning " -> ${currentQtDependency}: Not found!" + qtComponentMissing=true + fi + done + else + info " -> Qt library directory ${ANDROID_QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION}: Not all required components found!" + error "" + die 43 "Stopping build because of missing Qt" + + # Maybe used later: Build Qt ourself + local currentDir=$(pwd) + if [[ ! -e ${QT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${QT_ARCHIVE_LOCATION} + fi + cd ${QT_ARCHIVE_LOCATION} + if [[ ! -e "qt-everywhere-src-${QT_VERSION}.tar.xz" ]]; then + info " -> Downloading Qt archive" + wget https://download.qt.io/archive/qt/${QT_VERSION%.*}/${QT_VERSION}/single/qt-everywhere-src-${QT_VERSION}.tar.xz + else + info " -> Using existing Qt archive" + fi + info " -> Verifying archive checksum" + determinedMD5Sum=$(md5sum qt-everywhere-src-${QT_VERSION}.tar.xz | cut -d ' ' -f 1) + if [[ "${determinedMD5Sum}" != "${QT_ARCHIVE_HASH}" ]]; then + warning " => Checksum of downloaded archive not matching expected value of ${QT_ARCHIVE_HASH}: ${determinedMD5Sum}" + else + info " -> Archive checksum ok" + fi + info " -> Cleanup before extraction" + rm -rf qt-everywhere-src-${QT_VERSION} + info " -> Extracting Qt archive" + tar xf qt-everywhere-src-${QT_VERSION}.tar.xz + info " -> Configuring Qt build" + cd qt-everywhere-src-${QT_VERSION} + ./configure \ + -xplatform android-clang \ + --disable-rpath \ + -nomake tests \ + -nomake examples \ + -android-ndk ${ANDROID_NDK_ROOT} \ + -android-sdk ${ANDROID_SDK_ROOT} \ + -android-arch ${ANDROID_ABI} \ + -android-ndk-platform android-${ANDROID_API} \ + -no-warnings-are-errors \ + -opensource \ + -confirm-license \ + -silent \ + -prefix ${ANDROID_QT_INSTALLATION_DIR} || die 23 "Error during Qt configure step" + info " -> Building Qt" + make -j"${CORES_TO_USE}" || die 24 "Error during Qt build step" + info " -> Installing Qt" + make install || die 25 "Error during Qt install step" + cd "${currentDir}" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a, skip build" + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" + else + # TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + TOR_ARCHIVE_URL=https://github.com/guardianproject/tor/archive/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} -O tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of NDK functions =============================================== +checkNDKArchive() { + info "" + info "NDK:" + info " -> Searching Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE}" + if [[ -e ${ANDROID_TOOLCHAIN_CMAKE} ]]; then + info " -> Found it! :-)" + else + warning " -> Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE} not found!" + local currentDir=$(pwd) + if [[ ! -e ${ANDROID_NDK_ARCHIVE_LOCATION} ]]; then + mkdir -p ${ANDROID_NDK_ARCHIVE_LOCATION} + fi + cd ${ANDROID_NDK_ARCHIVE_LOCATION} + if [[ -e "${ANDROID_NDK_ARCHIVE}" ]]; then + info " -> Using existing NDK archive" + else + ANDROID_NDK_ARCHIVE_URL=https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE} + info " -> Downloading NDK archive ${ANDROID_NDK_ARCHIVE_URL}" + wget ${ANDROID_NDK_ARCHIVE_URL} + fi + info " -> Cleanup before extraction" + rm -rf android-ndk-${ANDROID_NDK_VERSION} + info " -> Extracting NDK archive" + unzip ${ANDROID_NDK_ARCHIVE} + cd - >/dev/null + fi +} +# ===== End of NDK functions ================================================= + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-darwin-x86_64.zip +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +GIVEN_DEPENDENCIES_BUILD_DIR='' + +while getopts a:c:dfgop:th? option; do + case ${option} in + a) ANDROID_TOOLCHAIN_CMAKE="${OPTARG}" ;; + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) + ENABLE_GUI=true + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${ANDROID_QT_LIBRARYDIR}/cmake" + ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkNDKArchive +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +fi +if ${ENABLE_GUI}; then + checkQt +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" +read -r -d '' cmd < Finished" +else + error " => Finished with return code ${rtc}" +fi +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/cmake-build-android_armv7.sh b/scripts/cmake-build-android_armv7.sh new file mode 100755 index 0000000000..ef691a0f03 --- /dev/null +++ b/scripts/cmake-build-android_armv7.sh @@ -0,0 +1,1124 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-22 HLXEasy +# +# This script can be used to build Alias for Android using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## +##### ### # Android # ### ################################################### +ANDROID_NDK_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Android +ANDROID_NDK_ROOT=${ANDROID_NDK_ARCHIVE_LOCATION}/android-ndk-${ANDROID_NDK_VERSION} +ANDROID_TOOLCHAIN_CMAKE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake +ANDROID_ARCH=armv7a +ANDROID_ABI=armeabi-v7a +ANDROID_API=26 + +##### ### # Android Qt # ### ################################################ +ANDROID_QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION_ANDROID}/android +ANDROID_QT_LIBRARYDIR=${ANDROID_QT_DIR}/lib + +##### ### # Boost # ### ##################################################### +# Location of Boost will be resolved by trying to find required Boost libs +BOOST_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Boost +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # Qt # ### ######################################################## +# Location of Qt will be resolved by trying to find required Qt libs +QT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Qt +QT_REQUIRED_LIBS='Core Widgets WebView WebChannel WebSockets QuickWidgets Quick Gui Qml Network' + +##### ### # BerkeleyDB # ### ################################################ +# Location of archive will be resolved like this: +# ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz +BERKELEYDB_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/BerkeleyDB + +##### ### # OpenSSL # ### ################################################### +# Location of archive will be resolved like this: +# ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz +#OPENSSL_ARCHIVE_LOCATION=https://mirror.viaduck.org/openssl +OPENSSL_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/OpenSSL + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor + +BUILD_DIR=cmake-build-cmdline-android${ANDROID_API}_${ANDROID_ARCH} + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. This includes also Android NDK. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + BerkeleyDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -s Use Qt from system + -t Build with included Tor + -h Show this help + + " +} + +# ===== Start of openssl functions =========================================== +checkOpenSSLArchive() { + if [[ -e "${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using OpenSSL archive ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + else + OPENSSL_ARCHIVE_URL=https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz + info " -> Downloading OpenSSL archive ${OPENSSL_ARCHIVE_URL}" + if [[ ! -e ${OPENSSL_ARCHIVE_LOCATION} ]]; then + mkdir -p ${OPENSSL_ARCHIVE_LOCATION} + fi + cd ${OPENSSL_ARCHIVE_LOCATION} + wget ${OPENSSL_ARCHIVE_URL} + cd - >/dev/null + fi +} + +# For OpenSSL we're using a fork of https://github.com/viaduck/openssl-cmake +# with some slight modifications for Alias +checkOpenSSLClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d openssl-cmake ]]; then + info " -> Updating openssl-cmake clone" + cd openssl-cmake + git pull --prune + else + info " -> Cloning openssl-cmake" + git clone --branch alias https://github.com/aliascash/openssl-cmake.git openssl-cmake + fi + cd "${currentDir}" +} + +checkOpenSSLBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished openssl build and install" + else + die ${rtc} " => OpenSSL build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkOpenSSL() { + info "" + info "OpenSSL:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a, skip build" + else + checkOpenSSLArchive + checkOpenSSLClone + checkOpenSSLBuild + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDBArchive() { + if [[ -e "${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using BerkeleyDB archive ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" + else + BERKELEYDB_ARCHIVE_URL=https://download.oracle.com/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + info " -> Downloading BerkeleyDB archive ${BERKELEYDB_ARCHIVE_URL}" + if [[ ! -e ${BERKELEYDB_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BERKELEYDB_ARCHIVE_LOCATION} + fi + cd ${BERKELEYDB_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BERKELEYDB_ARCHIVE_LOCATION}" + wget ${BERKELEYDB_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkBerkeleyDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished BerkeleyDB (libdb) build and install" + else + die ${rtc} " => BerkeleyDB (libdb) build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a, skip build" + else + checkBerkeleyDBArchive + checkBerkeleyDBBuild + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoostArchive() { + local currentDir=$(pwd) + if [[ ! -e ${BOOST_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BOOST_ARCHIVE_LOCATION} + fi + cd ${BOOST_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BOOST_ARCHIVE_LOCATION}" + if [[ ! -e "boost_${BOOST_VERSION//./_}.tar.gz" ]]; then + info " -> Downloading Boost archive" + wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION//./_}.tar.gz + else + info " -> Using existing Boost archive" + fi + + info " -> Verifying Boost archive checksum" + determinedChecksum=$(sha256sum boost_${BOOST_VERSION//./_}.tar.gz | awk '{ print $1 }') + info " Expected checksum: ${BOOST_ARCHIVE_HASH}" + info " Determined checksum: ${determinedChecksum}" + if [[ "${BOOST_ARCHIVE_HASH}" != "${determinedChecksum}" ]] ; then + die 2 " => Checksum of downloaded Boost archive not matching expected value!" + else + info " -> Checksum OK" + fi +} + +buildBoost() { + info " -> Building Boost on ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Cleanup before extraction" + rm -rf boost_${BOOST_VERSION//./_} + info " -> Extracting Boost archive" + tar xzf ${BOOST_ARCHIVE_LOCATION}/boost_${BOOST_VERSION//./_}.tar.gz + info " -> Building Boost" + cd boost_${BOOST_VERSION//./_} || die 1 "Unable to cd into boost_${BOOST_VERSION//./_}" + "${ownLocation}"/build-boost-for-android.sh -v ${BOOST_VERSION} -a ${ANDROID_ARCH} -p ${ANDROID_API} -n ${ANDROID_NDK_ROOT} -l "${BOOST_REQUIRED_LIBS// /,}" + cd "${currentDir}" || die 1 "Unable to cd into ${currentDir}" +} + +checkBoost() { + info "" + info "Boost:" + info " -> Searching required static Boost libs" + BOOST_ROOT=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_} + BOOST_INCLUDEDIR=${BOOST_ROOT}/include + BOOST_LIBRARYDIR=${BOOST_ROOT}/lib + boostBuildRequired=false + if [[ -d ${BOOST_LIBRARYDIR} ]]; then + for currentBoostDependency in ${BOOST_REQUIRED_LIBS}; do + if [[ -e ${BOOST_LIBRARYDIR}/libboost_${currentBoostDependency}.a ]]; then + info " -> ${currentBoostDependency}: OK" + else + warning " => ${currentBoostDependency}: Not found!" + boostBuildRequired=true + fi + done + else + warning " => Boost library directory ${BOOST_LIBRARYDIR} not found!" + boostBuildRequired=true + fi + if ${boostBuildRequired} ; then + checkBoostArchive + buildBoost + else + info " => All Boost requirements found" + fi +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${ANDROID_QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + for currentQtDependency in ${QT_REQUIRED_LIBS}; do + if [[ -n $(find ${ANDROID_QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}_${ANDROID_ABI}.so") ]]; then + info " -> ${currentQtDependency}: OK" + else + warning " -> ${currentQtDependency}: Not found!" + qtComponentMissing=true + fi + done + else + info " -> Qt library directory ${ANDROID_QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION}: Not all required components found!" + error "" + die 43 "Stopping build because of missing Qt" + + # Maybe used later: Build Qt ourself + local currentDir=$(pwd) + if [[ ! -e ${QT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${QT_ARCHIVE_LOCATION} + fi + cd ${QT_ARCHIVE_LOCATION} + if [[ ! -e "qt-everywhere-src-${QT_VERSION}.tar.xz" ]]; then + info " -> Downloading Qt archive" + wget https://download.qt.io/archive/qt/${QT_VERSION%.*}/${QT_VERSION}/single/qt-everywhere-src-${QT_VERSION}.tar.xz + else + info " -> Using existing Qt archive" + fi + info " -> Verifying archive checksum" + determinedMD5Sum=$(md5sum qt-everywhere-src-${QT_VERSION}.tar.xz | cut -d ' ' -f 1) + if [[ "${determinedMD5Sum}" != "${QT_ARCHIVE_HASH}" ]]; then + warning " => Checksum of downloaded archive not matching expected value of ${QT_ARCHIVE_HASH}: ${determinedMD5Sum}" + else + info " -> Archive checksum ok" + fi + info " -> Cleanup before extraction" + rm -rf qt-everywhere-src-${QT_VERSION} + info " -> Extracting Qt archive" + tar xf qt-everywhere-src-${QT_VERSION}.tar.xz + info " -> Configuring Qt build" + cd qt-everywhere-src-${QT_VERSION} + ./configure \ + -xplatform android-clang \ + --disable-rpath \ + -nomake tests \ + -nomake examples \ + -android-ndk ${ANDROID_NDK_ROOT} \ + -android-sdk ${ANDROID_SDK_ROOT} \ + -android-arch ${ANDROID_ABI} \ + -android-ndk-platform android-${ANDROID_API} \ + -no-warnings-are-errors \ + -opensource \ + -confirm-license \ + -silent \ + -prefix ${ANDROID_QT_INSTALLATION_DIR} || die 23 "Error during Qt configure step" + info " -> Building Qt" + make -j"${CORES_TO_USE}" || die 24 "Error during Qt build step" + info " -> Installing Qt" + make install || die 25 "Error during Qt install step" + cd "${currentDir}" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a, skip build" + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" + else + # TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + TOR_ARCHIVE_URL=https://github.com/guardianproject/tor/archive/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} -O tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of NDK functions =============================================== +checkNDKArchive() { + info "" + info "NDK:" + info " -> Searching Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE}" + if [[ -e ${ANDROID_TOOLCHAIN_CMAKE} ]]; then + info " -> Found it! :-)" + else + warning " -> Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE} not found!" + local currentDir=$(pwd) + if [[ ! -e ${ANDROID_NDK_ARCHIVE_LOCATION} ]]; then + mkdir -p ${ANDROID_NDK_ARCHIVE_LOCATION} + fi + cd ${ANDROID_NDK_ARCHIVE_LOCATION} + if [[ -e "${ANDROID_NDK_ARCHIVE}" ]]; then + info " -> Using existing NDK archive" + else + ANDROID_NDK_ARCHIVE_URL=https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE} + info " -> Downloading NDK archive ${ANDROID_NDK_ARCHIVE_URL}" + wget ${ANDROID_NDK_ARCHIVE_URL} + fi + info " -> Cleanup before extraction" + rm -rf android-ndk-${ANDROID_NDK_VERSION} + info " -> Extracting NDK archive" + unzip ${ANDROID_NDK_ARCHIVE} + cd - >/dev/null + fi +} +# ===== End of NDK functions ================================================= + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-darwin-x86_64.zip +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +GIVEN_DEPENDENCIES_BUILD_DIR='' + +while getopts a:c:dfgop:th? option; do + case ${option} in + a) ANDROID_TOOLCHAIN_CMAKE="${OPTARG}" ;; + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) + ENABLE_GUI=true + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${ANDROID_QT_LIBRARYDIR}/cmake" + ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkNDKArchive +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +fi +if ${ENABLE_GUI}; then + checkQt +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" +read -r -d '' cmd < Finished" +else + error " => Finished with return code ${rtc}" +fi +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/cmake-build-android_x86-64.sh b/scripts/cmake-build-android_x86-64.sh new file mode 100755 index 0000000000..bd1a0df217 --- /dev/null +++ b/scripts/cmake-build-android_x86-64.sh @@ -0,0 +1,1123 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-22 HLXEasy +# +# This script can be used to build Alias for Android using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## +##### ### # Android # ### ################################################### +ANDROID_NDK_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Android +ANDROID_NDK_ROOT=${ANDROID_NDK_ARCHIVE_LOCATION}/android-ndk-${ANDROID_NDK_VERSION} +ANDROID_TOOLCHAIN_CMAKE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake +ANDROID_ARCH=x86_64 +ANDROID_ABI=x86_64 +ANDROID_API=26 + +##### ### # Android Qt # ### ################################################ +ANDROID_QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION_ANDROID}/android +ANDROID_QT_LIBRARYDIR=${ANDROID_QT_DIR}/lib + +##### ### # Boost # ### ##################################################### +# Location of Boost will be resolved by trying to find required Boost libs +BOOST_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Boost +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # Qt # ### ######################################################## +# Location of Qt will be resolved by trying to find required Qt libs +QT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Qt +QT_REQUIRED_LIBS='Core Widgets WebView WebChannel WebSockets QuickWidgets Quick Gui Qml Network' + +##### ### # BerkeleyDB # ### ################################################ +# Location of archive will be resolved like this: +# ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz +BERKELEYDB_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/BerkeleyDB + +##### ### # OpenSSL # ### ################################################### +# Location of archive will be resolved like this: +# ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz +#OPENSSL_ARCHIVE_LOCATION=https://mirror.viaduck.org/openssl +OPENSSL_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/OpenSSL + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor + +BUILD_DIR=cmake-build-cmdline-android${ANDROID_API}_${ANDROID_ARCH} + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. This includes also Android NDK. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + BerkeleyDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -s Use Qt from system + -t Build with included Tor + -h Show this help + + " +} + +# ===== Start of openssl functions =========================================== +checkOpenSSLArchive() { + if [[ -e "${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using OpenSSL archive ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + else + OPENSSL_ARCHIVE_URL=https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz + info " -> Downloading OpenSSL archive ${OPENSSL_ARCHIVE_URL}" + if [[ ! -e ${OPENSSL_ARCHIVE_LOCATION} ]]; then + mkdir -p ${OPENSSL_ARCHIVE_LOCATION} + fi + cd ${OPENSSL_ARCHIVE_LOCATION} + wget ${OPENSSL_ARCHIVE_URL} + cd - >/dev/null + fi +} + +# For OpenSSL we're using a fork of https://github.com/viaduck/openssl-cmake +# with some slight modifications for Alias +checkOpenSSLClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d openssl-cmake ]]; then + info " -> Updating openssl-cmake clone" + cd openssl-cmake + git pull --prune + else + info " -> Cloning openssl-cmake" + git clone --branch alias https://github.com/aliascash/openssl-cmake.git openssl-cmake + fi + cd "${currentDir}" +} + +checkOpenSSLBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished openssl build and install" + else + die ${rtc} " => OpenSSL build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkOpenSSL() { + info "" + info "OpenSSL:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a, skip build" + else + checkOpenSSLArchive + checkOpenSSLClone + checkOpenSSLBuild + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDBArchive() { + if [[ -e "${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using BerkeleyDB archive ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" + else + BERKELEYDB_ARCHIVE_URL=https://download.oracle.com/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + info " -> Downloading BerkeleyDB archive ${BERKELEYDB_ARCHIVE_URL}" + if [[ ! -e ${BERKELEYDB_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BERKELEYDB_ARCHIVE_LOCATION} + fi + cd ${BERKELEYDB_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BERKELEYDB_ARCHIVE_LOCATION}" + wget ${BERKELEYDB_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkBerkeleyDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished BerkeleyDB (libdb) build and install" + else + die ${rtc} " => BerkeleyDB (libdb) build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a, skip build" + else + checkBerkeleyDBArchive + checkBerkeleyDBBuild + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoostArchive() { + local currentDir=$(pwd) + if [[ ! -e ${BOOST_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BOOST_ARCHIVE_LOCATION} + fi + cd ${BOOST_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BOOST_ARCHIVE_LOCATION}" + if [[ ! -e "boost_${BOOST_VERSION//./_}.tar.gz" ]]; then + info " -> Downloading Boost archive" + wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION//./_}.tar.gz + else + info " -> Using existing Boost archive" + fi + + info " -> Verifying Boost archive checksum" + determinedChecksum=$(sha256sum boost_${BOOST_VERSION//./_}.tar.gz | awk '{ print $1 }') + info " Expected checksum: ${BOOST_ARCHIVE_HASH}" + info " Determined checksum: ${determinedChecksum}" + if [[ "${BOOST_ARCHIVE_HASH}" != "${determinedChecksum}" ]] ; then + die 2 " => Checksum of downloaded Boost archive not matching expected value!" + else + info " -> Checksum OK" + fi +} + +buildBoost() { + info " -> Building Boost on ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Cleanup before extraction" + rm -rf boost_${BOOST_VERSION//./_} + info " -> Extracting Boost archive" + tar xzf ${BOOST_ARCHIVE_LOCATION}/boost_${BOOST_VERSION//./_}.tar.gz + info " -> Building Boost" + cd boost_${BOOST_VERSION//./_} || die 1 "Unable to cd into boost_${BOOST_VERSION//./_}" + "${ownLocation}"/build-boost-for-android.sh -v ${BOOST_VERSION} -a ${ANDROID_ARCH} -p ${ANDROID_API} -n ${ANDROID_NDK_ROOT} -l "${BOOST_REQUIRED_LIBS// /,}" + cd "${currentDir}" || die 1 "Unable to cd into ${currentDir}" +} + +checkBoost() { + info "" + info "Boost:" + info " -> Searching required static Boost libs" + BOOST_ROOT=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_} + BOOST_INCLUDEDIR=${BOOST_ROOT}/include + BOOST_LIBRARYDIR=${BOOST_ROOT}/lib + boostBuildRequired=false + if [[ -d ${BOOST_LIBRARYDIR} ]]; then + for currentBoostDependency in ${BOOST_REQUIRED_LIBS}; do + if [[ -e ${BOOST_LIBRARYDIR}/libboost_${currentBoostDependency}.a ]]; then + info " -> ${currentBoostDependency}: OK" + else + warning " => ${currentBoostDependency}: Not found!" + boostBuildRequired=true + fi + done + else + warning " => Boost library directory ${BOOST_LIBRARYDIR} not found!" + boostBuildRequired=true + fi + if ${boostBuildRequired} ; then + checkBoostArchive + buildBoost + else + info " => All Boost requirements found" + fi +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${ANDROID_QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + for currentQtDependency in ${QT_REQUIRED_LIBS}; do + if [[ -n $(find ${ANDROID_QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}_${ANDROID_ABI}.so") ]]; then + info " -> ${currentQtDependency}: OK" + else + warning " -> ${currentQtDependency}: Not found!" + qtComponentMissing=true + fi + done + else + info " -> Qt library directory ${ANDROID_QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION}: Not all required components found!" + error "" + die 43 "Stopping build because of missing Qt" + + # Maybe used later: Build Qt ourself + local currentDir=$(pwd) + if [[ ! -e ${QT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${QT_ARCHIVE_LOCATION} + fi + cd ${QT_ARCHIVE_LOCATION} + if [[ ! -e "qt-everywhere-src-${QT_VERSION}.tar.xz" ]]; then + info " -> Downloading Qt archive" + wget https://download.qt.io/archive/qt/${QT_VERSION%.*}/${QT_VERSION}/single/qt-everywhere-src-${QT_VERSION}.tar.xz + else + info " -> Using existing Qt archive" + fi + info " -> Verifying archive checksum" + determinedMD5Sum=$(md5sum qt-everywhere-src-${QT_VERSION}.tar.xz | cut -d ' ' -f 1) + if [[ "${determinedMD5Sum}" != "${QT_ARCHIVE_HASH}" ]]; then + warning " => Checksum of downloaded archive not matching expected value of ${QT_ARCHIVE_HASH}: ${determinedMD5Sum}" + else + info " -> Archive checksum ok" + fi + info " -> Cleanup before extraction" + rm -rf qt-everywhere-src-${QT_VERSION} + info " -> Extracting Qt archive" + tar xf qt-everywhere-src-${QT_VERSION}.tar.xz + info " -> Configuring Qt build" + cd qt-everywhere-src-${QT_VERSION} + ./configure \ + -xplatform android-clang \ + --disable-rpath \ + -nomake tests \ + -nomake examples \ + -android-ndk ${ANDROID_NDK_ROOT} \ + -android-sdk ${ANDROID_SDK_ROOT} \ + -android-arch ${ANDROID_ABI} \ + -android-ndk-platform android-${ANDROID_API} \ + -no-warnings-are-errors \ + -opensource \ + -confirm-license \ + -silent \ + -prefix ${ANDROID_QT_INSTALLATION_DIR} || die 23 "Error during Qt configure step" + info " -> Building Qt" + make -j"${CORES_TO_USE}" || die 24 "Error during Qt build step" + info " -> Installing Qt" + make install || die 25 "Error during Qt install step" + cd "${currentDir}" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a, skip build" + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz" + else + # TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + TOR_ARCHIVE_URL=https://github.com/guardianproject/tor/archive/tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} -O tor-${TOR_BUILD_VERSION_ANDROID}.tar.gz + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of NDK functions =============================================== +checkNDKArchive() { + info "" + info "NDK:" + info " -> Searching Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE}" + if [[ -e ${ANDROID_TOOLCHAIN_CMAKE} ]]; then + info " -> Found it! :-)" + else + warning " -> Android toolchain file ${ANDROID_TOOLCHAIN_CMAKE} not found!" + local currentDir=$(pwd) + if [[ ! -e ${ANDROID_NDK_ARCHIVE_LOCATION} ]]; then + mkdir -p ${ANDROID_NDK_ARCHIVE_LOCATION} + fi + cd ${ANDROID_NDK_ARCHIVE_LOCATION} + if [[ -e "${ANDROID_NDK_ARCHIVE}" ]]; then + info " -> Using existing NDK archive" + else + ANDROID_NDK_ARCHIVE_URL=https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE} + info " -> Downloading NDK archive ${ANDROID_NDK_ARCHIVE_URL}" + wget ${ANDROID_NDK_ARCHIVE_URL} + fi + info " -> Cleanup before extraction" + rm -rf android-ndk-${ANDROID_NDK_VERSION} + info " -> Extracting NDK archive" + unzip ${ANDROID_NDK_ARCHIVE} + cd - >/dev/null + fi +} +# ===== End of NDK functions ================================================= + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) + ANDROID_NDK_ARCHIVE=android-ndk-${ANDROID_NDK_VERSION}-darwin-x86_64.zip +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +GIVEN_DEPENDENCIES_BUILD_DIR='' + +while getopts a:c:dfgop:th? option; do + case ${option} in + a) ANDROID_TOOLCHAIN_CMAKE="${OPTARG}" ;; + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) + ENABLE_GUI=true + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${ANDROID_QT_LIBRARYDIR}/cmake" + ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkNDKArchive +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +fi +if ${ENABLE_GUI}; then + checkQt +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" +read -r -d '' cmd < Finished" +else + error " => Finished with return code ${rtc}" +fi +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/cmake-build-mac.sh b/scripts/cmake-build-mac.sh new file mode 100755 index 0000000000..2945faf452 --- /dev/null +++ b/scripts/cmake-build-mac.sh @@ -0,0 +1,946 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-10 HLXEasy +# +# This script can be used to build Alias on and for Mac using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## +##### ### # Mac Qt # ### #################################################### +if [[ -z "${MAC_QT_DIR}" ]]; then + MAC_QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION_MAC}/clang_64 +fi + +MAC_QT_LIBRARYDIR=${MAC_QT_DIR}/lib + +##### ### # Boost # ### ##################################################### +# Trying to find required Homebrew Boost libs +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # Qt # ### ######################################################## +# Location of Qt will be resolved by trying to find required Qt libs +QT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Qt +QT_REQUIRED_LIBS='Core Widgets WebView WebChannel WebSockets QuickWidgets Quick Gui Qml Network' + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor +TOR_RESOURCE_ARCHIVE=Tor.libraries.MacOS.zip + +BUILD_DIR=cmake-build-cmdline-mac + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + LevelDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -t Build with included Tor + -h Show this help + + " +} + +# ===== Start of homebrew functions ========================================== +checkHomebrew() { + info "" + info "Homebrew:" + if homebrewVersion=$(brew --version 2>/dev/null) ; then + # Show only the first line of the version output + info " -> Found ${homebrewVersion/$'\n'*/}" + else + error " -> Homebrew not found!" + error " You need to install homebrew and after that BerkeleyDB v4, Boost and OpenSSL:" + error " brew install berkeley-db@4 boost openssl" + error "" + die 40 "Stopping build because of missing Homebrew" + fi +} +# ===== End of homebrew functions ============================================ + +# ============================================================================ + +# ===== Start of openssl functions =========================================== +checkOpenSSL() { + info "" + info "OpenSSL:" + info " -> Searching required Homebrew OpenSSL package" + local opensslVersion + opensslVersion=$(brew ls --versions openssl) + if [[ $? -eq 0 ]]; then + info " -> Found ${opensslVersion}" + OPENSSL_VERSION_MAC=$(echo "${opensslVersion#* }" | xargs) + OPENSSL_FOLDERNAME=$(echo "${opensslVersion% *}" | xargs) + else + error " -> Required OpenSSL dependency not found!" + error " You need to install homebrew and install OpenSSL:" + error " brew install openssl" + error "" + die 41 "Stopping build because of missing OpenSSL" + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + info " -> Searching required Homebrew BerkeleyDB package" + local berkeleydbVersion + berkeleydbVersion=$(brew ls --versions berkeley-db@4) + if [[ $? -eq 0 ]]; then + info " -> Found ${berkeleydbVersion}" + else + error " -> Required BerkeleyDB dependency not found!" + error " You need to install homebrew and install BerkeleyDB v4:" + error " brew install berkeley-db@4" + error "" + die 41 "Stopping build because of missing BerkeleyDB" + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoost() { + info "" + info "Boost:" + info " -> Searching required Homebrew Boost package" + local boostVersion + boostVersion=$(brew ls --versions boost) + if [[ $? -eq 0 ]]; then + info " -> Found ${boostVersion}" + if [[ -z "${BOOST_VERSION_MAC}" ]]; then + # Use only version from "boost 1.2.3" and trim potential whitespaces + BOOST_VERSION_MAC=$(echo "${boostVersion#* }" | xargs) + fi + else + error " -> Required Boost dependencies not found!" + error " You need to install homebrew and install Boost:" + error " brew install boost" + error "" + die 42 "Stopping build because of missing Boost" + fi + BOOST_INCLUDEDIR="/usr/local/Cellar/boost/${BOOST_VERSION_MAC}/include" + BOOST_LIBRARYDIR="/usr/local/Cellar/boost/${BOOST_VERSION_MAC}/lib" +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${MAC_QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + # for currentQtDependency in ${QT_REQUIRED_LIBS} ; do + # if [[ -n $(find ${MAC_QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}*") ]] ; then + # info " -> ${currentQtDependency}: OK" + # else + # warning " -> ${currentQtDependency}: Not found!" + # qtComponentMissing=true + # fi + # done + info " -> Found Qt library directory ${MAC_QT_LIBRARYDIR}" + info " Detailed check for required libs needs to be implemented" + else + info " -> Qt library directory ${MAC_QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION_MAC} not found!" + error " You need to install Qt ${QT_VERSION_MAC}" + error "" + die 43 "Stopping build because of missing Qt component(s)" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libleveldb build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/local/lib/libleveldb.a, skip build" + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of wget functions =========================================== +checkWget() { + info "" + info "Wget:" + info " -> Searching required Homebrew wget package" + local wgetVersion + wgetVersion=$(brew ls --versions wget) + if [[ $? -eq 0 ]]; then + info " -> Found ${wgetVersion}" + else + error " -> Required wget dependency not found!" + error " You need to install homebrew and install wget:" + error " brew install wget" + error "" + die 41 "Stopping build because of missing wget" + fi +} +# ===== End of wget functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" + else + TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} + +checkTorMacArchive() { + info "" + info "Tor:" + if [[ -e "${TOR_ARCHIVE_LOCATION}/${TOR_RESOURCE_ARCHIVE}" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/${TOR_RESOURCE_ARCHIVE}" + else + TOR_ARCHIVE_URL=https://github.com/aliascash/resources/raw/master/resources/${TOR_RESOURCE_ARCHIVE} + info " -> Downloading Tor archive ${TOR_RESOURCE_ARCHIVE}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} + cd - >/dev/null + fi +} +# ===== End of tor functions ================================================= + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +GIVEN_DEPENDENCIES_BUILD_DIR='' + +while getopts c:dfgop:th? option; do + case ${option} in + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) + ENABLE_GUI=true + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${MAC_QT_LIBRARYDIR}/cmake" + ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkHomebrew +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +checkWget +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +else + checkTorMacArchive +fi +if ${ENABLE_GUI}; then + checkQt +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" +read -r -d '' cmd < Finished" +else + die 50 " => Failed with return code ${rtc}" +fi + +# Debug build: +#DEPLOY_QT_BINARY_TYPE_OPTION="-use-debug-libs" +DEPLOY_QT_BINARY_TYPE_OPTION='' + +if [[ -e ${MAC_QT_DIR}/bin/macdeployqt ]] ; then + info "" + info "Creating dmg:" + cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into ${ALIAS_BUILD_DIR}" + ${MAC_QT_DIR}/bin/macdeployqt \ + Alias.app \ + -qmldir="${ownLocation}"/../src/qt/res \ + -always-overwrite \ + -verbose=1 \ + "${DEPLOY_QT_BINARY_TYPE_OPTION}" + ${MAC_QT_DIR}/bin/macdeployqt \ + Alias.app \ + -dmg \ + -always-overwrite \ + -verbose=1 + info " -> Alias.dmg created" +else + die 23 "${MAC_QT_DIR}/bin/macdeployqt not found, unable to create dmg!" +fi + +info "" +info "Performing post build steps:" +info "============================" + +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" +cp Alias.dmg Alias.dmg.bak + +info "Change permision of .dmg file" +hdiutil convert "Alias.dmg" -format UDRW -o "Alias_Rw.dmg" +info " -> Done" + +info "Mount it and save the device" +PATH_AT_VOLUME=/Volumes/Alias +DEVICE=$(hdiutil attach -readwrite -noverify "Alias_Rw.dmg" | grep ${PATH_AT_VOLUME} | awk '{print $1}') +info " -> Done (${DEVICE})" + +sleep 2 + +info "Create symbolic link to application folder" +pushd "$PATH_AT_VOLUME" +ln -s /Applications +popd +info " -> Done" + +info "Copy background image in to package" +mkdir "$PATH_AT_VOLUME"/.background +cp "${ownLocation}"/../src/osx/app-slide-arrow.png "$PATH_AT_VOLUME"/.background/ +info " -> Done" + +info "Resize window, set background, change icon size, place icons in the right position, etc." +echo ' + tell application "Finder" + tell disk "Alias" ## check Path inside cd /Volume/ + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set the bounds of container window to {400, 100, 1200, 520} + set viewOptions to the icon view options of container window + set arrangement of viewOptions to not arranged + set icon size of viewOptions to 200 + set text size of viewOptions to 16 + set background picture of viewOptions to file ".background:app-slide-arrow.png" + set position of item "Alias.app" of container window to {180, 200} + set position of item "Applications" of container window to {620, 200} + close + open + update without registering applications + delay 2 + end tell + end tell +' | osascript +info " -> Done" + +sync + +info "Unmount" +hdiutil detach "${DEVICE}" +info " -> Done" + +info "Cleanup and convert" +rm -f "Alias.dmg" +hdiutil convert "Alias_Rw.dmg" -format UDZO -o "Alias.dmg" +rm -f "Alias_Rw.dmg" +info " -> Done" + +info " -> Finished: ${ALIAS_BUILD_DIR}/Alias.dmg" + +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/cmake-build-win-x86.bat b/scripts/cmake-build-win-x86.bat new file mode 100644 index 0000000000..66ba2ad70b --- /dev/null +++ b/scripts/cmake-build-win-x86.bat @@ -0,0 +1,113 @@ +:: =========================================================================== +:: +:: SPDX-FileCopyrightText: © 2025 ALIAS Developers +:: SPDX-FileCopyrightText: © 2020 Alias Developers +:: SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +:: SPDX-License-Identifier: MIT +:: +:: Created: 2019-10-22 HLXEasy +:: +:: Helper script to build Alias on Windows using VS2019 and QT. +:: +:: =========================================================================== + +@echo off +setlocal enabledelayedexpansion + +:: Check for required environment variables +IF "%QTDIR_x86%" == "" GOTO NOQT +:YESQT + +IF "%VSDIR%" == "" GOTO NOVS +:YESVS + +IF "%CMAKEDIR_x86%" == "" GOTO NOCMAKE +:YESVS + +IF "%VCPKGDIR%" == "" GOTO NOVCPKG +:YESVS + +:: Set up directory paths +set "SRC_DIR=%cd%" +set "BUILD_DIR=%cd%\build-x86" + +:: Initialize Visual Studio environment (32-bit) +:: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" +call "%VSDIR%\VC\Auxiliary\Build\vcvars32.bat" +if errorlevel 1 ( + echo Failed to initialize Visual Studio environment + endlocal + exit /b 1 +) + +cd +cd "%SRC_DIR%" +if errorlevel 1 ( + echo Failed to change to source directory: %SRC_DIR% + endlocal + exit /b 1 +) +dir + +echo on + +:: Clean and prepare build directory +if exist "%BUILD_DIR%\delivery" ( + rmdir /S /Q "%BUILD_DIR%\delivery" + if errorlevel 1 ( + echo Warning: Failed to remove delivery directory + ) +) +if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" +if errorlevel 1 goto :ERROR + +cd "%BUILD_DIR%" +if errorlevel 1 goto :ERROR + +:: Configure CMake for 32-bit build +"%CMAKEDIR_x86%\cmake.exe" -D CMAKE_TOOLCHAIN_FILE="%VCPKGDIR%\scripts\buildsystems\vcpkg.cmake" -D CMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER -D CMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER -D ENABLE_GUI=ON -D QT_CMAKE_MODULE_PATH="%QTDIR_x86%\lib\cmake" -D CMAKE_BUILD_TYPE=Release -G "Visual Studio 16 2019" -A Win32 .. +if errorlevel 1 goto :ERROR + +:: Build the project +"%CMAKEDIR_x86%\cmake.exe" --build . --target Aliaswallet --config Release +if errorlevel 1 goto :ERROR + +::ren "%OUT_DIR%" Alias +::echo "The prepared package is in: %BUILD_DIR%\delivery" + +echo "Everything is OK" +GOTO END + +:ERROR +echo Failed with error #%errorlevel%. +cd "%SRC_DIR%" +endlocal +exit /b %errorlevel% +GOTO END + +:NOVCPKG +@ECHO The VCPKGDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOCMAKE +@ECHO The CMAKEDIR_x86 environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOVS +@ECHO The VSDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOQT +@ECHO The QTDIR_x86 environment variable was NOT detected! +endlocal +exit /b 1 + +:END +cd "%SRC_DIR%" +endlocal diff --git a/scripts/cmake-build-win.bat b/scripts/cmake-build-win.bat new file mode 100644 index 0000000000..4c40c7ede2 --- /dev/null +++ b/scripts/cmake-build-win.bat @@ -0,0 +1,113 @@ +:: =========================================================================== +:: +:: SPDX-FileCopyrightText: © 2025 ALIAS Developers +:: SPDX-FileCopyrightText: © 2020 Alias Developers +:: SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +:: SPDX-License-Identifier: MIT +:: +:: Created: 2019-10-22 HLXEasy +:: +:: Helper script to build Alias on Windows using VS2019 and QT. +:: +:: =========================================================================== + +@echo off +setlocal enabledelayedexpansion + +:: Check for required environment variables +IF "%QTDIR%" == "" GOTO NOQT +:YESQT + +IF "%VSDIR%" == "" GOTO NOVS +:YESVS + +IF "%CMAKEDIR%" == "" GOTO NOCMAKE +:YESVS + +IF "%VCPKGDIR%" == "" GOTO NOVCPKG +:YESVS + +:: Set up directory paths +set "SRC_DIR=%cd%" +set "BUILD_DIR=%cd%\build" + +:: Initialize Visual Studio environment +:: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" +call "%VSDIR%\VC\Auxiliary\Build\vcvars64.bat" +if errorlevel 1 ( + echo Failed to initialize Visual Studio environment + endlocal + exit /b 1 +) + +cd +cd "%SRC_DIR%" +if errorlevel 1 ( + echo Failed to change to source directory: %SRC_DIR% + endlocal + exit /b 1 +) +dir + +echo on + +:: Clean and prepare build directory +if exist "%BUILD_DIR%\delivery" ( + rmdir /S /Q "%BUILD_DIR%\delivery" + if errorlevel 1 ( + echo Warning: Failed to remove delivery directory + ) +) +if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" +if errorlevel 1 goto :ERROR + +cd "%BUILD_DIR%" +if errorlevel 1 goto :ERROR + +:: Configure CMake +"%CMAKEDIR%\cmake.exe" -D CMAKE_TOOLCHAIN_FILE="%VCPKGDIR%\scripts\buildsystems\vcpkg.cmake" -D CMAKE_FIND_ROOT_PATH_MODE_LIBRARY=NEVER -D CMAKE_FIND_ROOT_PATH_MODE_INCLUDE=NEVER -D ENABLE_GUI=ON -D QT_CMAKE_MODULE_PATH="%QTDIR%\lib\cmake" -D CMAKE_BUILD_TYPE=Release .. +if errorlevel 1 goto :ERROR + +:: Build the project +"%CMAKEDIR%\cmake.exe" --build . --target Aliaswallet --config Release +if errorlevel 1 goto :ERROR + +::ren "%OUT_DIR%" Alias +::echo "The prepared package is in: %BUILD_DIR%\delivery" + +echo "Everything is OK" +GOTO END + +:ERROR +echo Failed with error #%errorlevel%. +cd "%SRC_DIR%" +endlocal +exit /b %errorlevel% +GOTO END + +:NOVCPKG +@ECHO The VCPKGDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOCMAKE +@ECHO The CMAKEDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOVS +@ECHO The VSDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOQT +@ECHO The QTDIR environment variable was NOT detected! +endlocal +exit /b 1 + +:END +cd "%SRC_DIR%" +endlocal diff --git a/scripts/cmake-build.sh b/scripts/cmake-build.sh new file mode 100755 index 0000000000..c6c7be2faa --- /dev/null +++ b/scripts/cmake-build.sh @@ -0,0 +1,1101 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-10 HLXEasy +# +# This script can be used to build Alias using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## + +##### ### # Boost # ### ##################################################### +# Location of Boost will be resolved by trying to find required Boost libs +BOOST_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Boost +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # BerkeleyDB # ### ################################################ +# Location of archive will be resolved like this: +# ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz +BERKELEYDB_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/BerkeleyDB + +##### ### # OpenSSL # ### ################################################### +# Location of archive will be resolved like this: +# ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz +#OPENSSL_ARCHIVE_LOCATION=https://mirror.viaduck.org/openssl +OPENSSL_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/OpenSSL + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor + +BUILD_DIR=cmake-build-cmdline + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + BerkeleyDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -s Use Qt from system + -t Build with included Tor + -h Show this help + + " +} + +# ===== Determining used distribution ======================================== +defineQtVersionForCurrentDistribution() { + info "" + info "Determining distribution:" + if [[ -e /etc/os-release ]]; then + . /etc/os-release + usedDistro='' + releaseName='' + case ${ID} in + "centos") + usedDistro="CENTOS" + case ${VERSION_ID} in + "8") + releaseName='8' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + ;; + esac + ;; + "debian") + usedDistro="DEBIAN" + case ${VERSION_ID} in + "9") + releaseName='STRETCH' + ;; + "10") + releaseName='BUSTER' + ;; + *) + case ${PRETTY_NAME} in + *"bullseye"*) + echo "Detected ${PRETTY_NAME}, installing Buster binaries" + releaseName='BUSTER' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + cat /etc/os-release + exit 1 + ;; + esac + ;; + esac + ;; + "ubuntu") + usedDistro="UBUNTU" + case ${VERSION_CODENAME} in + "bionic" | "cosmic") + releaseName='1804' + ;; + "disco") + releaseName='1904' + ;; + "eoan") + releaseName='1910' + ;; + "focal") + releaseName='2004' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_CODENAME}" + exit + ;; + esac + ;; + "fedora") + usedDistro="FEDORA" + ;; + "opensuse-tumbleweed") + usedDistro="OPENSUSE" + releaseName="TUMBLEWEED" + ;; + "raspbian") + usedDistro="RASPBERRY" + case ${VERSION_ID} in + "9") + releaseName='STRETCH' + ;; + "10") + releaseName='BUSTER' + ;; + *) + case ${PRETTY_NAME} in + *"bullseye"*) + echo "Detected ${PRETTY_NAME}, installing Buster binaries" + releaseName='BUSTER' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + cat /etc/os-release + exit 1 + ;; + esac + ;; + esac + ;; + *) + echo "Unsupported operating system ${ID}, VERSION_ID=${VERSION_ID}" + exit + ;; + esac + + # https://stackoverflow.com/questions/16553089/dynamic-variable-names-in-bash + defineQtVersionToUse=QT_VERSION_TO_USE + printf -v "$defineQtVersionToUse" '%s' "QT_VERSION_${usedDistro}_${releaseName}" + + # https://unix.stackexchange.com/questions/452723/is-it-possible-to-print-the-content-of-the-content-of-a-variable-with-shell-scri + QT_VERSION="${!QT_VERSION_TO_USE}" + QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION}/gcc_64 + QT_LIBRARYDIR=${QT_DIR}/lib + + info " -> Determined ${usedDistro} ${releaseName}, using Qt ${QT_VERSION}" + else + die 100 "Unable to determine used Linux distribution" + fi +} + +# ===== Start of openssl functions =========================================== +checkOpenSSLArchive() { + if [[ -e "${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using OpenSSL archive ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + else + OPENSSL_ARCHIVE_URL="https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + info " -> Downloading OpenSSL archive ${OPENSSL_ARCHIVE_URL}" + if [[ ! -e "${OPENSSL_ARCHIVE_LOCATION}" ]]; then + mkdir -p "${OPENSSL_ARCHIVE_LOCATION}" + fi + cd "${OPENSSL_ARCHIVE_LOCATION}" + wget "${OPENSSL_ARCHIVE_URL}" + cd - >/dev/null + fi +} + +# For OpenSSL we're using a fork of https://github.com/viaduck/openssl-cmake +# with some slight modifications for Alias +checkOpenSSLClone() { + local currentDir + currentDir=$(pwd) + cd "${ownLocation}/../external" + if [[ -d openssl-cmake ]]; then + info " -> Updating openssl-cmake clone" + cd openssl-cmake + git pull --prune + else + info " -> Cloning openssl-cmake" + git clone --branch alias https://github.com/aliascash/openssl-cmake.git openssl-cmake + fi + cd "${currentDir}" +} + +checkOpenSSLBuild() { + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished openssl build and install" + else + die ${rtc} " => OpenSSL build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkOpenSSL() { + info "" + info "OpenSSL:" + if [[ -f "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a" ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a, skip build" + else + checkOpenSSLArchive + checkOpenSSLClone + checkOpenSSLBuild + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDBArchive() { + if [[ -e "${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using BerkeleyDB archive ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" + else + BERKELEYDB_ARCHIVE_URL=https://download.oracle.com/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + info " -> Downloading BerkeleyDB archive ${BERKELEYDB_ARCHIVE_URL}" + if [[ ! -e ${BERKELEYDB_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BERKELEYDB_ARCHIVE_LOCATION} + fi + cd ${BERKELEYDB_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BERKELEYDB_ARCHIVE_LOCATION}" + wget ${BERKELEYDB_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkBerkeleyDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished BerkeleyDB (libdb) build and install" + else + die ${rtc} " => BerkeleyDB (libdb) build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a, skip build" + else + checkBerkeleyDBArchive + checkBerkeleyDBBuild + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoostArchive() { + local currentDir=$(pwd) + if [[ ! -e ${BOOST_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BOOST_ARCHIVE_LOCATION} + fi + cd ${BOOST_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BOOST_ARCHIVE_LOCATION}" + if [[ ! -e "boost_${BOOST_VERSION//./_}.tar.gz" ]]; then + info " -> Downloading Boost archive" + wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION//./_}.tar.gz + else + info " -> Using existing Boost archive" + fi + + info " -> Verifying Boost archive checksum" + determinedChecksum=$(sha256sum boost_${BOOST_VERSION//./_}.tar.gz | awk '{ print $1 }') + info " Expected checksum: ${BOOST_ARCHIVE_HASH}" + info " Determined checksum: ${determinedChecksum}" + if [[ "${BOOST_ARCHIVE_HASH}" != "${determinedChecksum}" ]] ; then + die 2 " => Checksum of downloaded Boost archive not matching expected value!" + else + info " -> Checksum OK" + fi +} + +buildBoost() { + info " -> Building Boost on ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Cleanup before extraction" + rm -rf boost_${BOOST_VERSION//./_} + info " -> Extracting Boost archive" + tar xzf ${BOOST_ARCHIVE_LOCATION}/boost_${BOOST_VERSION//./_}.tar.gz + info " -> Building Boost" + cd boost_${BOOST_VERSION//./_} || die 1 "Unable to cd into boost_${BOOST_VERSION//./_}" + ./bootstrap.sh --with-libraries="${BOOST_REQUIRED_LIBS// /,}" + # ./bootstrap.sh + ./b2 \ + -j"${CORES_TO_USE}" \ + --layout=tagged \ + --build-type=complete + cd "${currentDir}" || die 1 "Unable to cd into ${currentDir}" +} + +checkBoost() { + info "" + info "Boost:" + info " -> Searching required static Boost libs" + BOOST_INCLUDEDIR=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_} + BOOST_LIBRARYDIR=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_}/stage/lib + boostBuildRequired=false + if [[ -d ${BOOST_LIBRARYDIR} ]]; then + for currentBoostDependency in ${BOOST_REQUIRED_LIBS}; do + if [[ -e ${BOOST_LIBRARYDIR}/libboost_${currentBoostDependency}-mt-${LIB_ARCH_SUFFIX}.a ]]; then + info " -> ${currentBoostDependency}: OK" + else + warning " => ${currentBoostDependency}: Not found!" + boostBuildRequired=true + fi + done + else + warning " => Boost library directory ${BOOST_LIBRARYDIR} not found!" + boostBuildRequired=true + fi + if ${boostBuildRequired} ; then + checkBoostArchive + buildBoost + else + info " => All Boost requirements found" + fi +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + for currentQtDependency in ${QT_REQUIRED_LIBS}; do + if [[ -n $(find ${QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}.so") ]]; then + info " -> ${currentQtDependency}: OK" + else + warning " -> ${currentQtDependency}: Not found!" + qtComponentMissing=true + fi + done + else + info " -> Qt library directory ${QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION}: Not all required components found!" + error "" + die 43 "Stopping build because of missing Qt component(s)" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Using ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a" + LIB_LEVELDB_LOCATION=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/cmake/leveldb + elif [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/libleveldb.a ]]; then + info " -> Using ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/libleveldb.a" + LIB_LEVELDB_LOCATION=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/cmake/leveldb + else + die 23 " => libleveldb build result not found!" + fi + + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a, skip build" + LIB_LEVELDB_LOCATION=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/cmake/leveldb + elif [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/libleveldb.a, skip build" + LIB_LEVELDB_LOCATION=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib64/cmake/leveldb + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" + else + TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi +# Determine arch +LIB_ARCH_SUFFIX=x64 +if [[ "$(uname -m)" == "aarch64" ]]; then + LIB_ARCH_SUFFIX=a64 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +SYSTEM_QT=false +LIB_LEVELDB_LOCATION='' +GIVEN_DEPENDENCIES_BUILD_DIR='' + +defineQtVersionForCurrentDistribution + +while getopts c:dfgop:sth? option; do + case ${option} in + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) ENABLE_GUI=true ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + s) SYSTEM_QT=true ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# If GUI should be build, set proper parameters +if ${ENABLE_GUI}; then + if ${SYSTEM_QT}; then + ENABLE_GUI_PARAMETERS="ON" + else + checkQt + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${QT_LIBRARYDIR}/cmake" + fi +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" + +# FindBerkeleyDB.cmake requires this +export BERKELEYDB_ROOT=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install + +read -r -d '' cmd < Finished" +else + error " => Finished with return code ${rtc}" +fi +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/cmake-build_x86.sh b/scripts/cmake-build_x86.sh new file mode 100755 index 0000000000..df0d504f0f --- /dev/null +++ b/scripts/cmake-build_x86.sh @@ -0,0 +1,1116 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-10-10 HLXEasy +# +# This script can be used to build Alias using CMake +# +# =========================================================================== + +# =========================================================================== +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" || die 1 "Unable to cd into own location ${ownLocation}" +. ./include/helpers_console.sh +_init +. ./include/handle_buildconfig.sh + +##### ### # Global definitions # ### ######################################## + +##### ### # Boost # ### ##################################################### +# Location of Boost will be resolved by trying to find required Boost libs +BOOST_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Boost +BOOST_REQUIRED_LIBS='chrono filesystem iostreams program_options system thread regex date_time atomic' +# regex date_time atomic + +##### ### # BerkeleyDB # ### ################################################ +# Location of archive will be resolved like this: +# ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz +BERKELEYDB_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/BerkeleyDB + +##### ### # OpenSSL # ### ################################################### +# Location of archive will be resolved like this: +# ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz +#OPENSSL_ARCHIVE_LOCATION=https://mirror.viaduck.org/openssl +OPENSSL_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/OpenSSL + +##### ### # EventLib # ### ################################################## +# Location of archive will be resolved like this: +# ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz +LIBEVENT_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/EventLib + +##### ### # ZLib # ### ###################################################### +# Location of archive will be resolved like this: +# ${LIBZ_ARCHIVE_LOCATION}/v${LIBZ_BUILD_VERSION}.tar.gz +LIBZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/ZLib + +##### ### # XZLib # ### ##################################################### +# Location of archive will be resolved like this: +# ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz +LIBXZ_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/XZLib + +##### ### # Tor # ### ####################################################### +# Location of archive will be resolved like this: +# ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz +TOR_ARCHIVE_LOCATION=${ARCHIVES_ROOT_DIR}/Tor + +BUILD_DIR=cmake-build-cmdline-x86 + +helpMe() { + echo " + + Helper script to build Alias wallet and daemon using CMake. + Required library archives will be downloaded once and will be used + on subsequent builds. + + Default download location is ~/Archives. You can change this by + modifying '${ownLocation}/scripts/.buildconfig'. + + Usage: + ${0} [options] + + Optional parameters: + -c + The amount of cores to use for build. If not using this option + the script determines the available cores on this machine. + Not used for build steps of external libraries like OpenSSL or + BerkeleyDB. + -d Do _not_ build Alias but only the dependencies. Used to prepare + build slaves a/o builder docker images. + -f Perform fullbuild by cleanup all generated data from previous + build runs. + -g Build GUI (Qt) components + -o Perfom only Alias fullbuild. Only the alias buildfolder + will be wiped out before. All other folders stay in place. + -p + Build/install the required dependencies onto the given directory. + With this option the required dependencies could be located outside + the Git clone. This is useful + a) to have them only once at the local machine, even if working + with multiple Git clones and + b) to have them separated from the project itself, which is a must + if using Qt Creator. Otherwise Qt Creator always scans and finds + all the other content again and again. + Given value must be an absolute path or relative to the root of the + Git clone. + -s Use Qt from system + -t Build with included Tor + -h Show this help + + " +} + +# ===== Determining used distribution ======================================== +defineQtVersionForCurrentDistribution() { + info "" + info "Determining distribution:" + if [[ -e /etc/os-release ]]; then + . /etc/os-release + usedDistro='' + releaseName='' + case ${ID} in + "centos") + usedDistro="CENTOS" + case ${VERSION_ID} in + "8") + releaseName='8' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + ;; + esac + ;; + "debian") + usedDistro="DEBIAN" + case ${VERSION_ID} in + "9") + releaseName='STRETCH' + ;; + "10") + releaseName='BUSTER' + ;; + *) + case ${PRETTY_NAME} in + *"bullseye"*) + echo "Detected ${PRETTY_NAME}, installing Buster binaries" + releaseName='BUSTER' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + cat /etc/os-release + exit 1 + ;; + esac + ;; + esac + ;; + "ubuntu") + usedDistro="UBUNTU" + case ${VERSION_CODENAME} in + "bionic" | "cosmic") + releaseName='1804' + ;; + "disco") + releaseName='1904' + ;; + "eoan") + releaseName='1910' + ;; + "focal") + releaseName='2004' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_CODENAME}" + exit + ;; + esac + ;; + "fedora") + usedDistro="FEDORA" + ;; + "opensuse-tumbleweed") + usedDistro="OPENSUSE" + releaseName="TUMBLEWEED" + ;; + "raspbian") + usedDistro="RASPBERRY" + case ${VERSION_ID} in + "9") + releaseName='STRETCH' + ;; + "10") + releaseName='BUSTER' + ;; + *) + case ${PRETTY_NAME} in + *"bullseye"*) + echo "Detected ${PRETTY_NAME}, installing Buster binaries" + releaseName='BUSTER' + ;; + *) + echo "Unsupported operating system ID=${ID}, VERSION_ID=${VERSION_ID}" + cat /etc/os-release + exit 1 + ;; + esac + ;; + esac + ;; + *) + echo "Unsupported operating system ${ID}, VERSION_ID=${VERSION_ID}" + exit + ;; + esac + + # https://stackoverflow.com/questions/16553089/dynamic-variable-names-in-bash + defineQtVersionToUse=QT_VERSION_TO_USE + printf -v "$defineQtVersionToUse" '%s' "QT_VERSION_${usedDistro}_${releaseName}" + + # https://unix.stackexchange.com/questions/452723/is-it-possible-to-print-the-content-of-the-content-of-a-variable-with-shell-scri + QT_VERSION="${!QT_VERSION_TO_USE}" + QT_DIR=${QT_INSTALLATION_PATH}/${QT_VERSION}/gcc_64 + QT_LIBRARYDIR=${QT_DIR}/lib + + info " -> Determined ${usedDistro} ${releaseName}, using Qt ${QT_VERSION}" + else + die 100 "Unable to determine used Linux distribution" + fi +} + +# ===== Start of openssl functions =========================================== +checkOpenSSLArchive() { + if [[ -e "${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using OpenSSL archive ${OPENSSL_ARCHIVE_LOCATION}/openssl-${OPENSSL_BUILD_VERSION}.tar.gz" + else + OPENSSL_ARCHIVE_URL=https://mirror.viaduck.org/openssl/openssl-${OPENSSL_BUILD_VERSION}.tar.gz + info " -> Downloading OpenSSL archive ${OPENSSL_ARCHIVE_URL}" + if [[ ! -e ${OPENSSL_ARCHIVE_LOCATION} ]]; then + mkdir -p ${OPENSSL_ARCHIVE_LOCATION} + fi + cd ${OPENSSL_ARCHIVE_LOCATION} + wget ${OPENSSL_ARCHIVE_URL} + cd - >/dev/null + fi +} + +# For OpenSSL we're using a fork of https://github.com/viaduck/openssl-cmake +# with some slight modifications for Alias +checkOpenSSLClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d openssl-cmake ]]; then + info " -> Updating openssl-cmake clone" + cd openssl-cmake + git pull --prune + else + info " -> Cloning openssl-cmake" + git clone --branch alias https://github.com/aliascash/openssl-cmake.git openssl-cmake + fi + cd "${currentDir}" +} + +checkOpenSSLBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/openssl" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished openssl build and install" + else + die ${rtc} " => OpenSSL build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkOpenSSL() { + info "" + info "OpenSSL:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libssl.a, skip build" + else + checkOpenSSLArchive + checkOpenSSLClone + checkOpenSSLBuild + fi +} +# ===== End of openssl functions ============================================= + +# ============================================================================ + +# ===== Start of berkeleydb functions ======================================== +checkBerkeleyDBArchive() { + if [[ -e "${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using BerkeleyDB archive ${BERKELEYDB_ARCHIVE_LOCATION}/db-${BERKELEYDB_BUILD_VERSION}.tar.gz" + else + BERKELEYDB_ARCHIVE_URL=https://download.oracle.com/berkeley-db/db-${BERKELEYDB_BUILD_VERSION}.tar.gz + info " -> Downloading BerkeleyDB archive ${BERKELEYDB_ARCHIVE_URL}" + if [[ ! -e ${BERKELEYDB_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BERKELEYDB_ARCHIVE_LOCATION} + fi + cd ${BERKELEYDB_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BERKELEYDB_ARCHIVE_LOCATION}" + wget ${BERKELEYDB_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkBerkeleyDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb" + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished BerkeleyDB (libdb) build and install" + else + die ${rtc} " => BerkeleyDB (libdb) build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkBerkeleyDB() { + info "" + info "BerkeleyDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install/lib/libdb.a, skip build" + else + checkBerkeleyDBArchive + checkBerkeleyDBBuild + fi +} +# ===== End of berkeleydb functions ========================================== + +# ============================================================================ + +# ===== Start of boost functions ============================================= +checkBoostArchive() { + local currentDir=$(pwd) + if [[ ! -e ${BOOST_ARCHIVE_LOCATION} ]]; then + mkdir -p ${BOOST_ARCHIVE_LOCATION} + fi + cd ${BOOST_ARCHIVE_LOCATION} || die 1 "Unable to cd into ${BOOST_ARCHIVE_LOCATION}" + if [[ ! -e "boost_${BOOST_VERSION//./_}.tar.gz" ]]; then + info " -> Downloading Boost archive" + wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION//./_}.tar.gz + else + info " -> Using existing Boost archive" + fi + + info " -> Verifying Boost archive checksum" + determinedChecksum=$(sha256sum boost_${BOOST_VERSION//./_}.tar.gz | awk '{ print $1 }') + info " Expected checksum: ${BOOST_ARCHIVE_HASH}" + info " Determined checksum: ${determinedChecksum}" + if [[ "${BOOST_ARCHIVE_HASH}" != "${determinedChecksum}" ]] ; then + die 2 " => Checksum of downloaded Boost archive not matching expected value!" + else + info " -> Checksum OK" + fi +} + +buildBoost() { + info " -> Building Boost on ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Cleanup before extraction" + rm -rf boost_${BOOST_VERSION//./_} + info " -> Extracting Boost archive" + tar xzf ${BOOST_ARCHIVE_LOCATION}/boost_${BOOST_VERSION//./_}.tar.gz + info " -> Building Boost" + cd boost_${BOOST_VERSION//./_} || die 1 "Unable to cd into boost_${BOOST_VERSION//./_}" + ./bootstrap.sh --with-libraries="${BOOST_REQUIRED_LIBS// /,}" + # ./bootstrap.sh + ./b2 -j"${CORES_TO_USE}" + cd "${currentDir}" || die 1 "Unable to cd into ${currentDir}" +} + +checkBoost() { + info "" + info "Boost:" + info " -> Searching required static Boost libs" + BOOST_INCLUDEDIR=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_} + BOOST_LIBRARYDIR=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/boost_${BOOST_VERSION//./_}/stage/lib + boostBuildRequired=false + if [[ -d ${BOOST_LIBRARYDIR} ]]; then + for currentBoostDependency in ${BOOST_REQUIRED_LIBS}; do + if [[ -e ${BOOST_LIBRARYDIR}/libboost_${currentBoostDependency}.a ]]; then + info " -> ${currentBoostDependency}: OK" + else + warning " => ${currentBoostDependency}: Not found!" + boostBuildRequired=true + fi + done + else + warning " => Boost library directory ${BOOST_LIBRARYDIR} not found!" + boostBuildRequired=true + fi + if ${boostBuildRequired} ; then + checkBoostArchive + buildBoost + else + info " => All Boost requirements found" + fi +} +# ===== End of boost functions =============================================== + +# ============================================================================ + +# ===== Start of Qt functions ================================================ +checkQt() { + info "" + info "Qt:" + info " -> Searching required Qt libs" + qtComponentMissing=false + if [[ -d ${QT_LIBRARYDIR} ]]; then + # libQt5Quick.so + for currentQtDependency in ${QT_REQUIRED_LIBS}; do + if [[ -n $(find ${QT_LIBRARYDIR}/ -name "libQt5${currentQtDependency}.so") ]]; then + info " -> ${currentQtDependency}: OK" + else + warning " -> ${currentQtDependency}: Not found!" + qtComponentMissing=true + fi + done + else + info " -> Qt library directory ${QT_LIBRARYDIR} not found" + qtComponentMissing=true + fi + if ${qtComponentMissing}; then + error " -> Qt ${QT_VERSION}: Not all required components found!" + error "" + die 43 "Stopping build because of missing Qt component(s)" + fi +} +# ===== End of Qt functions ================================================== + +# ============================================================================ + +# ===== Start of libevent functions ========================================== +checkEventLibArchive() { + if [[ -e "${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" ]]; then + info " -> Using EventLib archive ${LIBEVENT_ARCHIVE_LOCATION}/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz" + else + LIBEVENT_ARCHIVE_URL=https://github.com/libevent/libevent/releases/download/release-${LIBEVENT_BUILD_VERSION}-stable/libevent-${LIBEVENT_BUILD_VERSION}-stable.tar.gz + info " -> Downloading EventLib archive ${LIBEVENT_ARCHIVE_URL}" + if [[ ! -e ${LIBEVENT_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBEVENT_ARCHIVE_LOCATION} + fi + cd ${LIBEVENT_ARCHIVE_LOCATION} + wget ${LIBEVENT_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkEventLibClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d libevent ]]; then + info " -> Updating libevent clone" + cd libevent + git pull --prune + else + info " -> Cloning libevent" + git clone https://github.com/libevent/libevent.git libevent + fi + cd "${currentDir}" +} + +checkEventLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libevent + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? " => Error during installation of libevent" + else + die ${rtc} " => libevent build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkEventLib() { + info "" + info "EventLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libevent.a, skip build" + else + checkEventLibClone + checkEventLibBuild + fi +} +# ===== End of libevent functions ============================================ + +# ============================================================================ + +# ===== Start of leveldb functions =========================================== +checkLevelDBClone() { + local currentDir=$(pwd) + cd ${ownLocation}/../external + if [[ -d leveldb ]]; then + info " -> Updating LevelDB clone" + cd leveldb + git pull --prune + else + info " -> Cloning LevelDB" + git clone https://github.com/google/leveldb.git leveldb + cd leveldb + fi + info " -> Checkout release ${LEVELDB_VERSION}" + git checkout ${LEVELDB_VERSION_TAG} + cd "${currentDir}" +} + +checkLevelDBBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libleveldb + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libevent build, installing..." + make install || die $? "Error during installation of libleveldb" + else + die ${rtc} " => libleveldb build failed with return code ${rtc}" + fi + # read a + cd - >/dev/null +} + +checkLevelDB() { + info "" + info "LevelDB:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libleveldb.a, skip build" + else + checkLevelDBClone + checkLevelDBBuild + fi +} +# ===== End of leveldb functions ============================================= + +# ============================================================================ + +# ===== Start of libzstd functions =========================================== +checkZStdLibArchive() { + if [[ -e "${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using ZLib archive ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz" + else + LIBZ_ARCHIVE_URL=https://github.com/facebook/zstd/releases/download/v${LIBZ_BUILD_VERSION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + info " -> Downloading ZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBZ_ARCHIVE_LOCATION} + fi + cd ${LIBZ_ARCHIVE_LOCATION} + wget ${LIBZ_ARCHIVE_URL} + cd - >/dev/null + fi + cd ${ownLocation}/../external + if [[ -d libzstd ]]; then + info " -> Directory external/libzstd already existing. Remove it to extract it again" + else + info " -> Extracting zstd-${LIBZ_BUILD_VERSION}.tar.gz..." + tar xzf ${LIBZ_ARCHIVE_LOCATION}/zstd-${LIBZ_BUILD_VERSION}.tar.gz + mv zstd-${LIBZ_BUILD_VERSION} libzstd + fi + cd - >/dev/null +} + +checkZStdLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libzstd + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libzstd build, installing..." + make install || die $? "Error during installation of libzstd" + else + die ${rtc} " => libzstd build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkZStdLib() { + info "" + info "ZStdLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/libzstd.a, skip build" + else + checkZStdLibArchive + checkZStdLibBuild + fi +} +# ===== End of libzstd functions ============================================= + +# ============================================================================ + +# ===== Start of libxz functions ============================================= +checkXZLibArchive() { + if [[ -e "${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using XZLib archive ${LIBXZ_ARCHIVE_LOCATION}/xz-${LIBXZ_BUILD_VERSION}.tar.gz" + else + LIBXZ_ARCHIVE_URL=https://tukaani.org/xz/xz-${LIBXZ_BUILD_VERSION}.tar.gz + info " -> Downloading XZLib archive ${LIBZ_ARCHIVE_URL}" + if [[ ! -e ${LIBXZ_ARCHIVE_LOCATION} ]]; then + mkdir -p ${LIBXZ_ARCHIVE_LOCATION} + fi + cd ${LIBXZ_ARCHIVE_LOCATION} + wget ${LIBXZ_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkXZLibBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libxz + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished libxz build and install" + else + die ${rtc} " => libxz build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkXZLib() { + info "" + info "XZLib:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/lib/liblzma.a, skip build" + else + checkXZLibArchive + checkXZLibBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# ===== Start of tor functions =============================================== +checkTorArchive() { + if [[ -e "${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" ]]; then + info " -> Using Tor archive ${TOR_ARCHIVE_LOCATION}/tor-${TOR_BUILD_VERSION}.tar.gz" + else + TOR_ARCHIVE_URL=https://github.com/torproject/tor/archive/tor-${TOR_BUILD_VERSION}.tar.gz + info " -> Downloading Tor archive ${TOR_ARCHIVE_URL}" + if [[ ! -e ${TOR_ARCHIVE_LOCATION} ]]; then + mkdir -p ${TOR_ARCHIVE_LOCATION} + fi + cd ${TOR_ARCHIVE_LOCATION} + wget ${TOR_ARCHIVE_URL} + cd - >/dev/null + fi +} + +checkTorBuild() { + mkdir -p ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + cd ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/tor + + info " -> Generating build configuration" + read -r -d '' cmd < Building with ${CORES_TO_USE} cores:" + CORES_TO_USE=${CORES_TO_USE} cmake \ + --build . \ + -- \ + -j "${CORES_TO_USE}" + + rtc=$? + info "" + if [[ ${rtc} = 0 ]]; then + info " -> Finished tor build and install" + else + die ${rtc} " => Tor build failed with return code ${rtc}" + fi + + cd - >/dev/null +} + +checkTor() { + info "" + info "Tor:" + if [[ -f ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor ]]; then + info " -> Found ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/usr/local/bin/tor, skip build" + else + checkTorArchive + checkTorBuild + fi +} +# ===== End of libxz functions =============================================== + +# ============================================================================ + +# Determine system +# Determine amount of cores: +if [[ "$OSTYPE" == "linux-gnu" ]]; then + CORES_TO_USE=$(grep -c ^processor /proc/cpuinfo) +elif [[ "$OSTYPE" == "darwin"* ]]; then + # Mac OSX + CORES_TO_USE=$(system_profiler SPHardwareDataType | grep "Total Number of Cores" | tr -s " " | cut -d " " -f 6) +#elif [[ "$OSTYPE" == "cygwin" ]]; then +# # POSIX compatibility layer and Linux environment emulation for Windows +#elif [[ "$OSTYPE" == "msys" ]]; then +# # Lightweight shell and GNU utilities compiled for Windows (part of MinGW) +#elif [[ "$OSTYPE" == "win32" ]]; then +# # I'm not sure this can happen. +#elif [[ "$OSTYPE" == "freebsd"* ]]; then +# CORES_TO_USE=1 +else + CORES_TO_USE=1 +fi + +FULLBUILD=false +ENABLE_GUI=false +ENABLE_GUI_PARAMETERS='OFF' +BUILD_ONLY_ALIAS=false +BUILD_ONLY_DEPENDENCIES=false +WITH_TOR=false +SYSTEM_QT=false +GIVEN_DEPENDENCIES_BUILD_DIR='' + +defineQtVersionForCurrentDistribution + +while getopts c:dfgop:sth? option; do + case ${option} in + c) CORES_TO_USE="${OPTARG}" ;; + d) BUILD_ONLY_DEPENDENCIES=true ;; + f) FULLBUILD=true ;; + g) ENABLE_GUI=true ;; + o) BUILD_ONLY_ALIAS=true ;; + p) GIVEN_DEPENDENCIES_BUILD_DIR="${OPTARG}" ;; + s) SYSTEM_QT=true ;; + t) WITH_TOR=true ;; + h | ?) helpMe && exit 0 ;; + *) die 90 "invalid option \"${OPTARG}\"" ;; + esac +done + +# Go to alias-wallet repository root directory +cd .. + +# ============================================================================ +# Handle given path to dependency location +if [[ -n "${GIVEN_DEPENDENCIES_BUILD_DIR}" ]] ; then + # ${GIVEN_DEPENDENCIES_BUILD_DIR} is set, + # so store given path on build configuration + if [[ "${GIVEN_DEPENDENCIES_BUILD_DIR}" = /* ]]; then + # Absolute path given + DEPENDENCIES_BUILD_DIR=${GIVEN_DEPENDENCIES_BUILD_DIR} + else + # Relative path given + DEPENDENCIES_BUILD_DIR=${ownLocation}/../${GIVEN_DEPENDENCIES_BUILD_DIR} + fi + storeDependenciesBuildDir "${DEPENDENCIES_BUILD_DIR}" +fi + +# ============================================================================ +# If ${DEPENDENCIES_BUILD_DIR} is empty, no path to the dependencies is given +# or stored on script/.buildproperties. In this case use default location +# inside of Git clone +if [[ -z "${DEPENDENCIES_BUILD_DIR}" ]] ; then + DEPENDENCIES_BUILD_DIR=${ownLocation}/.. +fi + +info "" +info "Building/using dependencies on/from directory:" +info " -> ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + +if [[ ! -d ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR} ]]; then + info "" + info "Creating dependency build directory ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + mkdir -p "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" + info " -> Done" +fi + +cd "${DEPENDENCIES_BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}" +DEPENDENCIES_BUILD_DIR=$(pwd) + +# ============================================================================ +# Handle which parts should be build +cd "${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" || die 1 "Unable to cd into ${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}" +if ${FULLBUILD}; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +# ============================================================================ +# If GUI should be build, set proper parameters +if ${ENABLE_GUI}; then + if ${SYSTEM_QT}; then + ENABLE_GUI_PARAMETERS="ON" + else + checkQt + ENABLE_GUI_PARAMETERS="ON -DQT_CMAKE_MODULE_PATH=${QT_LIBRARYDIR}/cmake" + fi +fi + +# ============================================================================ +# Check a/o build requirements/dependencies +checkBoost +checkBerkeleyDB +checkLevelDB +checkOpenSSL +if ${WITH_TOR}; then + checkXZLib + checkZStdLib + checkEventLib + checkTor +fi + +# ============================================================================ +# Only dependencies should be build, so exit here +if ${BUILD_ONLY_DEPENDENCIES}; then + info "" + info "Checked a/o built all required dependencies." + exit +fi + +# ============================================================================ +# Dependencies are ready. Go ahead with the main project +ALIAS_BUILD_DIR=${ownLocation}/../${BUILD_DIR}/aliaswallet +if [[ ! -d ${ALIAS_BUILD_DIR} ]]; then + info "" + info "Creating Alias build directory ${ALIAS_BUILD_DIR}" + mkdir -p "${ALIAS_BUILD_DIR}" + info " -> Done" +fi +cd "${ALIAS_BUILD_DIR}" || die 1 "Unable to cd into Alias build directory '${ALIAS_BUILD_DIR}'" + +# Update $ALIAS_BUILD_DIR with full path +ALIAS_BUILD_DIR=$(pwd) + +# If requested, cleanup leftovers from previous build +if [[ ${FULLBUILD} = true ]] || [[ ${BUILD_ONLY_ALIAS} = true ]]; then + info "" + info "Cleanup leftovers from previous build run" + rm -rf ./* + info " -> Done" +fi + +info "" +info "Generating Alias build configuration" + +# FindBerkeleyDB.cmake requires this +export BERKELEYDB_ROOT=${DEPENDENCIES_BUILD_DIR}/${BUILD_DIR}/libdb/libdb-install + +read -r -d '' cmd < Finished" +else + error " => Finished with return code ${rtc}" +fi +cd "${callDir}" || die 1 "Unable to cd back to where we came from (${callDir})" diff --git a/scripts/createChecksumSummary.sh b/scripts/createChecksumSummary.sh new file mode 100755 index 0000000000..279f27c91c --- /dev/null +++ b/scripts/createChecksumSummary.sh @@ -0,0 +1,55 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-01-22 HLXEasy +# +# Helper script to create checksums for given file (1st parameter) +# and write them into given another file (2nd parameter) +# +# =========================================================================== + +releaseDescription="${1}" +workspace="${2}" +jobURL="${3}" +accessToken="${4}" + +if [[ -e "${releaseDescription}" ]]; then + cp "${releaseDescription}" "${workspace}/releaseNotesToDeploy.txt" +else + echo "### ${releaseDescription}" > "${workspace}/releaseNotesToDeploy.txt" +fi +for currentChecksumfile in \ + Checksum-Alias-Android-APK.txt \ + Checksum-Alias-Android-AAB.txt \ + Checksum-Alias-CentOS-8.txt \ + Checksum-Alias-Debian-Buster.txt \ + Checksum-Alias-Debian-Stretch.txt \ + Checksum-Alias-Fedora.txt \ + Checksum-Alias-OpenSUSE-Tumbleweed.txt \ + Checksum-Alias-Mac.txt \ + Checksum-Alias-Mac-OBFS4.txt \ + Checksum-Alias-RaspberryPi-Buster.txt \ + Checksum-Alias-RaspberryPi-Buster-aarch64.txt \ + Checksum-Alias-RaspberryPi-Stretch.txt \ + Checksum-Alias-Ubuntu-18-04.txt \ + Checksum-Alias-Ubuntu-20-04.txt \ + Checksum-Alias-Win64.txt \ + Checksum-Alias-Win64-OBFS4.txt \ + Checksum-Alias-Win64-Qt5.12.txt \ + Checksum-Alias-Win64-Qt5.12-OBFS4.txt \ + Checksum-Alias-Win64-Qt5.9.6.txt \ + Checksum-Alias-Win64-Qt5.9.6-OBFS4.txt; do + curl -X POST -L --user "${accessToken}" "${jobURL}/artifact/${currentChecksumfile}" --output "${currentChecksumfile}" || true + if [[ -e "${currentChecksumfile}" ]] && [[ $(wc -l < "${currentChecksumfile}") -eq 1 ]]; then + archiveFilename=$(cut -d ' ' -f1 "${currentChecksumfile}") + checksum=$(cut -d ' ' -f2 "${currentChecksumfile}") + echo "**${archiveFilename}:** \`${checksum}\`" >> "${workspace}/releaseNotesToDeploy.txt" + echo '' >> "${workspace}/releaseNotesToDeploy.txt" + fi +done diff --git a/scripts/createChecksums.sh b/scripts/createChecksums.sh new file mode 100755 index 0000000000..489325549b --- /dev/null +++ b/scripts/createChecksums.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-01-22 HLXEasy +# +# Helper script to create checksums for given file (1st parameter) +# and write them into given another file (2nd parameter) +# +# =========================================================================== + +givenFileWithPath="${1}" +checksumfile="/tmp/checksumfile" +if [[ -z "${givenFileWithPath}" ]]; then + echo "No filename given, for which checksums should be created!" + exit 1 +fi +if [[ -n "${2}" ]]; then + checksumfile="${2}" +fi +filename="${givenFileWithPath##*/}" +echo "${filename} $(sha256sum "${givenFileWithPath}" | awk '{ print $1 }')" > "${checksumfile}" diff --git a/scripts/genbuild.sh b/scripts/genbuild.sh new file mode 100755 index 0000000000..2bccfe2662 --- /dev/null +++ b/scripts/genbuild.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# =========================================================================== + +if [[ $# -gt 0 ]]; then + FILE="${1}" + shift + if [[ -f "${FILE}" ]]; then + INFO="$(head -n 1 "${FILE}")" + fi +else + echo "Usage: ${0} " + exit 1 +fi + +if [[ -e "$(which git)" ]]; then + # clean 'dirty' status of touched files that haven't been modified + git diff >/dev/null 2>/dev/null + + # get a string like "v0.6.0-66-g59887e8-dirty" + DESC="$(git describe --dirty 2>/dev/null)" + + # get a string like "2012-04-10 16:27:19 +0200" + TIME="$(git log -n 1 --format="%ci")" + + # get short commit hash + COMMIT_ID="$(git rev-parse --short HEAD)" +fi + +if [[ -n "${DESC}" ]]; then + NEWINFO="#define BUILD_DESC \"${DESC}\"" +else + NEWINFO="// No build information available" +fi + +# only update build.h if necessary +if [[ "${INFO}" != "${NEWINFO}" ]]; then + echo "${NEWINFO}" >"${FILE}" + echo "#define BUILD_DATE \"${TIME}\"" >>"${FILE}" + echo "#define GIT_HASH \"${COMMIT_ID}\"" >>"${FILE}" +fi diff --git a/scripts/include/handle_buildconfig.sh b/scripts/include/handle_buildconfig.sh new file mode 100644 index 0000000000..e2a2052d3f --- /dev/null +++ b/scripts/include/handle_buildconfig.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-11-30 HLXEasy +# +# =========================================================================== + +if [[ ! -e .buildconfig ]]; then + cat << EOF > .buildconfig +##### ### # Global definitions # ### ######################################## +# Windows with msys2 +#ARCHIVES_ROOT_DIR=C:/msys64${HOME}/Archives +# Linux +# Do not use '~' as later steps might not be able to expand this! +ARCHIVES_ROOT_DIR=${HOME}/Archives + +##### ### # Android # ### ################################################### +ANDROID_NDK_VERSION=r21d +ANDROID_SDK_ROOT=${HOME}/Archives/Android/Sdk + +##### ### # Boost # ### ##################################################### +BOOST_VERSION=1.75.0 +BOOST_ARCHIVE_HASH=aeb26f80e80945e82ee93e5939baebdca47b9dee80a07d3144be1e1a6a66dd6a + +##### ### # Qt # ### ######################################################## +# Path to the folder which contains the Qt installation +# aka version folder to use +QT_INSTALLATION_PATH=${HOME}/Qt + +QT_REQUIRED_LIBS='Core Widgets WebView WebChannel WebSockets QuickWidgets Quick Gui Qml Network' + +# Qt version to use. In fact the folder right below ${QT_INSTALLATION_PATH} +#QT_VERSION=5.11.3 +#QT_ARCHIVE_HASH=unknown +#QT_VERSION=5.12.7 +#QT_ARCHIVE_HASH=ce2c5661c028b9de6183245982d7c120 +#QT_VERSION=5.12.8 +#QT_ARCHIVE_HASH=8ec2a0458f3b8e9c995b03df05e006e4 +#QT_VERSION=5.14.2 +#QT_ARCHIVE_HASH=b3d2b6d00e6ca8a8ede6d1c9bdc74daf +QT_VERSION=5.15.0 +QT_ARCHIVE_HASH=610a228dba6ef469d14d145b71ab3b88 + +# These are the default Qt versions on the corresponding distributions +QT_VERSION_ANDROID=5.15.2 +QT_VERSION_CENTOS_8=5.12.8 +QT_VERSION_DEBIAN_BUSTER=5.11.3 +QT_VERSION_UBUNTU_1804=5.9.5 +QT_VERSION_UBUNTU_1904=5.12.4 +QT_VERSION_UBUNTU_1910=5.12.4 +QT_VERSION_UBUNTU_2004=5.12.8 +QT_VERSION_FEDORA=5.15.2 +QT_VERSION_OPENSUSE_TUMBLEWEED=5.15.1 + +##### ### # Qt (Mac) # ### ################################################## +# Installed Qt version. In fact the folder below /Applications/Qt/ +QT_VERSION_MAC=5.12.10 + +##### ### # BerkeleyDB # ### ################################################ +BERKELEYDB_BUILD_VERSION=4.8.30 +BERKELEYDB_ARCHIVE_HASH=e0491a07cdb21fb9aa82773bbbedaeb7639cbd0e7f96147ab46141e0045db72a +#BERKELEYDB_BUILD_VERSION=5.0.32 +#BERKELEYDB_ARCHIVE_HASH=... +#BERKELEYDB_BUILD_VERSION=6.2.38 +#BERKELEYDB_ARCHIVE_HASH=... + +##### ### # LevelDB # ### ################################################### +LEVELDB_VERSION=1.22 +LEVELDB_VERSION_TAG=78b39d68 + +##### ### # OpenSSL # ### ################################################### +OPENSSL_BUILD_VERSION=1.1.0l +OPENSSL_ARCHIVE_HASH=74a2f756c64fd7386a29184dc0344f4831192d61dc2481a93a4c5dd727f41148 +#OPENSSL_ARCHIVE_HASH=... + +##### ### # EventLib # ### ################################################## +LIBEVENT_BUILD_VERSION=2.1.11 +LIBEVENT_ARCHIVE_HASH=a65bac6202ea8c5609fd5c7e480e6d25de467ea1917c08290c521752f147283d + +##### ### # ZLib # ### ###################################################### +#LIBZ_BUILD_VERSION=1.2.11 +#LIBZ_ARCHIVE_HASH=629380c90a77b964d896ed37163f5c3a34f6e6d897311f1df2a7016355c45eff +LIBZ_BUILD_VERSION=1.4.4 +LIBZ_ARCHIVE_HASH=59ef70ebb757ffe74a7b3fe9c305e2ba3350021a918d168a046c6300aeea9315 + +##### ### # XZLib # ### ##################################################### +LIBXZ_BUILD_VERSION=5.2.4 +LIBXZ_ARCHIVE_HASH=b512f3b726d3b37b6dc4c8570e137b9311e7552e8ccbab4d39d47ce5f4177145 + +##### ### # Tor # ### ####################################################### +TOR_BUILD_VERSION=0.4.1.6 +TOR_ARCHIVE_HASH=ee7adbbc5e30898bc35d9658bbf6a67e4242977175f7bad11c5f1ee0c1010d43 +#TOR_BUILD_VERSION=0.4.1.7 +#TOR_ARCHIVE_HASH=f769c8052f0c0f74b9b7bcaff6255f656e313da232bfa8f89d2a165df3868850 +#TOR_BUILD_VERSION=0.4.2.5 +#TOR_ARCHIVE_HASH=94ad248f4d852a8f38bd8902a12b9f41897c76e389fcd5b8a7d272aa265fd6c9 + +TOR_BUILD_VERSION_ANDROID=0.4.1.6 +TOR_ARCHIVE_HASH_ANDROID=ee7adbbc5e30898bc35d9658bbf6a67e4242977175f7bad11c5f1ee0c1010d43 +#TOR_BUILD_VERSION_ANDROID=0.4.2.3-alpha +#TOR_ARCHIVE_HASH_ANDROID=be22b9326093dd6b012377d9e3c456028cd2104e5a454a7773aebf75d44c1ccf +#TOR_BUILD_VERSION_ANDROID=0.4.2.5 +#TOR_ARCHIVE_HASH_ANDROID=94ad248f4d852a8f38bd8902a12b9f41897c76e389fcd5b8a7d272aa265fd6c9 + +EOF +fi +info "" +info "Build configuration:" +info " -> Loading general build configuration" +. .buildconfig + +if [[ -e "${HOME}/.alias_buildconfig" ]]; then + info " -> Loading personal build configuration" + # Personal build config found, so load it + . "${HOME}/.alias_buildconfig" +else + # Personal build config not existing, create it with all entries commented + info "" + warning " -> Personal build configuration not found, creating it now!" + sed "s/^\([a-zA-Z]\)/#\1/g" .buildconfig > "${HOME}/.alias_buildconfig" + info "" + info "If you like to modify '${HOME}/.alias_buildconfig'," + info "you should break script execution now (Ctrl-C)" + for i in $(seq 10 -1 0); do + info "${i}" + sleep 1 + done +fi diff --git a/scripts/include/helpers_console.sh b/scripts/include/helpers_console.sh new file mode 100644 index 0000000000..d3137efab7 --- /dev/null +++ b/scripts/include/helpers_console.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2018-11-28 HLXEasy +# +# =========================================================================== + +_init() { + #if [[ -n "${TERM}" && "${TERM}" != "dumb" ]]; then + GREEN='\e[0;32m' RED='\e[0;31m' BLUE='\e[0;34m' NORMAL='\e[0m' + #else + # GREEN="" RED="" BLUE="" NORMAL="" + #fi +} +die() { + local error="${1:-1}" + shift + error "$*" >&2 + exit "${error}" +} +info() { + printf "${GREEN}%-7s: %s${NORMAL}\n" "Info" "$*" +} +error() { + printf "${RED}%-7s: %s${NORMAL}\n" "Error" "$*" +} +warning() { + printf "${BLUE}%-7s: %s${NORMAL}\n" "Warning" "$*" +} + +# --------------------------------------------------------------------------- +# Execute the given command and return the given error value +# in case of an error +# $1 .. Cmd to execute +# $2 .. Return value in case the given cmd did not finish successful. If a +# negative value is given, a warning is written to the log but the +# function returns instead of performing 'die ...'. +executeCommand() { + local _command="$1" + local _returnCodeForError="$2" + echo "Executing '${_command}'" + eval "${_command}" + rtc=$? + evaluateRtc ${rtc} "${_returnCodeForError}" + return ${rtc} +} + +evaluateRtc() { + local _givenRtc="${1}" + local _returnCodeForError="${2}" + if [[ "${_givenRtc}" -ne 0 ]]; then + if [[ -z "${_returnCodeForError}" ]]; then + die 80 "Error during build steps" + elif [[ "${_returnCodeForError}" -lt 0 ]]; then + warning "Last command finished with non-zero return code but ignoring this for now" + else + die "${_returnCodeForError}" "Error during build steps! (${_returnCodeForError})" + fi + fi +} + +storeDependenciesBuildDir() { + local _dependenciesBuildDir="${1}" + sed -i ".bak" "/DEPENDENCIES_BUILD_DIR/d" "${ownLocation}/.buildconfig" + echo "DEPENDENCIES_BUILD_DIR=${_dependenciesBuildDir}" >> "${ownLocation}/.buildconfig" +} diff --git a/scripts/install_boost_1_67.sh b/scripts/install_boost_1_67.sh new file mode 100644 index 0000000000..160a1c2916 --- /dev/null +++ b/scripts/install_boost_1_67.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +wget -O boost_1_67_0.tar.gz http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.gz/download --no-check-certificate +tar xzvf boost_1_67_0.tar.gz +cd boost_1_67_0/ + +sudo apt-get update +sudo apt-get install build-essential g++ python-dev autotools-dev libicu-dev libbz2-dev + +./bootstrap.sh --prefix=/usr/local +sudo ./b2 --with=all -j 2 install diff --git a/scripts/install_docker_debian.sh b/scripts/install_docker_debian.sh new file mode 100644 index 0000000000..8249c26205 --- /dev/null +++ b/scripts/install_docker_debian.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -euo pipefail +# ============================================================================ +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Docker installation based on +# https://docs.docker.com/install/linux/docker-ce/debian/#install-docker-ce-1 +# +# Creation: 2018-07-25 hlxeasy +# +# ============================================================================ + +# Remove potential old versions +sudo apt-get remove docker docker-engine docker.io containerd runc + +# Update the apt package index +sudo apt-get update + +# Install packages to allow apt to use a repository over HTTPS +sudo apt-get install \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common + +# Add Docker’s official GPG key: +curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - + +# Set up the stable repository +sudo add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/debian \ + $(lsb_release -cs) \ + stable" + +# Update the apt package index again +sudo apt-get update + +# Install the latest version of Docker CE +sudo apt-get install docker-ce docker-ce-cli containerd.io + +# Test installation by running the hello-world-container +sudo docker run --rm hello-world diff --git a/scripts/mac-build.sh b/scripts/mac-build.sh new file mode 100755 index 0000000000..c66a64d61e --- /dev/null +++ b/scripts/mac-build.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2018-11-28 HLXEasy +# +# This script can be used to build Spectrecoin on Mac +# +# =========================================================================== + +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" +. ./include/helpers_console.sh + +# Go to Aliaswallet repository root directory +cd .. + +if [[ -z "${MACOSX_DEPLOYMENT_TARGET}" ]] ; then + MACOSX_DEPLOYMENT_TARGET=10.12 + warning "MACOSX_DEPLOYMENT_TARGET not set, using '${MACOSX_DEPLOYMENT_TARGET}'" +else + info "MACOSX_DEPLOYMENT_TARGET: ${MACOSX_DEPLOYMENT_TARGET}" +fi + +if [[ -z "${QT_PATH}" ]] ; then + QT_PATH=~/Qt/5.12.9/clang_64 + warning "QT_PATH not set, using '${QT_PATH}'" +else + info "QT_PATH: ${QT_PATH}" +fi +if [[ -z "${OPENSSL_PATH}" ]] ; then + OPENSSL_PATH=/usr/local/Cellar/openssl@1.1/1.1.1d + warning "OPENSSL_PATH not set, using '${OPENSSL_PATH}'" +else + info "OPENSSL_PATH: ${OPENSSL_PATH}" +fi + +if [[ -z "${BOOST_PATH}" ]] ; then + BOOST_PATH=/usr/local/Cellar/boost/1.68.0_1 + warning "BOOST_PATH not set, using '${BOOST_PATH}'" +else + info "BOOST_PATH: ${BOOST_PATH}" +fi + +info "Calling autogen.sh" +./autogen.sh + +info "Configure and make db4.8:" +cd db4.8/build_unix/ +./configure --enable-cxx --disable-shared --disable-replication --with-pic && make + +info "Configure and make leveldb:" +cd ../../leveldb/ +./build_detect_platform build_config.mk ./ && make +cd ../ + +info "Starting qmake:" +${QT_PATH}/bin/qmake src/src.pro -spec macx-clang CONFIG+=x86_64 +make -j2 diff --git a/scripts/mac-deployqt.sh b/scripts/mac-deployqt.sh new file mode 100755 index 0000000000..aff5bb4664 --- /dev/null +++ b/scripts/mac-deployqt.sh @@ -0,0 +1,91 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# This script uses macdeployqt to add the required libs to alias package. +# - Fixes non @executable openssl references. +# - Replaces openssl 1.0.0 references with 1.1 +# +# =========================================================================== + +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" +. ./include/helpers_console.sh + +# Go to Alias repository root directory +cd .. + +if [[ -z "${QT_PATH}" ]] ; then + QT_PATH=~/Qt/5.12.9/clang_64 + warning "QT_PATH not set, using '${QT_PATH}'" +else + info "QT_PATH: ${QT_PATH}" +fi +if [[ -z "${OPENSSL_PATH}" ]] ; then + OPENSSL_PATH=/usr/local/Cellar/openssl@1.1/1.1.1d + warning "OPENSSL_PATH not set, using '${OPENSSL_PATH}'" +else + info "OPENSSL_PATH: ${OPENSSL_PATH}" +fi + +if [[ -z "${BOOST_PATH}" ]] ; then + BOOST_PATH=/usr/local/Cellar/boost/1.68.0_1 + warning "BOOST_PATH not set, using '${BOOST_PATH}'" +else + info "BOOST_PATH: ${BOOST_PATH}" +fi + +info "Cleanup previous build artifacts" +if [[ -e Alias.dmg ]] ; then + rm -f Alias.dmg +fi +if [[ -e src/bin/Alias.dmg ]] ; then + rm -f src/bin/Alias.dmg +fi + +info "Call macdeployqt:" +${QT_PATH}/bin/macdeployqt src/bin/Alias.app -qmldir=src/qt/res/qml -always-overwrite -verbose=2 +rtc=$? +if [[ ${rtc} != 0 ]] ; then + die ${rtc} "Error during macdeployqt!" +fi + +info "Remove openssl 1.0.0 libs:" +rm -v src/bin/alias.app/Contents/Frameworks/libssl.1.0.0.dylib +rm -v src/bin/alias.app/Contents/Frameworks/libcrypto.1.0.0.dylib + +info "Replace openssl 1.0.0 lib references with 1.1:" +for f in src/bin/alias.app/Contents/Frameworks/*.dylib; do + install_name_tool -change @executable_path/../Frameworks/libssl.1.0.0.dylib @executable_path/../Frameworks/libssl.1.1.dylib "${f}" + install_name_tool -change @executable_path/../Frameworks/libcrypto.1.0.0.dylib @executable_path/../Frameworks/libcrypto.1.1.dylib "${f}" +done + + +info "install_name_tool -change $OPENSSL_PATH/lib/libcrypto.1.1.dylib @executable_path/../Frameworks/libcrypto.1.1.dylib src/bin/alias.app/Contents/Frameworks/libssl.1.1.dylib ..." +install_name_tool -change ${OPENSSL_PATH}/lib/libcrypto.1.1.dylib @executable_path/../Frameworks/libcrypto.1.1.dylib src/bin/alias.app/Contents/Frameworks/libssl.1.1.dylib +otool -l src/bin/alias.app/Contents/Frameworks/libssl.1.1.dylib | grep dylib + + +info "Please check for non included lib references:" +for f in src/bin/alias.app/Contents/Frameworks/*.dylib; do + otool -l "${f}" | grep dylib | grep -v @ +done + + +info "Create dmg package:" +cd src/bin +${QT_PATH}/bin/macdeployqt Alias.app -dmg -always-overwrite -verbose=2 +rtc=$? +if [[ ${rtc} != 0 ]] ; then + die ${rtc} "Error during macdeployqt!" +fi +cd ../.. +mv src/bin/Alias.dmg Alias.dmg diff --git a/scripts/mac-finalizedmg.sh b/scripts/mac-finalizedmg.sh new file mode 100755 index 0000000000..4921ad0300 --- /dev/null +++ b/scripts/mac-finalizedmg.sh @@ -0,0 +1,87 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# This script uses macdeployqt to add the required libs to alias package. +# - Fixes non @executable openssl references. +# - Replaces openssl 1.0.0 references with 1.1 +# +# =========================================================================== + +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" +. ./include/helpers_console.sh + +# Go to Alias repository root directory +cd .. + +info "Change permision of .dmg file" +hdiutil convert "Alias.dmg" -format UDRW -o "Alias_Rw.dmg" +info " -> Done" + +info "Mount it and save the device" +DEVICE=$(hdiutil attach -readwrite -noverify "Alias_Rw.dmg" | grep -E '^/dev/' | sed 1q | awk '{print $1}') +info " -> Done" + +sleep 2 + +info "Create symbolic link to application folder" +PATH_AT_VOLUME=/Volumes/Alias ## check Path inside cd /Volume/ + +pushd "$PATH_AT_VOLUME" +ln -s /Applications +popd +info " -> Done" + +#info "Copy background image in to package" +#mkdir "$PATH_AT_VOLUME"/.background +#cp backgroundImage.png "$PATH_AT_VOLUME"/.background/ +#info " -> Done" + +info "Resize window, set background, change icon size, place icons in the right position, etc." +echo ' + tell application "Finder" + tell disk "Alias" ## check Path inside cd /Volume/ + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set the bounds of container window to {400, 100, 1200, 650} + set viewOptions to the icon view options of container window + set arrangement of viewOptions to not arranged + set icon size of viewOptions to 200 + ## set background picture of viewOptions to file ".background:backgroundImage.png" + set position of item "Alias.app" of container window to {180, 200} + set position of item "Applications" of container window to {620, 200} + close + open + update without registering applications + delay 2 + end tell + end tell +' | osascript +info " -> Done" + +sync + +info "Unmount" +hdiutil detach "${DEVICE}" +info " -> Done" + +info "Cleanup and convert" +rm -f "Alias.dmg" +hdiutil convert "Alias_Rw.dmg" -format UDZO -o "Alias.dmg" +rm -f "Alias_Rw.dmg" +info " -> Done" + +info "Finished" + +exit diff --git a/scripts/patches/mac-boost-process.patch b/scripts/patches/mac-boost-process.patch new file mode 100644 index 0000000000..3e5f017ace --- /dev/null +++ b/scripts/patches/mac-boost-process.patch @@ -0,0 +1,43 @@ +--- a/boost/process/detail/posix/wait_group.hpp ++++ b/boost/process/detail/posix/wait_group.hpp +@@ -61,8 +61,8 @@ + ::sigset_t sigset; + ::siginfo_t siginfo; + +- ::sigemptyset(&sigset); +- ::sigaddset(&sigset, SIGCHLD); ++ sigemptyset(&sigset); ++ sigaddset(&sigset, SIGCHLD); + + auto get_timespec = + [](const Duration & dur) +@@ -87,7 +87,7 @@ + do + { + auto ts = get_timespec(time_out - Clock::now()); +- ret = ::sigtimedwait(&sigset, nullptr, &ts); ++ ret = sigtimedwait(&sigset, nullptr, &ts); + errno = 0; + if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN)) + old_sig.sa_handler(ret); +--- a/boost/process/detail/posix/wait_for_exit.hpp ++++ b/boost/process/detail/posix/wait_for_exit.hpp +@@ -57,8 +57,8 @@ + + ::sigset_t sigset; + +- ::sigemptyset(&sigset); +- ::sigaddset(&sigset, SIGCHLD); ++ sigemptyset(&sigset); ++ sigaddset(&sigset, SIGCHLD); + + auto get_timespec = + [](const Duration & dur) +@@ -84,7 +84,7 @@ + do + { + auto ts = get_timespec(time_out - Clock::now()); +- auto ret_sig = ::sigtimedwait(&sigset, nullptr, &ts); ++ auto ret_sig = sigtimedwait(&sigset, nullptr, &ts); + errno = 0; + ret = ::waitpid(p.pid, &status, WNOHANG); diff --git a/scripts/updateUIAssets.sh b/scripts/updateUIAssets.sh new file mode 100755 index 0000000000..610ae175b6 --- /dev/null +++ b/scripts/updateUIAssets.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -euo pipefail +# =========================================================================== +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# Created: 2019-04-22 HLXEasy +# +# Helper script to download UI asset archive from our CI +# and update existing assets with content of this archive +# +# =========================================================================== + +# Store path from where script was called, determine own location +# and source helper content from there +callDir=$(pwd) +ownLocation="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "${ownLocation}" +. ./include/helpers_console.sh + +# Go to Aliaswallet repository root directory +cd .. + +_init + +if [[ -z "${1}" ]]; then + downloadURL="https://ci.alias.cash/job/Alias/job/alias-wallet-ui/job/Aliaswallet-UI/lastSuccessfulBuild/artifact/alias-wallet-ui-assets.tgz" +else + downloadURL="${1}" +fi + +info "Using download URL ${downloadURL}" +cd src/qt/res +wget "${downloadURL}" + +info "Updating content" +tar xzf "${downloadURL##*/}" +mv spectre.qrc ../../../ + +info "Cleanup" +rm -f "${downloadURL##*/}" diff --git a/scripts/win-build.bat b/scripts/win-build.bat new file mode 100644 index 0000000000..e964994377 --- /dev/null +++ b/scripts/win-build.bat @@ -0,0 +1,104 @@ +:: SPDX-FileCopyrightText: © 2025 ALIAS Developers +:: SPDX-FileCopyrightText: © 2020 Alias Developers +:: SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +:: +:: SPDX-License-Identifier: MIT +:: +:: Helper script to build Aliaswallet on Windows using VS2017 and QT. + +@echo off +setlocal enabledelayedexpansion + +:: Check for required environment variables +IF "%QTDIR%" == "" GOTO NOQT +:YESQT + +IF "%VSDIR%" == "" GOTO NOVS +:YESVS + +:: Set up directory paths +set "CALL_DIR=%cd%" +set "SRC_DIR=%cd%\src" +set "DIST_DIR=%SRC_DIR%\dist" +set "BUILD_DIR=%SRC_DIR%\build" +set "OUT_DIR=%SRC_DIR%\bin" + +:: Initialize Visual Studio environment +:: "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" +call "%VSDIR%\Community\VC\Auxiliary\Build\vcvars64.bat" +if errorlevel 1 ( + echo Failed to initialize Visual Studio environment + exit /b 1 +) + +cd +cd "%SRC_DIR%" +if errorlevel 1 ( + echo Failed to change to source directory: %SRC_DIR% + exit /b 1 +) +dir + +echo on + +:: Clean previous build artifacts +del "%OUT_DIR%\Alias.exe" 2>nul +if exist "%DIST_DIR%" ( + rmdir /S /Q "%DIST_DIR%" + if errorlevel 1 ( + echo Warning: Failed to remove dist directory + ) +) +if not exist "%DIST_DIR%" mkdir "%DIST_DIR%" +if errorlevel 1 goto :ERROR + +if not exist "%BUILD_DIR%" mkdir "%BUILD_DIR%" +if errorlevel 1 goto :ERROR + +if not exist "%OUT_DIR%" mkdir "%OUT_DIR%" +if errorlevel 1 goto :ERROR + +:: Build using qmake +pushd "%BUILD_DIR%" + +"%QTDIR%\bin\qmake.exe" ^ + -spec win32-msvc ^ + "CONFIG += release" ^ + "%SRC_DIR%\src.pro" +if errorlevel 1 goto :ERROR + +nmake +if errorlevel 1 goto :ERROR + +popd + +:: Deploy Qt dependencies +"%QTDIR%\bin\windeployqt.exe" --force --qmldir "%SRC_DIR%\qt\res" --qml --quick --webengine "%OUT_DIR%\Alias.exe" +if errorlevel 1 goto :ERROR + +::ren "%OUT_DIR%" Alias +::echo "The prepared package is in: %SRC_DIR%\Alias" + +echo "Everything is OK" +GOTO END + +:ERROR +echo Failed with error #%errorlevel%. +endlocal +exit /b %errorlevel% +GOTO END + +:NOVS +@ECHO The VSDIR environment variable was NOT detected! +endlocal +exit /b 1 +GOTO END + +:NOQT +@ECHO The QTDIR environment variable was NOT detected! +endlocal +exit /b 1 + +:END +cd "%CALL_DIR%" +endlocal diff --git a/scripts/win-genbuild.bat b/scripts/win-genbuild.bat new file mode 100644 index 0000000000..8c62f1a9bb --- /dev/null +++ b/scripts/win-genbuild.bat @@ -0,0 +1,30 @@ +:: SPDX-FileCopyrightText: © 2025 ALIAS Developers +:: SPDX-FileCopyrightText: © 2020 Alias Developers +:: SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +:: +:: SPDX-License-Identifier: MIT +:: +:: Helper script to create build.h. +echo off +set SRC_DIR=%cd%\src +set CALL_DIR=%cd% + +cd +cd %SRC_DIR% + +echo on + +@echo Creating build.h + +FOR /F "delims=" %%i IN ('git describe --dirty') DO set DESC=%%i +@echo #define BUILD_DESC "%DESC%" > build.h + +FOR /F "delims=" %%j IN ('git log -n 1 --format^="%%ci"') DO set TIME=%%j +@echo #define BUILD_DATE "%TIME%" >> build.h + +FOR /F "delims=" %%k IN ('git rev-parse --short HEAD') DO set COMMIT=%%k +@echo #define GIT_HASH "%COMMIT%" >> build.h + +@echo Created build.h with the following content: +type build.h +cd %CALL_DIR% diff --git a/scripts/win-wrapper.bat b/scripts/win-wrapper.bat new file mode 100644 index 0000000000..0c583aa65f --- /dev/null +++ b/scripts/win-wrapper.bat @@ -0,0 +1,33 @@ +:: SPDX-FileCopyrightText: © 2025 ALIAS Developers +:: SPDX-FileCopyrightText: © 2020 Alias Developers +:: SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +:: +:: SPDX-License-Identifier: MIT +:: +:: Wrapper script to define all requirements + +@echo off +setlocal enabledelayedexpansion + +:: Set version and Qt directory +set "ALIASWALLET_VERSION=4.2.0" +set "QTDIR=C:\Qt\5.15.0\msvc2019_64" + +:: Generate build.h +call "scripts\win-genbuild.bat" +if errorlevel 1 ( + echo Failed to generate build.h + endlocal + exit /b %errorlevel% +) + +:: Build the project +call "scripts\win-build.bat" +if errorlevel 1 ( + echo Failed to build project + endlocal + exit /b %errorlevel% +) + +endlocal +exit /b 0 diff --git a/shadow.pro b/shadow.pro deleted file mode 100644 index d3ed74a340..0000000000 --- a/shadow.pro +++ /dev/null @@ -1,483 +0,0 @@ -TEMPLATE = app -TARGET = umbra -VERSION = 1.5.0.2 -INCLUDEPATH += src src/json src/qt -DEFINES += BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE -CONFIG += no_include_pwd -CONFIG += thread - -# Mobile devices -android:ios{ - CONFIG += mobility - MOBILITY = -} - -greaterThan(QT_MAJOR_VERSION, 4) { - DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 -} - -# for boost 1.37, add -mt to the boost libraries -# use: qmake BOOST_LIB_SUFFIX=-mt -# for boost thread win32 with _win32 sufix -# use: BOOST_THREAD_LIB_SUFFIX=_win32-... -# or when linking against a specific BerkelyDB version: BDB_LIB_SUFFIX=-4.8 - -# Dependency library locations can be customized with: -# BOOST_INCLUDE_PATH, BOOST_LIB_PATH, BDB_INCLUDE_PATH, -# BDB_LIB_PATH, OPENSSL_INCLUDE_PATH and OPENSSL_LIB_PATH respectively - -OBJECTS_DIR = build -MOC_DIR = build -UI_DIR = build -RESOURCES = shadow.qrc - -android { - INCLUDEPATH += src/qt/android - - QT += androidextras - - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android - - OTHER_FILES += - - HEADERS += - SOURCES += - - OBJECTS_DIR = build-android - MOC_DIR = build-android - UI_DIR = build-android -} else { - - QT += widgets webkitwidgets -} - -build_macosx64 { - QMAKE_TARGET_BUNDLE_PREFIX = co.shadowcoin - BOOST_LIB_SUFFIX=-mt - BOOST_INCLUDE_PATH=/usr/local/Cellar/boost/1.61.0_1/include - BOOST_LIB_PATH=/usr/local/Cellar/boost/1.61.0_1/lib - - BDB_INCLUDE_PATH=/usr/local/opt/berkeley-db4/include - BDB_LIB_PATH=/usr/local/Cellar/berkeley-db4/4.8.30/lib - - OPENSSL_INCLUDE_PATH=/usr/local/opt/openssl/include - OPENSSL_LIB_PATH=/usr/local/opt/openssl/lib - - #MINIUPNPC_INCLUDE_PATH=/usr/local/opt/miniupnpc/include - #MINIUPNPC_LIB_PATH=/usr/local/Cellar/miniupnpc/1.8.20131007/lib - MINIUPNPC_INCLUDE_PATH=/usr/local/Cellar/miniupnpc/2.0/include - MINIUPNPC_LIB_PATH=/usr/local/Cellar/miniupnpc/2.0/lib - - QMAKE_CXXFLAGS += -arch x86_64 -stdlib=libc++ - QMAKE_CFLAGS += -arch x86_64 - QMAKE_LFLAGS += -arch x86_64 -stdlib=libc++ - USE_UPNP=1 - -} -build_win32 { - BOOST_LIB_SUFFIX=-mgw48-mt-s-1_55 - BOOST_INCLUDE_PATH=c:/deps/boost/include - BOOST_LIB_PATH=c:/deps/boost/lib - - BDB_INCLUDE_PATH=c:/deps/db-4.8.30.NC/build_unix - BDB_LIB_PATH=c:/deps/db-4.8.30.NC/build_unix - OPENSSL_INCLUDE_PATH=c:/deps/openssl_1.0.1h/include - OPENSSL_LIB_PATH=c:/deps/openssl_1.0.1h/lib/ - - MINIUPNPC_INCLUDE_PATH=c:/deps/miniupnpc - MINIUPNPC_LIB_PATH=c:/deps/miniupnpc - - #USE_BUILD_INFO = 1 - DEFINES += HAVE_BUILD_INFO - - #USE_UPNP=- -} - -# use: qmake "RELEASE=1" -contains(RELEASE, 1) { - CONFIG += static - - !windows:!macx { - # Linux: static link - LIBS += -Wl,-Bstatic - } -} - -# for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection -QMAKE_CXXFLAGS *= -fstack-protector-all --param ssp-buffer-size=1 -QMAKE_LFLAGS *= -fstack-protector-all --param ssp-buffer-size=1 -# We need to exclude this for Windows cross compile with MinGW 4.2.x, as it will result in a non-working executable! -# This can be enabled for Windows, when we switch to MinGW >= 4.4.x. -# for extra security on Windows: enable ASLR and DEP via GCC linker flags -win32:QMAKE_LFLAGS *= -Wl,--dynamicbase -Wl,--nxcompat -static -win32:QMAKE_LFLAGS *= -static-libgcc -static-libstdc++ - -# use: qmake "USE_UPNP=1" ( enabled by default; default) -# or: qmake "USE_UPNP=0" (disabled by default) -# or: qmake "USE_UPNP=-" (not supported) -# miniupnpc (http://miniupnp.free.fr/files/) must be installed for support -contains(USE_UPNP, -) { - message(Building without UPNP support) -} else { - message(Building with UPNP support) - count(USE_UPNP, 0) { - USE_UPNP=1 - } - DEFINES += USE_UPNP=$$USE_UPNP MINIUPNP_STATICLIB STATICLIB - INCLUDEPATH += $$MINIUPNPC_INCLUDE_PATH - LIBS += $$join(MINIUPNPC_LIB_PATH,,-L,) -lminiupnpc - win32:LIBS += -liphlpapi -} - -# use: qmake "USE_DBUS=1" or qmake "USE_DBUS=0" -linux:count(USE_DBUS, 0) { - USE_DBUS=1 -} -contains(USE_DBUS, 1) { - message(Building with DBUS (Freedesktop notifications) support) - DEFINES += USE_DBUS - QT += dbus -} - -contains(SHADOW_NEED_QT_PLUGINS, 1) { - DEFINES += SHADOW_NEED_QT_PLUGINS - QTPLUGIN += qcncodecs qjpcodecs qtwcodecs qkrcodecs qtaccessiblewidgets -} - -INCLUDEPATH += src/leveldb/include src/leveldb/helpers -LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a -SOURCES += src/txdb-leveldb.cpp \ - src/qt/addresstablemodel.cpp - -win32 { - # make an educated guess about what the ranlib command is called - isEmpty(QMAKE_RANLIB) { - QMAKE_RANLIB = $$replace(QMAKE_STRIP, strip, ranlib) - } - LIBS += -lshlwapi - genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libleveldb.a && $$QMAKE_RANLIB $$PWD/src/leveldb/libmemenv.a -} else:macx { - # we use QMAKE_CXXFLAGS_RELEASE even without RELEASE=1 because we use RELEASE to indicate linking preferences not -O preferences - genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX AR=$${QMAKE_HOST}-ar TARGET_OS=Darwin $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a -} else { - genleveldb.commands = cd $$PWD/src/leveldb && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) OPT=\"$$QMAKE_CXXFLAGS $$QMAKE_CXXFLAGS_RELEASE\" libleveldb.a libmemenv.a -} -genleveldb.target = $$PWD/src/leveldb/libleveldb.a -genleveldb.depends = FORCE -PRE_TARGETDEPS += $$PWD/src/leveldb/libleveldb.a -QMAKE_EXTRA_TARGETS += genleveldb -# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it. -QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean - -# regenerate src/build.h -!windows|contains(USE_BUILD_INFO, 1) { - genbuild.depends = FORCE - genbuild.commands = cd $$PWD; /bin/sh share/genbuild.sh $$OUT_PWD/build/build.h - genbuild.target = $$OUT_PWD/build/build.h - PRE_TARGETDEPS += $$OUT_PWD/build/build.h - QMAKE_EXTRA_TARGETS += genbuild - DEFINES += HAVE_BUILD_INFO -} - -contains(USE_O3, 1) { - message(Building O3 optimization flag) - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS += -O3 - QMAKE_CFLAGS += -O3 -} - -*-g++-32 { - message("32 platform, adding -msse2 flag") - - QMAKE_CXXFLAGS += -msse2 - QMAKE_CFLAGS += -msse2 -} - -QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter -Wstack-protector - -# Input -DEPENDPATH += src src/json src/qt -HEADERS += \ - src/alert.h \ - src/allocators.h \ - src/wallet.h \ - src/keystore.h \ - src/version.h \ - src/netbase.h \ - src/clientversion.h \ - src/threadsafety.h \ - src/protocol.h \ - src/ui_interface.h \ - src/crypter.h \ - src/addrman.h \ - src/base58.h \ - src/bignum.h \ - src/chainparams.h \ - src/checkpoints.h \ - src/compat.h \ - src/coincontrol.h \ - src/sync.h \ - src/util.h \ - src/hash.h \ - src/uint256.h \ - src/kernel.h \ - src/scrypt.h \ - src/pbkdf2.h \ - src/serialize.h \ - src/strlcpy.h \ - src/smessage.h \ - src/main.h \ - src/miner.h \ - src/net.h \ - src/key.h \ - src/extkey.h \ - src/eckey.h \ - src/db.h \ - src/txdb.h \ - src/walletdb.h \ - src/script.h \ - src/stealth.h \ - src/ringsig.h \ - src/core.h \ - src/txmempool.h \ - src/state.h \ - src/bloom.h \ - src/init.h \ - src/mruset.h \ - src/rpcprotocol.h \ - src/rpcserver.h \ - src/rpcclient.h \ - src/json/json_spirit_writer_template.h \ - src/json/json_spirit_writer.h \ - src/json/json_spirit_value.h \ - src/json/json_spirit_utils.h \ - src/json/json_spirit_stream_reader.h \ - src/json/json_spirit_reader_template.h \ - src/json/json_spirit_reader.h \ - src/json/json_spirit_error_position.h \ - src/json/json_spirit.h \ - src/qt/transactiontablemodel.h \ - src/qt/addresstablemodel.h \ - src/qt/coincontroldialog.h \ - src/qt/coincontroltreewidget.h \ - src/qt/aboutdialog.h \ - src/qt/editaddressdialog.h \ - src/qt/bitcoinaddressvalidator.h \ - src/qt/clientmodel.h \ - src/qt/guiutil.h \ - src/qt/transactionrecord.h \ - src/qt/guiconstants.h \ - src/qt/optionsmodel.h \ - src/qt/monitoreddatamapper.h \ - src/qt/transactiondesc.h \ - src/qt/bitcoinamountfield.h \ - src/qt/walletmodel.h \ - src/qt/csvmodelwriter.h \ - src/qt/qvalidatedlineedit.h \ - src/qt/bitcoinunits.h \ - src/qt/qvaluecombobox.h \ - src/qt/askpassphrasedialog.h \ - src/qt/notificator.h \ - src/qt/rpcconsole.h \ - src/qt/paymentserver.h \ - src/qt/peertablemodel.h \ - src/qt/scicon.h \ - src/qt/trafficgraphwidget.h \ - src/qt/messagemodel.h \ - src/qt/shadowgui.h \ - src/qt/shadowbridge.h \ - src/qt/bridgetranslations.h - -SOURCES += \ - src/alert.cpp \ - src/version.cpp \ - src/chainparams.cpp \ - src/sync.cpp \ - src/smessage.cpp \ - src/util.cpp \ - src/hash.cpp \ - src/netbase.cpp \ - src/key.cpp \ - src/extkey.cpp \ - src/eckey.cpp \ - src/script.cpp \ - src/main.cpp \ - src/miner.cpp \ - src/init.cpp \ - src/net.cpp \ - src/checkpoints.cpp \ - src/addrman.cpp \ - src/db.cpp \ - src/walletdb.cpp \ - src/noui.cpp \ - src/kernel.cpp \ - src/scrypt-arm.S \ - src/scrypt-x86.S \ - src/scrypt-x86_64.S \ - src/scrypt.cpp \ - src/pbkdf2.cpp \ - src/stealth.cpp \ - src/ringsig.cpp \ - src/core.cpp \ - src/txmempool.cpp \ - src/wallet.cpp \ - src/keystore.cpp \ - src/state.cpp \ - src/bloom.cpp \ - src/crypter.cpp \ - src/protocol.cpp \ - src/rpcprotocol.cpp \ - src/rpcserver.cpp \ - src/rpcclient.cpp \ - src/rpcdump.cpp \ - src/rpcnet.cpp \ - src/rpcmining.cpp \ - src/rpcwallet.cpp \ - src/rpcblockchain.cpp \ - src/rpcrawtransaction.cpp \ - src/rpcsmessage.cpp \ - src/rpcextkey.cpp \ - src/rpcmnemonic.cpp \ - src/qt/transactiontablemodel.cpp \ - src/qt/coincontroldialog.cpp \ - src/qt/coincontroltreewidget.cpp \ - src/qt/aboutdialog.cpp \ - src/qt/editaddressdialog.cpp \ - src/qt/bitcoinaddressvalidator.cpp \ - src/qt/clientmodel.cpp \ - src/qt/guiutil.cpp \ - src/qt/transactionrecord.cpp \ - src/qt/optionsmodel.cpp \ - src/qt/monitoreddatamapper.cpp \ - src/qt/transactiondesc.cpp \ - src/qt/bitcoinstrings.cpp \ - src/qt/bitcoinamountfield.cpp \ - src/qt/walletmodel.cpp \ - src/qt/csvmodelwriter.cpp \ - src/qt/qvalidatedlineedit.cpp \ - src/qt/bitcoinunits.cpp \ - src/qt/qvaluecombobox.cpp \ - src/qt/askpassphrasedialog.cpp \ - src/qt/notificator.cpp \ - src/qt/rpcconsole.cpp \ - src/qt/paymentserver.cpp \ - src/qt/peertablemodel.cpp \ - src/qt/scicon.cpp \ - src/qt/trafficgraphwidget.cpp \ - src/qt/messagemodel.cpp \ - src/qt/shadowgui.cpp \ - src/qt/shadow.cpp \ - src/qt/shadowbridge.cpp - - -FORMS += \ - src/qt/forms/coincontroldialog.ui \ - src/qt/forms/aboutdialog.ui \ - src/qt/forms/editaddressdialog.ui \ - src/qt/forms/transactiondescdialog.ui \ - src/qt/forms/askpassphrasedialog.ui \ - src/qt/forms/rpcconsole.ui - - -CODECFORTR = UTF-8 - -# for lrelease/lupdate -# also add new translations to shadow.qrc under translations/ -TRANSLATIONS = $$files(src/qt/locale/umbra*.ts) - -isEmpty(QMAKE_LRELEASE) { - win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe - else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease -} -isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale -# automatically build translations, so they can be included in resource file -TSQM.name = lrelease ${QMAKE_FILE_IN} -TSQM.input = TRANSLATIONS -TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm -TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT} -TSQM.CONFIG = no_link -QMAKE_EXTRA_COMPILERS += TSQM - -# "Other files" to show in Qt Creator -OTHER_FILES += \ - .travis.yml doc/*.rst doc/*.txt doc/README README.md res/bitcoin-qt.rc contrib/macdeploy/createdmg - -# platform specific defaults, if not overridden on command line -isEmpty(BOOST_LIB_SUFFIX) { - macx:BOOST_LIB_SUFFIX = -mt - windows:BOOST_LIB_SUFFIX = -mt -} - -isEmpty(BOOST_THREAD_LIB_SUFFIX) { - BOOST_THREAD_LIB_SUFFIX = $$BOOST_LIB_SUFFIX -} - -isEmpty(BDB_LIB_PATH) { - macx:BDB_LIB_PATH = /opt/local/lib/db48 -} - -isEmpty(BDB_LIB_SUFFIX) { - macx:BDB_LIB_SUFFIX = -4.8 -} - -isEmpty(BDB_INCLUDE_PATH) { - macx:BDB_INCLUDE_PATH = /opt/local/include/db48 -} - -isEmpty(BOOST_LIB_PATH) { - macx:BOOST_LIB_PATH = /opt/local/lib -} - -isEmpty(BOOST_INCLUDE_PATH) { - macx:BOOST_INCLUDE_PATH = /opt/local/include -} - -windows:DEFINES += WIN32 -windows:RC_FILE = src/qt/res/bitcoin-qt.rc - -windows:!contains(MINGW_THREAD_BUGFIX, 0) { - # At least qmake's win32-g++-cross profile is missing the -lmingwthrd - # thread-safety flag. GCC has -mthreads to enable this, but it doesn't - # work with static linking. -lmingwthrd must come BEFORE -lmingw, so - # it is prepended to QMAKE_LIBS_QT_ENTRY. - # It can be turned off with MINGW_THREAD_BUGFIX=0, just in case it causes - # any problems on some untested qmake profile now or in the future. - DEFINES += _MT BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN - QMAKE_LIBS_QT_ENTRY = -lmingwthrd $$QMAKE_LIBS_QT_ENTRY -} - -macx:HEADERS += src/qt/macdockiconhandler.h \ - src/qt/macnotificationhandler.h -macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm \ - src/qt/macnotificationhandler.mm -macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit -macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 -macx:ICON = src/qt/res/icons/shadow.icns -macx:TARGET = "Umbra" -macx:QMAKE_CFLAGS_THREAD += -pthread -macx:QMAKE_LFLAGS_THREAD += -pthread -macx:QMAKE_CXXFLAGS_THREAD += -pthread - -# Set libraries and includes at end, to use platform-defined defaults if not overridden -INCLUDEPATH += $$BOOST_INCLUDE_PATH $$BDB_INCLUDE_PATH $$OPENSSL_INCLUDE_PATH -LIBS += $$join(BOOST_LIB_PATH,,-L,) $$join(BDB_LIB_PATH,,-L,) $$join(OPENSSL_LIB_PATH,,-L,) -LIBS += -lssl -lcrypto -ldb_cxx$$BDB_LIB_SUFFIX -# -lgdi32 has to happen after -lcrypto (see #681) -windows:LIBS += -lws2_32 -lshlwapi -lmswsock -lole32 -loleaut32 -luuid -lgdi32 -LIBS += -lboost_system$$BOOST_LIB_SUFFIX -lboost_filesystem$$BOOST_LIB_SUFFIX -lboost_program_options$$BOOST_LIB_SUFFIX -lboost_thread$$BOOST_THREAD_LIB_SUFFIX -windows:LIBS += -lboost_chrono$$BOOST_LIB_SUFFIX - -contains(RELEASE, 1) { - !windows:!macx { - # Linux: turn dynamic linking back on for c/c++ runtime libraries - LIBS += -Wl,-Bdynamic - } -} - -!windows:!macx:!android:!ios { - DEFINES += LINUX - LIBS += -lrt -ldl -} - -system($$QMAKE_LRELEASE -silent $$_PRO_FILE_) diff --git a/share/genbuild.sh b/share/genbuild.sh deleted file mode 100755 index d959877dc8..0000000000 --- a/share/genbuild.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -if [ $# -gt 0 ]; then - FILE="$1" - shift - if [ -f "$FILE" ]; then - INFO="$(head -n 1 "$FILE")" - fi -else - echo "Usage: $0 " - exit 1 -fi - -if [ -e "$(which git)" ]; then - # clean 'dirty' status of touched files that haven't been modified - git diff >/dev/null 2>/dev/null - - # get a string like "v0.6.0-66-g59887e8-dirty" - DESC="$(git describe --dirty 2>/dev/null)" - - # get a string like "2012-04-10 16:27:19 +0200" - TIME="$(git log -n 1 --format="%ci")" -fi - -if [ -n "$DESC" ]; then - NEWINFO="#define BUILD_DESC \"$DESC\"" -else - NEWINFO="// No build information available" -fi - -# only update build.h if necessary -if [ "$INFO" != "$NEWINFO" ]; then - echo "$NEWINFO" >"$FILE" - echo "#define BUILD_DATE \"$TIME\"" >>"$FILE" -fi diff --git a/share/pixmaps/addressbook16.bmp b/share/pixmaps/addressbook16.bmp deleted file mode 100644 index c5576910b1..0000000000 Binary files a/share/pixmaps/addressbook16.bmp and /dev/null differ diff --git a/share/pixmaps/addressbook16mask.bmp b/share/pixmaps/addressbook16mask.bmp deleted file mode 100644 index d3a478d1ad..0000000000 Binary files a/share/pixmaps/addressbook16mask.bmp and /dev/null differ diff --git a/share/pixmaps/addressbook20.bmp b/share/pixmaps/addressbook20.bmp deleted file mode 100644 index 2b33b228aa..0000000000 Binary files a/share/pixmaps/addressbook20.bmp and /dev/null differ diff --git a/share/pixmaps/addressbook20mask.bmp b/share/pixmaps/addressbook20mask.bmp deleted file mode 100644 index 56ce6125db..0000000000 Binary files a/share/pixmaps/addressbook20mask.bmp and /dev/null differ diff --git a/share/pixmaps/bitcoin-bc.ico b/share/pixmaps/bitcoin-bc.ico deleted file mode 100644 index 88cc240e2d..0000000000 Binary files a/share/pixmaps/bitcoin-bc.ico and /dev/null differ diff --git a/share/pixmaps/bitcoin.ico b/share/pixmaps/bitcoin.ico deleted file mode 100644 index 61926807cc..0000000000 Binary files a/share/pixmaps/bitcoin.ico and /dev/null differ diff --git a/share/pixmaps/bitcoin32.xpm b/share/pixmaps/bitcoin32.xpm deleted file mode 100644 index f538a44d2d..0000000000 --- a/share/pixmaps/bitcoin32.xpm +++ /dev/null @@ -1,232 +0,0 @@ -/* XPM */ -static const char * bitcoin32_xpm[] = { -/* columns rows colors chars-per-pixel */ -"32 32 194 2", -" c #745305", -". c #785704", -"X c #7C5903", -"o c #75560B", -"O c #77590F", -"+ c #7C5C0B", -"@ c #795B12", -"# c #7F631D", -"$ c #825E07", -"% c #825F0B", -"& c #85610A", -"* c #8C660C", -"= c #8E680E", -"- c #916B0F", -"; c #856515", -": c #8B6714", -"> c #8F6A16", -", c #816218", -"< c #88691C", -"1 c #926D12", -"2 c #936F1C", -"3 c #997417", -"4 c #94721E", -"5 c #9B761C", -"6 c #9F781C", -"7 c #A17B1E", -"8 c #826622", -"9 c #916E20", -"0 c #967425", -"q c #9D7420", -"w c #9C7923", -"e c #997728", -"r c #99792C", -"t c #A37D23", -"y c #A37F2C", -"u c #A68125", -"i c #AB8225", -"p c #A5832B", -"a c #AA852C", -"s c #B28A2C", -"d c #A58233", -"f c #AC8734", -"g c #AE8C33", -"h c #AC8C3C", -"j c #B28C33", -"k c #B98E34", -"l c #B28D3D", -"z c #B59136", -"x c #BC9335", -"c c #B3913E", -"v c #BC933A", -"b c #BF9A3D", -"n c #C19235", -"m c #C2953C", -"M c #C39B3C", -"N c #CA9C3D", -"B c #B59343", -"V c #BE9642", -"C c #B69A44", -"Z c #BD9A45", -"A c #B49649", -"S c #BB9A49", -"D c #BB9F52", -"F c #BFA256", -"G c #C49C43", -"H c #CA9D41", -"J c #C59D4A", -"K c #C99E4D", -"L c #C3A144", -"P c #CDA244", -"I c #CFAA47", -"U c #C3A14D", -"Y c #CDA24A", -"T c #CCAB49", -"R c #D2A644", -"E c #D2A54B", -"W c #D6AA4C", -"Q c #DAAE4E", -"! c #DAB04F", -"~ c #C7A656", -"^ c #CDA452", -"/ c #CFAC52", -"( c #C0A65E", -") c #CEA75A", -"_ c #CCAC59", -"` c #D2AB53", -"' c #DCAF52", -"] c #D6AD5A", -"[ c #D9AE5B", -"{ c #DCB556", -"} c #DFB855", -"| c #D6B25F", -" . c #DCB35C", -".. c #DEBE5E", -"X. c #E2B656", -"o. c #E1B55A", -"O. c #E6BC5D", -"+. c #E9BD5E", -"@. c #C3AA63", -"#. c #CCAD62", -"$. c #D4AF62", -"%. c #CDB565", -"&. c #CEB46D", -"*. c #D7B164", -"=. c #DBB362", -"-. c #D6BD64", -";. c #DDBA64", -":. c #D3B66C", -">. c #DFB86B", -",. c #CEB772", -"<. c #D0B771", -"1. c #D4BA73", -"2. c #D9BE77", -"3. c #D6BE79", -"4. c #D8BF7A", -"5. c #E4BB62", -"6. c #E9BF64", -"7. c #E4BC69", -"8. c #E9BF69", -"9. c #E0BB71", -"0. c #E9C05E", -"q. c #D2C279", -"w. c #DBC27C", -"e. c #E2C667", -"r. c #EDC364", -"t. c #E3C16E", -"y. c #ECC46C", -"u. c #EDCC6C", -"i. c #F1C764", -"p. c #F5CA66", -"a. c #F9CD67", -"s. c #F5CC6A", -"d. c #F9CD6B", -"f. c #FBD36F", -"g. c #EDC572", -"h. c #E5CF77", -"j. c #ECCA74", -"k. c #E0C67E", -"l. c #EFCE78", -"z. c #F6CE72", -"x. c #FBCF71", -"c. c #F4CE79", -"v. c #F4D273", -"b. c #FCD473", -"n. c #F4DC75", -"m. c #FEDA74", -"M. c #F6D77C", -"N. c #FBD47A", -"B. c #F1DA7B", -"V. c #FDDA7C", -"C. c #FEE27D", -"Z. c #DDC683", -"A. c #DFC884", -"S. c #E4CA84", -"D. c #E3CC89", -"F. c #E7D183", -"G. c #EFD280", -"H. c #EFDC82", -"J. c #ECD48D", -"K. c #EFDA8C", -"L. c #F9D783", -"P. c #F2DF83", -"I. c #FCDB83", -"U. c #F5DC8F", -"Y. c #FADD8B", -"T. c #EBD593", -"R. c #EFDA99", -"E. c #F3DD93", -"W. c #F3DF9F", -"Q. c #FFE385", -"!. c #FEE986", -"~. c #FDE48C", -"^. c #FEEC8E", -"/. c #ECE199", -"(. c #F6E591", -"). c #FEE494", -"_. c #FEEB93", -"`. c #FEE69A", -"'. c #FFEB9B", -"]. c #FFF197", -"[. c #FFF39B", -"{. c #FEF99B", -"}. c #F6E2A2", -"|. c #F9E5A5", -" X c #F7E9A5", -".X c #FEECA4", -"XX c #FBE7A8", -"oX c #FDEAAB", -"OX c #F7F2AA", -"+X c #FEF2AC", -"@X c #FDF4B4", -"#X c #FFFABA", -"$X c #FFFEC2", -"%X c None", -/* pixels */ -"%X%X%X%X%X%X%X%X%X%X%X%Xp t 6 5 w t w %X%X%X%X%X%X%X%X%X%X%X%X%X", -"%X%X%X%X%X%X%X%X%Xu u x I X.0.s.u.0.W x 7 4 %X%X%X%X%X%X%X%X%X%X", -"%X%X%X%X%X%X%Xy i I i.a.f.m.m.b.f.s.a.s.i.W 7 > %X%X%X%X%X%X%X%X", -"%X%X%X%X%X%Xt M 0.a.m.m.m.m.f.d.p.p.p.f.d.f.i.b 1 < %X%X%X%X%X%X", -"%X%X%X%X%X7 ! d.f.f.m.f.+.W P R I Q 5.v.V.V.z.f.{ 5 + %X%X%X%X%X", -"%X%X%X%Xu X.f.m.m.f.' H s ~ V y _ Z J o.g.L.L.Q.!.e.5 X %X%X%X%X", -"%X%X%Xu X.b.C.m.+.N m n t }.3.> }.w.V 5.y.y.Y.[.^.^.-.1 + %X%X%X", -"%X%Xt P m.N.m.X.v v v k 6 }.1.: /.4.c 7.N.N.v.!.{.{.^.L & %X%X%X", -"%X%Xg Y.Y.V.+.m k a t t : }.1.% }.1.r | l.B.M.b.!.{.^.n.7 X %X%X", -"%Xp -._.'.Y.' Y n D.}.}.|.oXXX|.oX XT.w.F _ j.v.v._.^.C.T & @ %X", -"%Xa (.'.'.9.[ [ K S.}.oXoXoXoXXXoXoXoXoX XD / s.d.v.!.C.v.3 o %X", -"%XU '.'.Y.[ [ [ [ J f <.oXoX( 2 f S J.oXoXT.j r.s.i.C.C.C.z X %X", -"p e.'.'.F. .=.=.=.=.) 1.oXoX@.f . .F oXoX}.a +.i.i.b.C.m.I X O ", -"u w.'.[.j.5.8.7.7.7.] 2.oXoX@.y W c &.oXoXZ.k r.s.i.s.V.m.} = o ", -"u H.[.{.y.8.y.g.8.g.7.2.oXoXA.@.&.D.oXoXT.e G +.O.O.5.V.m.0.- o ", -"u !.].[.r.8.y.g.g.g.7.4.oXoXoXoXoXoXoXoXoX<.y W X.o.o.m.m.0.- o ", -"u B._._.5.5.8.y.g.c.g.w.oXoX,.h A F <..XoXoX1.k ' ' ' V.N.r.- ", -"u u.Q.~.r.6.z.N.V.I.v.k.oXoX@.B | _ c 1.oXoX}.a ' ' O.I.b.O.= o ", -"u ..Q.Q.v.i.s.c.N.L.l.Z.oXoX@.B t.=.S &.oXoXXXy Y R +.N.b.Q % o ", -"t T C.I.I.6.u.z.z.5.S 1.oXoX@.e B h D |.oXoXS.f Y Y 6.d.d.n X O ", -"%Xs m.V.Q.r.r.z.5.<.}.oXoXoXXXW.}.oXoXoXoXW.h G H R a.p.s.7 %X", -"%X7 O.V.V.v.+.r.` 4.oXoXoXoXoXoXoXoXXXR.<.h v N N o.a.p.Q = %X", -"%Xw x v.v.v.r.+. .Z l d e }.Z.r }.3.d l V G n n R a.s.a.s X O %X", -"%X%X6 { v.l.v.+.O.5.=.^ d }.4.9 }.1.f J G m m G d.d.x.Q = %X%X", -"%X%X%Xs u.v.v.v.r.6.o. .l }.4.9 W.4.l ^ ^ J ) c.N.N.y.7 X O %X%X", -"%X%X%X5 z v.v.M.I.g.;. .J 1.#.B 1.#.) 7.$.S..X'.W.Y.j $ %X%X%X", -"%X%X%X%X5 b N.Y.~.).Y.j.5.$.=.=.$.*.2.J.@X$X#X#XoXC $ %X%X%X%X", -"%X%X%X%X%X3 z U.@X+X`.`.`.(.E.E.E.|.@X@X#X#X#X/.j % %X%X%X%X%X", -"%X%X%X%X%X%Xw a q.OX|.).`._.'.'.XX.X.X+X+X X%.w X o %X%X%X%X%X%X", -"%X%X%X%X%X%X%X%Xw a _ j.~.~.).).`.`.`.F._ t & . # %X%X%X%X%X%X%X", -"%X%X%X%X%X%X%X%X%X%X4 3 t z L U Z z t 1 $ . 8 %X%X%X%X%X%X%X%X%X", -"%X%X%X%X%X%X%X%X%X%X%X%X%X< ; & + + , 8 %X%X%X%X%X%X%X%X%X%X%X%X" -}; diff --git a/share/pixmaps/bitcoin80.xpm b/share/pixmaps/bitcoin80.xpm deleted file mode 100644 index c3c816e92d..0000000000 --- a/share/pixmaps/bitcoin80.xpm +++ /dev/null @@ -1,292 +0,0 @@ -/* XPM */ -static const char * bitcoin80_xpm[] = { -/* columns rows colors chars-per-pixel */ -"80 80 206 2", -" c #725203", -". c #785706", -"X c #7B5907", -"o c #7C5A09", -"O c #7F5F10", -"+ c #815E0B", -"@ c #85620C", -"# c #89650F", -"$ c #856313", -"% c #896614", -"& c #8D6913", -"* c #886718", -"= c #8D6B1B", -"- c #926D14", -"; c #926E1B", -": c #967116", -"> c #997317", -", c #95711E", -"< c #9B7419", -"1 c #9F781B", -"2 c #A27B1D", -"3 c #8F6F22", -"4 c #926F21", -"5 c #947323", -"6 c #9A7623", -"7 c #9D7925", -"8 c #957628", -"9 c #9A7729", -"0 c #9D7B2B", -"q c #9D7F33", -"w c #A47D23", -"e c #A97F27", -"r c #A37E2B", -"t c #9F8030", -"y c #A78021", -"u c #AC8425", -"i c #A5802D", -"p c #AC842B", -"a c #AF8829", -"s c #B2872C", -"d c #B28B2D", -"f c #A68333", -"g c #AA8633", -"h c #AD8A36", -"j c #A4863A", -"k c #A88638", -"l c #A7893B", -"z c #AC8B3B", -"x c #B28732", -"c c #B48C32", -"v c #B98E34", -"b c #B28D3B", -"n c #B88F3C", -"m c #B69033", -"M c #BD9235", -"N c #B4913D", -"B c #BC943A", -"V c #BE993C", -"C c #C19336", -"Z c #C1953B", -"A c #C49A3C", -"S c #C99C3D", -"D c #CDA13F", -"F c #D0A33F", -"G c #A88B40", -"H c #B08F40", -"J c #AE9142", -"K c #AE944C", -"L c #B49443", -"P c #BB9542", -"I c #B49946", -"U c #BD9846", -"Y c #B3964C", -"T c #BB974A", -"R c #B6994A", -"E c #BF9C4A", -"W c #B69B53", -"Q c #B99D53", -"! c #BCA055", -"~ c #BDA25A", -"^ c #C49742", -"/ c #C49C43", -"( c #CB9E42", -") c #C49D4B", -"_ c #C99E4C", -"` c #C29F52", -"' c #C5A244", -"] c #CDA245", -"[ c #C5A34C", -"{ c #CCA34B", -"} c #CCA94D", -"| c #D2A445", -" . c #D1A54B", -".. c #D5AA4E", -"X. c #DBAF4F", -"o. c #C6A352", -"O. c #CBA554", -"+. c #C5AA57", -"@. c #CEAC54", -"#. c #C4A65A", -"$. c #CDA458", -"%. c #C2A85F", -"&. c #CEAA5B", -"*. c #D0A550", -"=. c #D4AB53", -"-. c #DBAE53", -";. c #D0A75B", -":. c #D4AC5A", -">. c #D9AE5C", -",. c #CEB25E", -"<. c #D4B156", -"1. c #DDB156", -"2. c #D4B25C", -"3. c #DCB35D", -"4. c #D7B85C", -"5. c #DCBA5E", -"6. c #E2B355", -"7. c #E2B65B", -"8. c #E4BA5D", -"9. c #EABD5E", -"0. c #C5AA62", -"q. c #CCAE63", -"w. c #C6AE69", -"e. c #D5AF62", -"r. c #CEB167", -"t. c #CCB36C", -"y. c #D5B162", -"u. c #DCB462", -"i. c #D7B964", -"p. c #DCBC64", -"a. c #D2B66B", -"s. c #DCB669", -"d. c #D7BE69", -"f. c #DFB86A", -"g. c #D0B771", -"h. c #D2BA74", -"j. c #D5BE78", -"k. c #E1B766", -"l. c #E4BB63", -"z. c #E9BE63", -"x. c #E3BB6A", -"c. c #E9BF6A", -"v. c #E1BE72", -"b. c #DDC16B", -"n. c #DAC27E", -"m. c #E4C164", -"M. c #ECC264", -"N. c #E4C36B", -"B. c #EBC36C", -"V. c #E7C96F", -"C. c #EECA6E", -"Z. c #F1C564", -"A. c #F1C76A", -"S. c #F5CB6C", -"D. c #FACE6D", -"F. c #F4D06F", -"G. c #FCD06E", -"H. c #E5C371", -"J. c #EDC573", -"K. c #E4CA73", -"L. c #ECCC74", -"P. c #E7CF7A", -"I. c #EBCD7A", -"U. c #F3CD73", -"Y. c #F8CE71", -"T. c #F3CD7A", -"R. c #EDD076", -"E. c #EDD17B", -"W. c #F4D274", -"Q. c #FBD274", -"!. c #FED977", -"~. c #F3D47B", -"^. c #FDD47A", -"/. c #F5DA7C", -"(. c #FDDA7C", -"). c #FFE07F", -"_. c #DBC481", -"`. c #DFC885", -"'. c #E1CA86", -"]. c #EACC80", -"[. c #E4CD8A", -"{. c #EED383", -"}. c #E7D18F", -"|. c #EAD38C", -" X c #F4D680", -".X c #FDD780", -"XX c #F5DA83", -"oX c #FCDC84", -"OX c #F5DB8A", -"+X c #FADE89", -"@X c #EAD492", -"#X c #EED896", -"$X c #EFDA9A", -"%X c #F1DD9D", -"&X c #FDE283", -"*X c #F6E18D", -"=X c #FEE48D", -"-X c #FFE692", -";X c #FFE894", -":X c #FBE799", -">X c #FFEA98", -",X c #F6E2A3", -".J..X.X.X.X(.W.Z.C.&X;X;X;X;X-X-X-X<.u u < 3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3Xu u c oX=X=X=X=X=X=X=Xl.Z C M M C C v v v s w = '.2X2X2X5 $ = 2X2X2X}.5 g ) u./.+X+X=X=X=X&XW.Z.F.=X;X;X;X;X-X-X*XV u y @ X 3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3Xu u u N.-X-X-X-X=X=X=XB.Z M C v v s e e e e w > % `.2X2X2X= + % 2X2X2X}.= r L 4.E.OX+X-X=X=X&X).W.M.R.;X;X;X-X-X-X;XR.u u y 3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3Xu u U -X-X-X-X-X-X=XW.^ C C C x e e r 6 5 4 ; = $ `.2X2X2X= O = 2X2X2X}.O = t Q ,.b.P./.*X=X&X&X).F.M.W.;X;X;X;X&X-X&X} u u O 3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3Xu u u R.-X-X-X-X-X-X=X=.{ ^ Z C x n 2X2X.>.>.=.=._ n b 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X:XI N +.V./.).).F.F.9.W.;X=X;X-X-X-XR.u u > 3X3X3X3X3X3X3X3X", -"3X3X3X3X3Xu u d =X;X-X-X-X-X-Xx.>.>.>.>.>...^ P 2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X2X,Xl N 4.R.!.!.!.G.Z.M.&X;X=X=X-X-X-XB a u 3X3X3X3X3X3X3X", -"3X3X3X3X3Xu u @.;X;X-X;X;X;XXX>.:.>.>.>.>.>._ P ` Y Y W _.2X2X2X2X2X2X@XW W ~ 0.t.'..>.>.>.>.>.>.=._ P z r 4 8 2X2X2X2X2X2X_.. $ , 6 1 3 t ~ 1X2X2X2X2X2X2X2Xt B 5.G.!.!.G.G.M.9.&X;X=X-X-X=X/.u u > 3X3X3X3X3X3X3X", -"3X3X3X3Xu u d =X;X;X=X;X;X=X3.>.>.>.e.>.3.3.>.:.*._ P r 9 2X2X2X2X2X1Xn.@ , c B N m h 8 ~ 2X2X2X2X2X2X2XI h <.F.!.G.G.F.M.9.W.;X=X-X-X=X=Xm u y . 3X3X3X3X3X3X", -"3X3X3X3Xu u ' -X-X>X-X-X-X X>.>.>.>.>.>.>.u.u.u.u.3.$.P f 2X2X2X2X2X2X_.$ i / -.<.8.} h 8 1X2X2X2X2X2X2X! i <.S.G.G.G.G.Z.9.Z.=X-X=X-X&X-X} u u X 3X3X3X3X3X3X", -"3X3X3X3Xu u 4.-X-X-X-X-X-XJ.3.>.>.k.k.k.k.k.u.k.u.u.:.U k 2X2X2X2X2X1X_.% f } 8.Z.F.8.U 8 ,X2X2X2X2X2X2XI g } Z.D.G.D.G.D.Z.9.&X-X=X=X=X-Xm.u u @ 3X3X3X3X3X3X", -"3X3X3X3Xu u K.;X-X;X-X>X-Xk.3.k.k.k.k.k.k.k.k.k.k.u.e.U k 2X2X2X2X2X2X_.% f [ 8.F.M.<.b i 2X2X2X2X2X2X2Xt a X.Z.D.D.D.G.G.Z.9./.=X-X=X=X=XR.u u & 3X3X3X3X3X3X", -"3X3X3X3Xu u E.;X-X;X-X-X=Xl.l.x.c.k.x.k.k.x.x.v.x.x.u.) z 2X2X2X2X2X2X_.$ 7 L <.<.} N 6 h.2X2X2X2X2X2X_.: V 1.S.D.D.G.D.S.M.6.W.-X=X-X=X=X&Xu u > X 3X3X3X3X3X", -"3X3X3Xu a u =X;X;X;X;X;XoX7.z.c.c.c.c.c.c.c.c.c.x.k.u.) z 2X2X2X2X2X2Xn.o = i N h i l n.2X2X2X2X2X2X.o.L r [.2X2X2X9 = 8 2X2X2X}.4 r ^ _ *.*._ ) ) ^ ^ ^ O.oX=X-X-X-X-X-X-X<.u u : . 3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3Xy u u i.=X=X=X=X=X-X*X=XW.9.M.A.B.3.5.5.;.U f [.2X2X2Xq 4 8 2X2X2X}.r q _ _ ;.;.*._ _ ` _ e.+X-X-X-X-X-X-X-XR.a u 2 3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3Xu u u K.=X=X=X-X=X=X=X=XXXz.M.8.5.8.u.:.) h }.2X2X2Xj r f 2X2X2X@Xq T _ e.e.u.e.;.$.$.b.-X-X-X=X;X=X;X-X&Xa a u + 3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3Xu u d ~.=X=X=X=X=X-X=X-X+XC.3.5.7.7.2.@.) q.r.q.q.H H L g.r.w.q.T ` e.k.v.k.k.s.s.{.-X-X;X-X;X;X;X;X*XV u u & . 3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X2 u u c XX-X=X=X=X=X-X=X-X-X Xl.7.7.u.2.$.o.[ [ o.O.$.&.&.` ` ` q.s.k.v.k.k.x.{.%X>X>X>X;X>X;X>X>X*XV u u > 3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X2 u u m ~.=X-X-X-X=X-X-X-X-X-X Xc.7.5.u.3.e.y.u.s.f.k.s.e.e.s.s.k.k.k.v. X:X>X>X>X>X>X>X;X>X>X*XV u u < 3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u d R.-X=X-X=X-X-X-X-X-X-X-X+XI.v.u.s.l.k.k.x.x.x.s.s.s.s.j.].+X>X>X>X>X>X:X>X>X>X>X>XOXV u u 1 3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u a p.-X-X-X;X;X;X-X-X-X:X-X-X-X-XOX XL.J.J.J.L.I.].OX:X>X-X>X>X-X>X>X>X>X>X>X>X>XK.a a u < 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u @.=X;X;X>X;X-X-X>X-X-X-X-X;X-X-X-X-X-X>X>X-X>X-X>X>X>X>X;X>X>X>X-X>X-X-X:X<.u u u > 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u m n.>X;X>X>X-X-X-X-X>X-X-X-X;X;X;X-X-X-X-X-X>X-X-X>X-X>X>X-X>X>X>X>XK.B u u u & 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xw u u u / {.>X>X-X-X-X-X-X-X-X-X-X-X;X-X-X;X:X-X-X>X-X:X>X;X;X>X;X;X{.[ u u u w + 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X2 u u u u ) K.-X-X-X-X:X-X-X-X-X-X-X-X-X-X-X-X-X>X-X-X-X-X-X-XE.[ u u u u - . 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X1 u u u u m 2.E.-X+X:X-X-X-X-X-X-X-X-X-X:X-X-X-X;X-XOXi.B u u u u 1 o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X> u u u u u v [ l.I.OX-X-X-X-X-X-X-X-X+XI.f.@.m u u u u u 1 + o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X& 2 u u u u u u u d B V V V V B d u u u u u u u y - . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X+ - 1 u u u u u u u a u u u u u u u u 2 - o o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo . X # - > 1 2 2 2 1 2 > - # o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3Xo o . o 3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X", -"3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X3X" -}; diff --git a/share/pixmaps/check.ico b/share/pixmaps/check.ico deleted file mode 100644 index 0c4e6e8147..0000000000 Binary files a/share/pixmaps/check.ico and /dev/null differ diff --git a/share/pixmaps/favicon.ico b/share/pixmaps/favicon.ico deleted file mode 100644 index d249e41feb..0000000000 Binary files a/share/pixmaps/favicon.ico and /dev/null differ diff --git a/share/pixmaps/nsis-header.bmp b/share/pixmaps/nsis-header.bmp deleted file mode 100644 index 5eb10ae773..0000000000 Binary files a/share/pixmaps/nsis-header.bmp and /dev/null differ diff --git a/share/pixmaps/nsis-wizard.bmp b/share/pixmaps/nsis-wizard.bmp deleted file mode 100644 index 330de6bc91..0000000000 Binary files a/share/pixmaps/nsis-wizard.bmp and /dev/null differ diff --git a/share/pixmaps/send16.bmp b/share/pixmaps/send16.bmp deleted file mode 100644 index 676b5c4b49..0000000000 Binary files a/share/pixmaps/send16.bmp and /dev/null differ diff --git a/share/pixmaps/send16mask.bmp b/share/pixmaps/send16mask.bmp deleted file mode 100644 index 06c747f934..0000000000 Binary files a/share/pixmaps/send16mask.bmp and /dev/null differ diff --git a/share/pixmaps/send16masknoshadow.bmp b/share/pixmaps/send16masknoshadow.bmp deleted file mode 100644 index faf24e0d8a..0000000000 Binary files a/share/pixmaps/send16masknoshadow.bmp and /dev/null differ diff --git a/share/pixmaps/send20.bmp b/share/pixmaps/send20.bmp deleted file mode 100644 index 2b90422b38..0000000000 Binary files a/share/pixmaps/send20.bmp and /dev/null differ diff --git a/share/pixmaps/send20mask.bmp b/share/pixmaps/send20mask.bmp deleted file mode 100644 index f124d0da08..0000000000 Binary files a/share/pixmaps/send20mask.bmp and /dev/null differ diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py deleted file mode 100755 index 771f28ab0a..0000000000 --- a/share/qt/extract_strings_qt.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/python -''' -Extract _("...") strings for translation and convert to Qt4 stringdefs so that -they can be picked up by Qt linguist. -''' -from subprocess import Popen, PIPE -import glob - -OUT_CPP="src/qt/bitcoinstrings.cpp" -EMPTY=['""'] - -def parse_po(text): - """ - Parse 'po' format produced by xgettext. - Return a list of (msgid,msgstr) tuples. - """ - messages = [] - msgid = [] - msgstr = [] - in_msgid = False - in_msgstr = False - - for line in text.split('\n'): - line = line.rstrip('\r') - if line.startswith('msgid '): - if in_msgstr: - messages.append((msgid, msgstr)) - in_msgstr = False - # message start - in_msgid = True - - msgid = [line[6:]] - elif line.startswith('msgstr '): - in_msgid = False - in_msgstr = True - msgstr = [line[7:]] - elif line.startswith('"'): - if in_msgid: - msgid.append(line) - if in_msgstr: - msgstr.append(line) - - if in_msgstr: - messages.append((msgid, msgstr)) - - return messages - -files = glob.glob('src/*.cpp') + glob.glob('src/*.h') - -# xgettext -n --keyword=_ $FILES -child = Popen(['xgettext','--output=-','-n','--keyword=_'] + files, stdout=PIPE) -(out, err) = child.communicate() - -messages = parse_po(out) - -f = open(OUT_CPP, 'w') -f.write("""#include -// Automatically generated by extract_strings.py -#ifdef __GNUC__ -#define UNUSED __attribute__((unused)) -#else -#define UNUSED -#endif -""") -f.write('static const char UNUSED *bitcoin_strings[] = {') -for (msgid, msgstr) in messages: - if msgid != EMPTY: - f.write('QT_TRANSLATE_NOOP("bitcoin-core", %s),\n' % ('\n'.join(msgid))) -f.write('};') -f.close() diff --git a/share/qt/img/reload.xcf b/share/qt/img/reload.xcf deleted file mode 100644 index dc8be62831..0000000000 Binary files a/share/qt/img/reload.xcf and /dev/null differ diff --git a/share/qt/make_spinner.py b/share/qt/make_spinner.py deleted file mode 100755 index 136aff3cb7..0000000000 --- a/share/qt/make_spinner.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# W.J. van der Laan, 2011 -# Make spinning .mng animation from a .png -# Requires imagemagick 6.7+ -from __future__ import division -from os import path -from PIL import Image -from subprocess import Popen - -SRC='img/reload_scaled.png' -DST='../../src/qt/res/movies/update_spinner.mng' -TMPDIR='/tmp' -TMPNAME='tmp-%03i.png' -NUMFRAMES=35 -FRAMERATE=10.0 -CONVERT='convert' -CLOCKWISE=True -DSIZE=(16,16) - -im_src = Image.open(SRC) - -if CLOCKWISE: - im_src = im_src.transpose(Image.FLIP_LEFT_RIGHT) - -def frame_to_filename(frame): - return path.join(TMPDIR, TMPNAME % frame) - -frame_files = [] -for frame in xrange(NUMFRAMES): - rotation = (frame + 0.5) / NUMFRAMES * 360.0 - if CLOCKWISE: - rotation = -rotation - im_new = im_src.rotate(rotation, Image.BICUBIC) - im_new.thumbnail(DSIZE, Image.ANTIALIAS) - outfile = frame_to_filename(frame) - im_new.save(outfile, 'png') - frame_files.append(outfile) - -p = Popen([CONVERT, "-delay", str(FRAMERATE), "-dispose", "2"] + frame_files + [DST]) -p.communicate() - - - diff --git a/share/qt/make_windows_icon.sh b/share/qt/make_windows_icon.sh deleted file mode 100755 index f775a30580..0000000000 --- a/share/qt/make_windows_icon.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -# create multiresolution windows icon -ICON_DST=../../src/qt/res/icons/novacoin.ico - -convert ../../src/qt/res/icons/novacoin-16.png ../../src/qt/res/icons/novacoin-32.png ../../src/qt/res/icons/novacoin-48.png ${ICON_DST} diff --git a/share/setup.nsi b/share/setup.nsi deleted file mode 100644 index accce9bc1d..0000000000 --- a/share/setup.nsi +++ /dev/null @@ -1,163 +0,0 @@ -Name NovaCoin - -RequestExecutionLevel highest -SetCompressor /SOLID lzma - -# General Symbol Definitions -!define REGKEY "SOFTWARE\$(^Name)" -!define VERSION 0.3.0 -!define COMPANY "NovaCoin project" -!define URL http://www.novacoin.ru/ - -# MUI Symbol Definitions -!define MUI_ICON "../share/pixmaps/novacoin.ico" -!define MUI_WELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp" -!define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_RIGHT -!define MUI_HEADERIMAGE_BITMAP "../share/pixmaps/nsis-header.bmp" -!define MUI_FINISHPAGE_NOAUTOCLOSE -!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM -!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY} -!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup -!define MUI_STARTMENUPAGE_DEFAULTFOLDER NovaCoin -#!define MUI_FINISHPAGE_RUN $INSTDIR\novacoin-qt.exe -!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" -!define MUI_UNWELCOMEFINISHPAGE_BITMAP "../share/pixmaps/nsis-wizard.bmp" -!define MUI_UNFINISHPAGE_NOAUTOCLOSE - -# Included files -!include Sections.nsh -!include MUI2.nsh - -# Variables -Var StartMenuGroup - -# Installer pages -!insertmacro MUI_PAGE_WELCOME -!insertmacro MUI_PAGE_DIRECTORY -!insertmacro MUI_PAGE_STARTMENU Application $StartMenuGroup -!insertmacro MUI_PAGE_INSTFILES -!insertmacro MUI_PAGE_FINISH -!insertmacro MUI_UNPAGE_CONFIRM -!insertmacro MUI_UNPAGE_INSTFILES - -# Installer languages -!insertmacro MUI_LANGUAGE English - -# Installer attributes -OutFile novacoin-0.3.0-win32-setup.exe -InstallDir $PROGRAMFILES\NovaCoin -CRCCheck on -XPStyle on -BrandingText " " -ShowInstDetails show -VIProductVersion 0.3.0.0 -VIAddVersionKey ProductName NovaCoin -VIAddVersionKey ProductVersion "${VERSION}" -VIAddVersionKey CompanyName "${COMPANY}" -VIAddVersionKey CompanyWebsite "${URL}" -VIAddVersionKey FileVersion "${VERSION}" -VIAddVersionKey FileDescription "" -VIAddVersionKey LegalCopyright "" -InstallDirRegKey HKCU "${REGKEY}" Path -ShowUninstDetails show - -# Installer sections -Section -Main SEC0000 - SetOutPath $INSTDIR - SetOverwrite on - #File ../release/novacoin-qt.exe - File /oname=license.txt ../COPYING - File /oname=readme.txt ../doc/README_windows.txt - SetOutPath $INSTDIR\daemon - File ../src/novacoind.exe - SetOutPath $INSTDIR\src - File /r /x *.exe /x *.o ../src\*.* - SetOutPath $INSTDIR - WriteRegStr HKCU "${REGKEY}\Components" Main 1 - - # Remove old wxwidgets-based-bitcoin executable and locales: - #Delete /REBOOTOK $INSTDIR\novacoin.exe - #RMDir /r /REBOOTOK $INSTDIR\locale -SectionEnd - -Section -post SEC0001 - WriteRegStr HKCU "${REGKEY}" Path $INSTDIR - SetOutPath $INSTDIR - WriteUninstaller $INSTDIR\uninstall.exe - !insertmacro MUI_STARTMENU_WRITE_BEGIN Application - CreateDirectory $SMPROGRAMS\$StartMenuGroup - CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall NovaCoin.lnk" $INSTDIR\uninstall.exe - !insertmacro MUI_STARTMENU_WRITE_END - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayVersion "${VERSION}" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" Publisher "${COMPANY}" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" URLInfoAbout "${URL}" - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayIcon $INSTDIR\uninstall.exe - WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe - WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1 - WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1 - - # bitcoin: URI handling disabled for 0.6.0 - # WriteRegStr HKCR "bitcoin" "URL Protocol" "" - # WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin" - # WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe - # WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "$$1"' -SectionEnd - -# Macro for selecting uninstaller sections -!macro SELECT_UNSECTION SECTION_NAME UNSECTION_ID - Push $R0 - ReadRegStr $R0 HKCU "${REGKEY}\Components" "${SECTION_NAME}" - StrCmp $R0 1 0 next${UNSECTION_ID} - !insertmacro SelectSection "${UNSECTION_ID}" - GoTo done${UNSECTION_ID} -next${UNSECTION_ID}: - !insertmacro UnselectSection "${UNSECTION_ID}" -done${UNSECTION_ID}: - Pop $R0 -!macroend - -# Uninstaller sections -Section /o -un.Main UNSEC0000 - #Delete /REBOOTOK $INSTDIR\novacoin-qt.exe - Delete /REBOOTOK $INSTDIR\license.txt - Delete /REBOOTOK $INSTDIR\readme.txt - RMDir /r /REBOOTOK $INSTDIR\daemon - RMDir /r /REBOOTOK $INSTDIR\src - DeleteRegValue HKCU "${REGKEY}\Components" Main -SectionEnd - -Section -un.post UNSEC0001 - DeleteRegKey HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" - Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Uninstall NovaCoin.lnk" - #Delete /REBOOTOK "$SMPROGRAMS\$StartMenuGroup\Bitcoin.lnk" - #Delete /REBOOTOK "$SMSTARTUP\Bitcoin.lnk" - Delete /REBOOTOK $INSTDIR\uninstall.exe - Delete /REBOOTOK $INSTDIR\debug.log - Delete /REBOOTOK $INSTDIR\db.log - DeleteRegValue HKCU "${REGKEY}" StartMenuGroup - DeleteRegValue HKCU "${REGKEY}" Path - DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components" - DeleteRegKey /IfEmpty HKCU "${REGKEY}" - DeleteRegKey HKCR "novacoin" - RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup - RmDir /REBOOTOK $INSTDIR - Push $R0 - StrCpy $R0 $StartMenuGroup 1 - StrCmp $R0 ">" no_smgroup -no_smgroup: - Pop $R0 -SectionEnd - -# Installer functions -Function .onInit - InitPluginsDir -FunctionEnd - -# Uninstaller functions -Function un.onInit - ReadRegStr $INSTDIR HKCU "${REGKEY}" Path - !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuGroup - !insertmacro SELECT_UNSECTION Main ${UNSEC0000} -FunctionEnd diff --git a/share/ui.rc b/share/ui.rc deleted file mode 100644 index 063641cba2..0000000000 --- a/share/ui.rc +++ /dev/null @@ -1,15 +0,0 @@ -bitcoin ICON "pixmaps/bitcoin.ico" - -#include "wx/msw/wx.rc" - -check ICON "pixmaps/check.ico" -send16 BITMAP "pixmaps/send16.bmp" -send16mask BITMAP "pixmaps/send16mask.bmp" -send16masknoshadow BITMAP "pixmaps/send16masknoshadow.bmp" -send20 BITMAP "pixmaps/send20.bmp" -send20mask BITMAP "pixmaps/send20mask.bmp" -addressbook16 BITMAP "pixmaps/addressbook16.bmp" -addressbook16mask BITMAP "pixmaps/addressbook16mask.bmp" -addressbook20 BITMAP "pixmaps/addressbook20.bmp" -addressbook20mask BITMAP "pixmaps/addressbook20mask.bmp" -favicon ICON "pixmaps/favicon.ico" diff --git a/shadow.qrc b/spectre.qrc similarity index 95% rename from shadow.qrc rename to spectre.qrc index fc9a0120bc..2ea820c97b 100644 --- a/shadow.qrc +++ b/spectre.qrc @@ -1,11 +1,21 @@ + + + + + src/qt/res/assets/css/contextMenu.css src/qt/res/assets/css/font-awesome-buttons.min.css src/qt/res/assets/css/font-awesome.min.css - src/qt/res/assets/css/framework-icons.min.css + src/qt/res/assets/css/font-montserrat.css + src/qt/res/assets/css/footable.core.css + src/qt/res/assets/css/footable.metro.css + src/qt/res/assets/css/framework-icons.css src/qt/res/assets/css/framework.min.css src/qt/res/assets/css/normalize.css - src/qt/res/assets/css/shadow.min.css + src/qt/res/assets/css/spectre.min.css + src/qt/res/assets/fonts/chinese_s.otf + src/qt/res/assets/fonts/chinese_t.otf src/qt/res/assets/fonts/FontAwesome/FontAwesome.otf src/qt/res/assets/fonts/FontAwesome/fontawesome-webfont.eot src/qt/res/assets/fonts/FontAwesome/fontawesome-webfont.svg @@ -19,67 +29,21 @@ src/qt/res/assets/fonts/Framework-icon/framework-icon.svg src/qt/res/assets/fonts/Framework-icon/framework-icon.ttf src/qt/res/assets/fonts/Framework-icon/framework-icon.woff - src/qt/res/assets/fonts/Montserrat/Montserrat-Bold.ttf - src/qt/res/assets/fonts/Montserrat/montserrat-bold-webfont.svg - src/qt/res/assets/fonts/Montserrat/montserrat-bold-webfont.woff - src/qt/res/assets/fonts/Montserrat/montserrat-bold-webfont.woff2 - src/qt/res/assets/fonts/Montserrat/Montserrat-Regular.ttf - src/qt/res/assets/fonts/Montserrat/montserrat-regular-webfont.svg - src/qt/res/assets/fonts/Montserrat/montserrat-regular-webfont.woff - src/qt/res/assets/fonts/Montserrat/montserrat-regular-webfont.woff2 - src/qt/res/assets/fonts/OpenSans/OpenSans-BoldItalic.ttf - src/qt/res/assets/fonts/OpenSans/OpenSans-Bold.ttf - src/qt/res/assets/fonts/OpenSans/OpenSans-Italic.ttf - src/qt/res/assets/fonts/OpenSans/OpenSans-LightItalic.ttf - src/qt/res/assets/fonts/OpenSans/OpenSans-Light.ttf - src/qt/res/assets/fonts/OpenSans/OpenSans-Regular.ttf - src/qt/res/assets/icons/chat_bubble.png + src/qt/res/assets/fonts/japanese.otf + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-300.woff + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-300.woff2 + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-500.woff + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-500.woff2 + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-700.woff + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-700.woff2 + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-regular.woff + src/qt/res/assets/fonts/Montserrat/montserrat-v14-latin-regular.woff2 src/qt/res/assets/icons/chevron.png - src/qt/res/assets/icons/connect_0.png - src/qt/res/assets/icons/connect_1.png - src/qt/res/assets/icons/connect_2.png - src/qt/res/assets/icons/connect_3.png - src/qt/res/assets/icons/connect_4.png - src/qt/res/assets/icons/connect_5.png - src/qt/res/assets/icons/connect_6.png - src/qt/res/assets/icons/delete.png - src/qt/res/assets/icons/i2p_off.png - src/qt/res/assets/icons/i2p.png - src/qt/res/assets/icons/lock_off.png - src/qt/res/assets/icons/lock.png - src/qt/res/assets/icons/lock_stake.png src/qt/res/assets/icons/noti-cross-2x.png src/qt/res/assets/icons/noti-cross.png - src/qt/res/assets/icons/notsynced.png - src/qt/res/assets/icons/search_icon.png - src/qt/res/assets/icons/shadowcoin-128.png - src/qt/res/assets/icons/shadowcoin-16.png - src/qt/res/assets/icons/shadowcoin-32.png - src/qt/res/assets/icons/shadowcoin-48.png - src/qt/res/assets/icons/shadowcoin-64.png - src/qt/res/assets/icons/shadowcoin-80.png - src/qt/res/assets/icons/shadowcoin.ico - src/qt/res/assets/icons/shadowcoin_icon.png - src/qt/res/assets/icons/shadowcoin.png - src/qt/res/assets/icons/shadow.icns - src/qt/res/assets/icons/staking_off.png - src/qt/res/assets/icons/staking.png - src/qt/res/assets/icons/synced.png - src/qt/res/assets/icons/syncing.gif - src/qt/res/assets/icons/syncing_static.gif + src/qt/res/assets/icons/qrcode.png src/qt/res/assets/icons/top_tray_2x.png src/qt/res/assets/icons/top_tray.png - src/qt/res/assets/icons/tor_off.png - src/qt/res/assets/icons/tor.png - src/qt/res/assets/icons/transaction0.png - src/qt/res/assets/icons/tx_inout.png - src/qt/res/assets/icons/tx_input.png - src/qt/res/assets/icons/tx_mined.png - src/qt/res/assets/icons/tx_output.png - src/qt/res/assets/img/about.png - src/qt/res/assets/img/avatars/kewde.png - src/qt/res/assets/img/avatars/litebit.png - src/qt/res/assets/img/linear_gradient.png src/qt/res/assets/img/progress/progress-bar-complete.svg src/qt/res/assets/img/progress/progress-bar-danger.svg src/qt/res/assets/img/progress/progress-bar-info.svg @@ -98,25 +62,20 @@ src/qt/res/assets/img/progress/progress-circle-primary.svg src/qt/res/assets/img/progress/progress-circle-success.svg src/qt/res/assets/img/progress/progress-circle-warning.svg - src/qt/res/assets/img/sdc-vertical.png - src/qt/res/assets/img/shadow_logo.png - src/qt/res/assets/img/shoppingcart.png - src/qt/res/assets/img/splash.png src/qt/res/assets/js/navigation.min.js src/qt/res/assets/js/pages/send.min.js src/qt/res/assets/js/qrcode.min.js - src/qt/res/assets/js/shadow.min.js + src/qt/res/assets/js/spectre.min.js src/qt/res/assets/js/tooltip.min.js - src/qt/res/assets/plugins/boostrapv3/css/bootstrap.css.map - src/qt/res/assets/plugins/boostrapv3/css/bootstrap.min.css - src/qt/res/assets/plugins/boostrapv3/css/bootstrap-theme.css - src/qt/res/assets/plugins/boostrapv3/css/bootstrap-theme.css.map - src/qt/res/assets/plugins/boostrapv3/fonts/glyphicons-halflings-regular.eot - src/qt/res/assets/plugins/boostrapv3/fonts/glyphicons-halflings-regular.svg - src/qt/res/assets/plugins/boostrapv3/fonts/glyphicons-halflings-regular.ttf - src/qt/res/assets/plugins/boostrapv3/fonts/glyphicons-halflings-regular.woff - src/qt/res/assets/plugins/boostrapv3/fonts/glyphicons-halflings-regular.woff2 - src/qt/res/assets/plugins/boostrapv3/js/bootstrap.min.js + src/qt/res/assets/plugins/bootstrapv3/css/bootstrap.min.css + src/qt/res/assets/plugins/bootstrapv3/css/bootstrap-theme.css + src/qt/res/assets/plugins/bootstrapv3/css/bootstrap-theme.css.map + src/qt/res/assets/plugins/bootstrapv3/fonts/glyphicons-halflings-regular.eot + src/qt/res/assets/plugins/bootstrapv3/fonts/glyphicons-halflings-regular.svg + src/qt/res/assets/plugins/bootstrapv3/fonts/glyphicons-halflings-regular.ttf + src/qt/res/assets/plugins/bootstrapv3/fonts/glyphicons-halflings-regular.woff + src/qt/res/assets/plugins/bootstrapv3/fonts/glyphicons-halflings-regular.woff2 + src/qt/res/assets/plugins/bootstrapv3/js/bootstrap.min.js src/qt/res/assets/plugins/classie/classie.js src/qt/res/assets/plugins/contextMenu/contextMenu.css src/qt/res/assets/plugins/contextMenu/contextMenu.min.js @@ -1993,95 +1952,76 @@ src/qt/res/assets/plugins/pnglib/pnglib.js src/qt/res/assets/plugins/qrcode/qrcode.min.js src/qt/res/assets/plugins/shajs/shajs.js + src/qt/res/assets/svg/alias-app.svg + src/qt/res/assets/svg/Alias-Horizontal-Reverse.svg + src/qt/res/assets/svg/Alias-Stacked-Reverse.svg + src/qt/res/assets/svg/Alias-Vertical-Reverse.svg + src/qt/res/assets/svg/connection-0.svg + src/qt/res/assets/svg/connection-10.svg + src/qt/res/assets/svg/connection-11.svg + src/qt/res/assets/svg/connection-12.svg + src/qt/res/assets/svg/connection-1.svg + src/qt/res/assets/svg/connection-2.svg + src/qt/res/assets/svg/connection-3.svg + src/qt/res/assets/svg/connection-4.svg + src/qt/res/assets/svg/connection-5.svg + src/qt/res/assets/svg/connection-6.svg + src/qt/res/assets/svg/connection-7.svg + src/qt/res/assets/svg/connection-8.svg + src/qt/res/assets/svg/connection-9.svg + src/qt/res/assets/svg/lock_off.svg + src/qt/res/assets/svg/lock_stake.svg + src/qt/res/assets/svg/lock.svg + src/qt/res/assets/svg/spinner.svg + src/qt/res/assets/svg/staking_off.svg + src/qt/res/assets/svg/staking.svg + src/qt/res/assets/svg/synced.svg + src/qt/res/assets/svg/syncing-0.svg + src/qt/res/assets/svg/syncing-100-bg.svg + src/qt/res/assets/svg/syncing-100.svg + src/qt/res/assets/svg/syncing-10.svg + src/qt/res/assets/svg/syncing-15.svg + src/qt/res/assets/svg/syncing-20.svg + src/qt/res/assets/svg/syncing-25.svg + src/qt/res/assets/svg/syncing-30.svg + src/qt/res/assets/svg/syncing-35.svg + src/qt/res/assets/svg/syncing-40.svg + src/qt/res/assets/svg/syncing-45.svg + src/qt/res/assets/svg/syncing-50.svg + src/qt/res/assets/svg/syncing-55.svg + src/qt/res/assets/svg/syncing-5.svg + src/qt/res/assets/svg/syncing-60.svg + src/qt/res/assets/svg/syncing-65.svg + src/qt/res/assets/svg/syncing-70.svg + src/qt/res/assets/svg/syncing-75.svg + src/qt/res/assets/svg/syncing-80.svg + src/qt/res/assets/svg/syncing-85.svg + src/qt/res/assets/svg/syncing-90.svg + src/qt/res/assets/svg/syncing-95.svg + src/qt/res/assets/svg/tor_off.svg + src/qt/res/assets/svg/tor.svg + src/qt/res/assets/svg/tx_contributed.svg + src/qt/res/assets/svg/tx_donated.svg + src/qt/res/assets/svg/tx_inout.svg + src/qt/res/assets/svg/tx_input.svg + src/qt/res/assets/svg/tx_output.svg + src/qt/res/assets/svg/tx_staked.svg src/qt/res/index.html - - src/qt/res/icons/shadowcoin-80.png - src/qt/res/icons/shadowcoin-80.png - src/qt/res/icons/shadowcoin-16.png - src/qt/res/icons/shadowcoin-16.png + src/qt/res/icons/export.png src/qt/res/icons/remove.png - src/qt/res/icons/tx_mined.png - src/qt/res/icons/tx_input.png - src/qt/res/icons/tx_output.png - src/qt/res/icons/tx_inout.png src/qt/res/icons/key.png src/qt/res/icons/debugwindow.png src/qt/res/icons/qrcode.png - src/qt/res/icons/history.png + src/qt/res/icons/alias-app.ico + src/qt/res/icons/alias-app.ico + src/qt/res/icons/cmd_request.png + src/qt/res/icons/cmd_reply.png + src/qt/res/icons/cmd_reply.png + src/qt/res/icons/cmd_misc.png - - src/qt/res/images/about.png - src/qt/res/images/splash.png - - - src/qt/locale/umbra_af_ZA.qm - src/qt/locale/umbra_ar.qm - src/qt/locale/umbra_be_BY.qm - src/qt/locale/umbra_bg.qm - src/qt/locale/umbra_bs.qm - src/qt/locale/umbra_ca_ES.qm - src/qt/locale/umbra_ca.qm - src/qt/locale/umbra_ca@valencia.qm - src/qt/locale/umbra_cs.qm - src/qt/locale/umbra_cy.qm - src/qt/locale/umbra_da.qm - src/qt/locale/umbra_de.qm - src/qt/locale/umbra_el_GR.qm - src/qt/locale/umbra_el.qm - src/qt/locale/umbra_en.qm - src/qt/locale/umbra_eo.qm - src/qt/locale/umbra_es_CL.qm - src/qt/locale/umbra_es_DO.qm - src/qt/locale/umbra_es_MX.qm - src/qt/locale/umbra_es.qm - src/qt/locale/umbra_es_UY.qm - src/qt/locale/umbra_et.qm - src/qt/locale/umbra_eu_ES.qm - src/qt/locale/umbra_fa_IR.qm - src/qt/locale/umbra_fa.qm - src/qt/locale/umbra_fi.qm - src/qt/locale/umbra_fr_CA.qm - src/qt/locale/umbra_fr.qm - src/qt/locale/umbra_gl.qm - src/qt/locale/umbra_he.qm - src/qt/locale/umbra_hi_IN.qm - src/qt/locale/umbra_hr.qm - src/qt/locale/umbra_hu.qm - src/qt/locale/umbra_id_ID.qm - src/qt/locale/umbra_it.qm - src/qt/locale/umbra_ja.qm - src/qt/locale/umbra_ka.qm - src/qt/locale/umbra_kk_KZ.qm - src/qt/locale/umbra_ko_KR.qm - src/qt/locale/umbra_ky.qm - src/qt/locale/umbra_la.qm - src/qt/locale/umbra_lt.qm - src/qt/locale/umbra_lv_LV.qm - src/qt/locale/umbra_ms_MY.qm - src/qt/locale/umbra_nb.qm - src/qt/locale/umbra_nl.qm - src/qt/locale/umbra_pam.qm - src/qt/locale/umbra_pl.qm - src/qt/locale/umbra_pt_BR.qm - src/qt/locale/umbra_pt_PT.qm - src/qt/locale/umbra_ro_RO.qm - src/qt/locale/umbra_ru.qm - src/qt/locale/umbra_sah.qm - src/qt/locale/umbra_sk.qm - src/qt/locale/umbra_sl_SI.qm - src/qt/locale/umbra_sq.qm - src/qt/locale/umbra_sr.qm - src/qt/locale/umbra_sv.qm - src/qt/locale/umbra_th_TH.qm - src/qt/locale/umbra_tr.qm - src/qt/locale/umbra_uk.qm - src/qt/locale/umbra_ur_PK.qm - src/qt/locale/umbra_vi.qm - src/qt/locale/umbra_vi_VN.qm - src/qt/locale/umbra_zh_CN.qm - src/qt/locale/umbra_zh_HK.qm - src/qt/locale/umbra_zh_TW.qm + + src/qt/res/qml/main.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000..b217c311f5 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,707 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +############################################################################## +##### Some helper stuff ###################################################### + +# Configure a header file to pass some of the CMake settings +# to the source code like version and Git hash +configure_file( + "${CMAKE_CURRENT_LIST_DIR}/clientversion.h.in" + "${CMAKE_CURRENT_LIST_DIR}/clientversion.h" +) + + +############################################################################## +##### Setup a library with all the common content ############################ + +# Create dummy file since we want an empty shared library before linking +set(DUMMY_SOURCE ${CMAKE_BINARY_DIR}/dummy.c) +file(WRITE ${DUMMY_SOURCE} "") + +add_library(aliaswallet_lib + OBJECT + ${DUMMY_SOURCE}) + +target_link_libraries(aliaswallet_lib + Oracle::BerkeleyDB + leveldb::leveldb + OpenSSL::SSL + OpenSSL::Crypto + Boost::atomic + Boost::boost + Boost::chrono + Boost::date_time + Boost::filesystem + Boost::iostreams + Boost::program_options + Boost::regex + Boost::system + Boost::thread + ) + +target_include_directories(aliaswallet_lib + SYSTEM BEFORE PUBLIC + ${PROJECT_BINARY_DIR}/usr/local/include + ${PROJECT_BINARY_DIR}/libdb/libdb-install/include + ${OPENSSL_INCLUDE_DIR} + ${BERKELEYDB_INCLUDE_DIR} + ${LEVELDB_INCLUDE_DIR} + ) + +# Common sources +target_sources(aliaswallet_lib + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/addrman.h + ${CMAKE_CURRENT_LIST_DIR}/alert.h + ${CMAKE_CURRENT_LIST_DIR}/allocators.h + ${CMAKE_CURRENT_LIST_DIR}/anonymize.h + ${CMAKE_CURRENT_LIST_DIR}/base58.h + ${CMAKE_CURRENT_LIST_DIR}/bignum.h + ${CMAKE_CURRENT_LIST_DIR}/bloom.h + ${CMAKE_CURRENT_LIST_DIR}/chainparams.h + ${CMAKE_CURRENT_LIST_DIR}/chainparamsseeds.h + ${CMAKE_CURRENT_LIST_DIR}/checkpoints.h + ${CMAKE_CURRENT_LIST_DIR}/clientversion.h + ${CMAKE_CURRENT_LIST_DIR}/coincontrol.h + ${CMAKE_CURRENT_LIST_DIR}/compat.h + ${CMAKE_CURRENT_LIST_DIR}/core.h + ${CMAKE_CURRENT_LIST_DIR}/crypter.h + ${CMAKE_CURRENT_LIST_DIR}/db.h + ${CMAKE_CURRENT_LIST_DIR}/eckey.h + ${CMAKE_CURRENT_LIST_DIR}/extkey.h + ${CMAKE_CURRENT_LIST_DIR}/hash.h + ${CMAKE_CURRENT_LIST_DIR}/init.h + ${CMAKE_CURRENT_LIST_DIR}/kernel.h + ${CMAKE_CURRENT_LIST_DIR}/key.h + ${CMAKE_CURRENT_LIST_DIR}/keystore.h + ${CMAKE_CURRENT_LIST_DIR}/main.h + ${CMAKE_CURRENT_LIST_DIR}/miner.h + ${CMAKE_CURRENT_LIST_DIR}/mruset.h + ${CMAKE_CURRENT_LIST_DIR}/netbase.h + ${CMAKE_CURRENT_LIST_DIR}/net.h + ${CMAKE_CURRENT_LIST_DIR}/pbkdf2.h + ${CMAKE_CURRENT_LIST_DIR}/protocol.h + ${CMAKE_CURRENT_LIST_DIR}/resource.h + ${CMAKE_CURRENT_LIST_DIR}/ringsig.h + ${CMAKE_CURRENT_LIST_DIR}/rpcclient.h + ${CMAKE_CURRENT_LIST_DIR}/rpcprotocol.h + ${CMAKE_CURRENT_LIST_DIR}/rpcserver.h + ${CMAKE_CURRENT_LIST_DIR}/script.h + ${CMAKE_CURRENT_LIST_DIR}/scrypt.h + ${CMAKE_CURRENT_LIST_DIR}/serialize.h + ${CMAKE_CURRENT_LIST_DIR}/smessage.h + ${CMAKE_CURRENT_LIST_DIR}/state.h + ${CMAKE_CURRENT_LIST_DIR}/stealth.h + ${CMAKE_CURRENT_LIST_DIR}/strlcpy.h + ${CMAKE_CURRENT_LIST_DIR}/sync.h + ${CMAKE_CURRENT_LIST_DIR}/threadsafety.h + ${CMAKE_CURRENT_LIST_DIR}/tinyformat.h + ${CMAKE_CURRENT_LIST_DIR}/txdb.h + ${CMAKE_CURRENT_LIST_DIR}/txdb-leveldb.h + ${CMAKE_CURRENT_LIST_DIR}/txmempool.h + ${CMAKE_CURRENT_LIST_DIR}/types.h + ${CMAKE_CURRENT_LIST_DIR}/interface.h + ${CMAKE_CURRENT_LIST_DIR}/uint256.h + ${CMAKE_CURRENT_LIST_DIR}/util.h + ${CMAKE_CURRENT_LIST_DIR}/version.h + ${CMAKE_CURRENT_LIST_DIR}/walletdb.h + ${CMAKE_CURRENT_LIST_DIR}/wallet.h + ${CMAKE_CURRENT_LIST_DIR}/shutdown.h + ${CMAKE_CURRENT_LIST_DIR}/validation_alias.h + ${CMAKE_CURRENT_LIST_DIR}/validation_connectblock_alias.h + ${CMAKE_CURRENT_LIST_DIR}/net_alias.h + ${CMAKE_CURRENT_LIST_DIR}/net_node_alias.h + ${CMAKE_CURRENT_LIST_DIR}/chainparams_compat.h + ${CMAKE_CURRENT_LIST_DIR}/chainparams_migration.h + ${CMAKE_CURRENT_LIST_DIR}/kernel/chainparams.h + ${CMAKE_CURRENT_LIST_DIR}/kernel/messagestartchars.h + ${CMAKE_CURRENT_LIST_DIR}/kernel/context.h + ${CMAKE_CURRENT_LIST_DIR}/node/context.h + ${CMAKE_CURRENT_LIST_DIR}/pos/kernel.h + ${CMAKE_CURRENT_LIST_DIR}/consensus/params.h + ${CMAKE_CURRENT_LIST_DIR}/util/chaintype.h + ${CMAKE_CURRENT_LIST_DIR}/util/vector.h + ${CMAKE_CURRENT_LIST_DIR}/util/hash_type.h + ${CMAKE_CURRENT_LIST_DIR}/chainparamsbase.h + + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/addrman.cpp + ${CMAKE_CURRENT_LIST_DIR}/alert.cpp + ${CMAKE_CURRENT_LIST_DIR}/anonymize.cpp + ${CMAKE_CURRENT_LIST_DIR}/bloom.cpp + ${CMAKE_CURRENT_LIST_DIR}/chainparams.cpp + ${CMAKE_CURRENT_LIST_DIR}/checkpoints.cpp + ${CMAKE_CURRENT_LIST_DIR}/core.cpp + ${CMAKE_CURRENT_LIST_DIR}/crypter.cpp + ${CMAKE_CURRENT_LIST_DIR}/db.cpp + ${CMAKE_CURRENT_LIST_DIR}/eckey.cpp + ${CMAKE_CURRENT_LIST_DIR}/extkey.cpp + ${CMAKE_CURRENT_LIST_DIR}/hash.cpp + ${CMAKE_CURRENT_LIST_DIR}/init.cpp + ${CMAKE_CURRENT_LIST_DIR}/kernel.cpp + ${CMAKE_CURRENT_LIST_DIR}/key.cpp + ${CMAKE_CURRENT_LIST_DIR}/keystore.cpp + ${CMAKE_CURRENT_LIST_DIR}/main.cpp + ${CMAKE_CURRENT_LIST_DIR}/miner.cpp + ${CMAKE_CURRENT_LIST_DIR}/netbase.cpp + ${CMAKE_CURRENT_LIST_DIR}/net.cpp + ${CMAKE_CURRENT_LIST_DIR}/noui.cpp + ${CMAKE_CURRENT_LIST_DIR}/pbkdf2.cpp + ${CMAKE_CURRENT_LIST_DIR}/protocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/ringsig.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcblockchain.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcclient.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcdump.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcextkey.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcmining.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcmnemonic.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcnet.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcprotocol.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcrawtransaction.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcserver.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcwallet.cpp + ${CMAKE_CURRENT_LIST_DIR}/script.cpp + ${CMAKE_CURRENT_LIST_DIR}/scrypt.cpp + ${CMAKE_CURRENT_LIST_DIR}/smessage.cpp + ${CMAKE_CURRENT_LIST_DIR}/state.cpp + ${CMAKE_CURRENT_LIST_DIR}/stealth.cpp + ${CMAKE_CURRENT_LIST_DIR}/sync.cpp + ${CMAKE_CURRENT_LIST_DIR}/txdb-leveldb.cpp + ${CMAKE_CURRENT_LIST_DIR}/txmempool.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/version.cpp + ${CMAKE_CURRENT_LIST_DIR}/wallet.cpp + ${CMAKE_CURRENT_LIST_DIR}/walletdb.cpp + ${CMAKE_CURRENT_LIST_DIR}/shutdown.cpp + ${CMAKE_CURRENT_LIST_DIR}/validation_alias.cpp + ${CMAKE_CURRENT_LIST_DIR}/validation_connectblock_alias.cpp + ${CMAKE_CURRENT_LIST_DIR}/net_alias.cpp + ${CMAKE_CURRENT_LIST_DIR}/net_node_alias.cpp + ${CMAKE_CURRENT_LIST_DIR}/chainparams_compat.cpp + ${CMAKE_CURRENT_LIST_DIR}/chainparams_migration.cpp + ${CMAKE_CURRENT_LIST_DIR}/kernel/chainparams.cpp + ${CMAKE_CURRENT_LIST_DIR}/kernel/context.cpp + ${CMAKE_CURRENT_LIST_DIR}/node/context.cpp + ${CMAKE_CURRENT_LIST_DIR}/pos/kernel.cpp + ${CMAKE_CURRENT_LIST_DIR}/util/chaintype.cpp + ${CMAKE_CURRENT_LIST_DIR}/chainparamsbase.cpp + ) + +add_subdirectory(json) +add_subdirectory(lz4) +add_subdirectory(wordlists) +add_subdirectory(xxhash) +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + add_subdirectory(win) +endif () + + + +############################################################################## +##### Setup and link the executables ######################################### + + +if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + message(STATUS "No daemon build on Mac") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + message(STATUS "No daemon build on Windows") +else() + # The daemon + add_executable(Aliaswalletd ${CMAKE_CURRENT_LIST_DIR}/spectrecoind.cpp) + + # Link the daemon as static binary + target_link_libraries(Aliaswalletd + OpenSSL::SSL + OpenSSL::Crypto + Oracle::BerkeleyDB + leveldb::leveldb + aliaswallet_lib + -static + ) + set_target_properties(Aliaswalletd PROPERTIES + OUTPUT_NAME aliaswalletd + ) +endif() + +if (ENABLE_GUI) + # The qm files are generated in the build tree, but the qrc file is inside the + # source directory and the path to resources are relative to the location of + # the qrc file itself. We use configure_file() to copy the qrc file in the build + # directory such that it can find the qm translations files. The qrc file is + # copied if it doesn't exist in the destination or if it is modified. + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/qt/alias_locale.qrc ${CMAKE_BINARY_DIR} COPYONLY) + + # Create only alias_en.ts new, to figure out if there are new strings to translate. + # If src/qt/locale/alias_en.ts is modified afterwards, there are new strings to + # translate. Any further steps on transifex.com. + # Don't forget to add new source files here too, if they contain strings to translate! + qt5_create_translation(QM_FILES + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/aboutdialog.ui + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/askpassphrasedialog.ui + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/coincontroldialog.ui + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/editaddressdialog.ui + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/rpcconsole.ui + ${CMAKE_CURRENT_LIST_DIR}/qt/forms/transactiondescdialog.ui + + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliasbridgestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliascorestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.h + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.h + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiconstants.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.h + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.h + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.h + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.h + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.h + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.h + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.h + + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.cpp + ${CMAKE_CURRENT_LIST_DIR}/init.cpp + ${CMAKE_CURRENT_LIST_DIR}/util.cpp + ${CMAKE_CURRENT_LIST_DIR}/main.cpp + ${CMAKE_CURRENT_LIST_DIR}/net.cpp + ${CMAKE_CURRENT_LIST_DIR}/rpcserver.cpp + ${CMAKE_CURRENT_LIST_DIR}/wallet.cpp + + ${CMAKE_CURRENT_LIST_DIR}/qt/locale/alias_en.ts + ) + + # Call lrelease on each translation file to create qm files. + qt5_add_translation(QM_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_af_ZA.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ar.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_be.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_bg.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_bs.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ca.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ca_ES.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_cs.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_cy.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_da.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_de.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_el.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_el_GR.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_eo.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_es.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_es_MX.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_et.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_eu_ES.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_fa.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_fa_IR.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_fi.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_fr.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_fr_CA.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_gl.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_he.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_hi_IN.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_hr.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_hu.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_id_ID.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_it.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ja.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ka.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_kk.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ko_KR.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ky.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_la.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_lt.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_lv_LV.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ms_MY.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_nb.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_nl.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_pl.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_pt_BR.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_pt_PT.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ro_RO.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ru.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_sk.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_sl_SI.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_sq.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_sr.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_sv.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_th.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_tr.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_uk.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_ur_PK.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_vi.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_vi_VN.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_zh_CN.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_zh_HK.ts + ${CMAKE_CURRENT_SOURCE_DIR}/qt/locale/alias_zh_TW.ts + ) + + if (ANDROID) + # Create a shared library 'libAliaswallet_.so' + add_library(Aliaswallet + SHARED + ../spectre.qrc + ${CMAKE_CURRENT_LIST_DIR}/qt/spectre.cpp + ${CMAKE_BINARY_DIR}/alias_locale.qrc + ${QM_FILES} + ) +# set_target_properties(Aliaswallet +# PROPERTIES +# OUTPUT_NAME "Aliaswallet_${CMAKE_ANDROID_ARCH}" +# ) + install(TARGETS Aliaswallet + LIBRARY DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/android-build/libs/${DCMAKE_ANDROID_ARCH_ABI}/" + ARCHIVE DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/android-build/libs/${DCMAKE_ANDROID_ARCH_ABI}/" + ) + + # Link the UI wallet + # QtWebEngine not static available, so no static binary here :-( + target_link_libraries(Aliaswallet + OpenSSL::SSL + OpenSSL::Crypto + Oracle::BerkeleyDB + leveldb::leveldb + aliaswallet_lib + Qt5::Core + Qt5::Widgets + Qt5::WebView + Qt5::WebChannel + Qt5::WebSockets + Qt5::Quick + Qt5::QuickWidgets + Qt5::Svg + Qt5::Concurrent + ) + + target_sources(Aliaswallet + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliasbridgestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliascorestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.h + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.h + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiconstants.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.h + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.h + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.h + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.h + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.h + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.h + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.h + + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.cpp + ) + else() + # The UI wallet + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # We have to reference the alias_locale.qrc copy in the build directory, not the + # original file in the source directory. We also add qm files to the target to + # create a dependency that will force rebuild in case the translation are + # updated. + add_executable(Aliaswallet + MACOSX_BUNDLE + ../spectre.qrc + ${CMAKE_CURRENT_LIST_DIR}/qt/spectre.cpp + ${CMAKE_BINARY_DIR}/alias_locale.qrc + ${QM_FILES} + ) + elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows") + # We have to reference the alias_locale.qrc copy in the build directory, not the + # original file in the source directory. We also add qm files to the target to + # create a dependency that will force rebuild in case the translation are + # updated. + add_executable(Aliaswallet + ../spectre.qrc + ${CMAKE_CURRENT_LIST_DIR}/qt/spectre.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/res/alias-qt.rc + ${CMAKE_BINARY_DIR}/alias_locale.qrc + ${QM_FILES} + ) + else() + # We have to reference the alias_locale.qrc copy in the build directory, not the + # original file in the source directory. We also add qm files to the target to + # create a dependency that will force rebuild in case the translation are + # updated. + add_executable(Aliaswallet + ../spectre.qrc + ${CMAKE_CURRENT_LIST_DIR}/qt/spectre.cpp + ${CMAKE_BINARY_DIR}/alias_locale.qrc + ${QM_FILES} + ) + endif() + + # Link the UI wallet + # QtWebEngine not static available, so no static binary here :-( + target_link_libraries(Aliaswallet + OpenSSL::SSL + OpenSSL::Crypto + Oracle::BerkeleyDB + leveldb::leveldb + aliaswallet_lib + Qt5::Core + Qt5::Widgets + Qt5::WebView + Qt5::WebChannel + Qt5::WebSockets + Qt5::Quick + Qt5::QuickWidgets + Qt5::Svg + Qt5::Concurrent + ) + + target_sources(Aliaswallet + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliasbridgestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/aliascorestrings.h + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.h + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.h + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.h + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiconstants.h + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.h + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.h + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.h + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.h + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.h + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.h + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.h + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.h + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.h + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.h + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.h + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.h + + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/qt/aboutdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/addresstablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/askpassphrasedialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinaddressvalidator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinamountfield.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/bitcoinunits.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/clientmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroldialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/coincontroltreewidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/csvmodelwriter.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/editaddressdialog.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/guiutil.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/monitoreddatamapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/notificator.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/optionsmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/paymentserver.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/peertablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvalidatedlineedit.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/qvaluecombobox.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/rpcconsole.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/scicon.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/setupwalletwizard.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectrebridge.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/spectregui.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/trafficgraphwidget.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiondesc.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactionrecord.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/transactiontablemodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/walletmodel.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websocketclientwrapper.cpp + ${CMAKE_CURRENT_LIST_DIR}/qt/websockettransport.cpp + ) + + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_sources(Aliaswallet + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/qt/macdockiconhandler.h + ${CMAKE_CURRENT_LIST_DIR}/qt/macnotificationhandler.h + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/qt/macdockiconhandler.mm + ${CMAKE_CURRENT_LIST_DIR}/qt/macnotificationhandler.mm + ) + set_target_properties(Aliaswallet PROPERTIES + MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME}${DBG_EXTENSION} Version ${VERSION_STRING}, © 2020 The Alias developers." + MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_NAME}${DBG_EXTENSION}" + MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME}${DBG_EXTENSION} Version ${VERSION_STRING}" + MACOSX_BUNDLE_BUNDLE_NAME ${PROJECT_NAME}${DBG_EXTENSION} + MACOSX_BUNDLE_SHORT_VERSION_STRING ${VERSION_STRING} + MACOSX_BUNDLE_BUNDLE_VERSION ${VERSION_STRING} + MACOSX_BUNDLE_COPYRIGHT " © 2020 The Alias developers" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/osx/MacOSXBundleInfo.plist.in + OUTPUT_NAME Alias + ) + target_link_libraries(Aliaswallet "-framework AppKit") + add_custom_command(TARGET Aliaswallet POST_BUILD +# COMMAND cd ${CMAKE_BINARY_DIR} && "${MACDEPLOYQT_EXECUTABLE}" +# Alias.app +# -qmldir=${CMAKE_SOURCE_DIR}/src/qt/res +# -always-overwrite +# -verbose=1 +# ${DEPLOY_QT_BINARY_TYPE_OPTION} + COMMAND rm -rf ${CMAKE_BINARY_DIR}/Alias.app/Contents/MacOS/Tor + COMMAND unzip ${TOR_ARCHIVE} -d ${CMAKE_BINARY_DIR}/Alias.app/ + COMMAND chmod +x ${CMAKE_BINARY_DIR}/Alias.app/Contents/MacOS/Tor/tor.real + COMMAND chmod +x ${CMAKE_BINARY_DIR}/Alias.app/Contents/MacOS/Tor/libevent* + COMMAND chmod +x ${CMAKE_BINARY_DIR}/Alias.app/Contents/MacOS/Tor/PluggableTransports/* + COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Alias.app/Contents/Resources + COMMAND cp ${CMAKE_SOURCE_DIR}/src/qt/res/icons/alias-app.icns ${CMAKE_BINARY_DIR}/Alias.app/Contents/Resources/ +# COMMAND cd ${CMAKE_BINARY_DIR} && "${MACDEPLOYQT_EXECUTABLE}" +# Alias.app +# -dmg +# -always-overwrite +# -verbose=1 + COMMENT "Put additional content onto app directory" + ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + target_sources(Aliaswallet + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/qt/winshutdownmonitor.h + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/qt/winshutdownmonitor.cpp + ) + set_target_properties(Aliaswallet PROPERTIES + OUTPUT_NAME Alias + ) + target_link_libraries(Aliaswallet "Shlwapi") + add_custom_command(TARGET Aliaswallet POST_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/delivery/Alias + COMMAND "${CMAKE_COMMAND}" -E + env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}" + --force + --libdir ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER} + --plugindir ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER} + ${DEPLOY_QT_BINARY_TYPE_OPTION} + --qmldir ${CMAKE_SOURCE_DIR}/src/qt/res/qml + --qml + --quick + --webengine + "$" + COMMAND unzip -o ${VCRUNTIME_ARCHIVE} -d ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER}/ + COMMAND unzip -o ${TOR_ARCHIVE} -d ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER}/ + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER} ${CMAKE_BINARY_DIR}/delivery/Alias + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/delivery/${WINDEPLOYQT_TARGET_FOLDER} + COMMENT "Running windeployqt..." + ) + else() + set_target_properties(Aliaswallet PROPERTIES + OUTPUT_NAME aliaswallet + ) + endif() + endif() +endif () + +#message(STATUS "BERKELEYDB_INCLUDE_PATH: ${BERKELEYDB_INCLUDE_PATH}") +#message(STATUS "OPENSSL_INCLUDE_PATH: ${OPENSSL_INCLUDE_PATH}") +#message(STATUS "OPENSSL_API_COMPAT: ${OPENSSL_API_COMPAT}") diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000000..86841daa54 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,316 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +AM_LDFLAGS = -fstack-protector + +if OS_LINUX +AM_LDFLAGS += -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,noexecheap -Wl,-z,nodlopen -Wl,-z,nodump +else +if OS_WINDOWS_CROSSCOMPILE +AM_LDFLAGS += -Wl,--dynamicbase -Wl,--nxcompat -Wl,--subsystem,windows +else +if OS_MACOS +AM_LDFLAGS += $(MACOS_RPATH) +endif +endif +endif + +AM_CPPFLAGS = -pthread -fPIC -fstack-protector -O2 \ + -D_FORTIFY_SOURCE=1 \ + -Wall -Wextra -Wno-ignored-qualifiers -Woverloaded-virtual \ + -Wformat -Wformat-security -Wno-unused-parameter + +if OS_MACOS +AM_CPPFLAGS += -std=c++17 -mmacosx-version-min=10.10 +endif + +common_SOURCES = anonymize.cpp \ + json/json_spirit_reader.cpp \ + json/json_spirit_writer.cpp \ + alert.cpp \ + version.cpp \ + checkpoints.cpp \ + netbase.cpp \ + addrman.cpp \ + crypter.cpp \ + key.cpp \ + eckey.cpp \ + extkey.cpp \ + db.cpp \ + init.cpp \ + keystore.cpp \ + miner.cpp \ + main.cpp \ + net.cpp \ + protocol.cpp \ + rpcprotocol.cpp \ + rpcserver.cpp \ + rpcclient.cpp \ + rpcdump.cpp \ + rpcnet.cpp \ + rpcmining.cpp \ + rpcwallet.cpp \ + rpcblockchain.cpp \ + rpcrawtransaction.cpp \ + rpcextkey.cpp \ + rpcmnemonic.cpp \ + script.cpp \ + sync.cpp \ + util.cpp \ + hash.cpp \ + wallet.cpp \ + walletdb.cpp \ + kernel.cpp \ + pbkdf2.cpp \ + scrypt.cpp \ + scrypt-arm.S \ + scrypt-x86.S \ + scrypt-x86_64.S \ + smessage.cpp \ + stealth.cpp \ + ringsig.cpp \ + core.cpp \ + txdb-leveldb.cpp \ + txmempool.cpp \ + chainparams.cpp \ + state.cpp \ + bloom.cpp \ + shutdown.cpp \ + validation_alias.cpp \ + validation_connectblock_alias.cpp \ + net_alias.cpp \ + net_node_alias.cpp \ + chainparams_compat.cpp \ + chainparams_migration.cpp \ + kernel/chainparams.cpp \ + kernel/context.cpp \ + node/context.cpp \ + pos/kernel.cpp \ + util/chaintype.cpp \ + chainparamsbase.cpp + +bin_PROGRAMS = aliaswalletd +aliaswalletd_SOURCES = $(common_SOURCES) \ + spectrecoind.cpp \ + noui.cpp + +aliaswalletd_LDADD = ../leveldb/out-static/libmemenv.a \ + ../leveldb/out-static/libleveldb.a \ + ../db4.8/build_unix/libdb_cxx.a \ + $(OPENSSL_LIBS) \ + $(LIBEVENT_LIBS) \ + $(LIBSECCOMP_LIBS) \ + $(LIBCAP_LIBS) \ + $(ZLIB_LIBS) \ + $(ZSTD_LIBS) \ + $(LZMA_LIBS) \ + $(BOOST_SYSTEM_LIBS) \ + $(BOOST_CHRONO_LIBS) \ + $(BOOST_FILESYSTEM_LIBS) \ + $(BOOST_PROGRAM_OPTIONS_LIBS) \ + $(BOOST_THREAD_LIBS) + +aliaswalletd_CPPFLAGS = $(AM_CPPFLAGS) $(OPENSSL_CFLAGS) $(LIBEVENT_CFLAGS) \ + $(LIBSECCOMP_CFLAGS) $(LIBCAP_CFLAGS) $(ZLIB_CFLAGS) $(ZSTD_CPPFLAGS) $(LZMA_CPPFLAGS) \ + $(BOOST_CPPFLAGS) \ + -I../leveldb/include -I../leveldb/helpers -I../db4.8/build_unix \ + -D_FORTIFY_SOURCE=1 -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE \ + -DBOOST_ASIO_ENABLE_OLD_SERVICES +aliaswalletd_CFLAGS = $(aliaswalletd_CPPFLAGS) -std=c11 +aliaswalletd_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_LDFLAGS) $(LIBEVENT_LDFLAGS) \ + $(LIBSECCOMP_LDFLAGS) $(LIBCAP_LDFLAGS) $(ZLIB_LDFLAGS) $(ZSTD_LDFLAGS) $(LZMA_LDFLAGS) \ + $(BOOST_SYSTEM_LDFLAGS) $(BOOST_CHRONO_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) \ + $(BOOST_PROGRAM_OPTIONS_LDFLAGS) $(BOOST_THREAD_LDFLAGS) +aliaswalletd_LIBTOOLFLAGS = --tag CXX + +if OS_WINDOWS_CROSSCOMPILE +aliaswalletd_LDADD += -lmswsock -lshlwapi -luuid -lole32 -lgdi32 +aliaswalletd_CPPFLAGS += -DWIN32 -D_WIN32 +else +if OS_MACOS +aliaswalletd_CPPFLAGS += -DMAC_OSX +else +aliaswalletd_LDFLAGS += -pie +aliaswalletd_LDADD += -lcap -lseccomp +endif +endif + +if ENABLE_GUI +qt/locale/%.qm: qt/locale/%.ts + @LRELEASE@ $< -qm $@ + +qt/qrc_%.cpp: ../%.qrc + @RCC@ $< -o $@ + +if OS_MACOS + MOC_CPPFLAGS = -DQ_OS_MACOS +endif + +qt/moc_%.cpp: qt/%.h + @MOC@ -o $@ $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(MOC_CPPFLAGS) $< + +qt/ui_%.h: qt/forms/%.ui + @UIC@ -o $@ $< + +BUILT_SOURCES = qt/ui_aboutdialog.h \ + qt/ui_askpassphrasedialog.h \ + qt/ui_coincontroldialog.h \ + qt/ui_editaddressdialog.h \ + qt/ui_rpcconsole.h \ + qt/ui_transactiondescdialog.h \ + qt/locale/spectrecoin_af_ZA.qm \ + qt/locale/spectrecoin_ar.qm \ + qt/locale/spectrecoin_be_BY.qm \ + qt/locale/spectrecoin_bg.qm \ + qt/locale/spectrecoin_bs.qm \ + qt/locale/spectrecoin_ca_ES.qm \ + qt/locale/spectrecoin_ca.qm \ + qt/locale/spectrecoin_ca@valencia.qm \ + qt/locale/spectrecoin_cs.qm \ + qt/locale/spectrecoin_cy.qm \ + qt/locale/spectrecoin_da.qm \ + qt/locale/spectrecoin_de.qm \ + qt/locale/spectrecoin_el_GR.qm \ + qt/locale/spectrecoin_el.qm \ + qt/locale/spectrecoin_en.qm \ + qt/locale/spectrecoin_eo.qm \ + qt/locale/spectrecoin_es_CL.qm \ + qt/locale/spectrecoin_es_DO.qm \ + qt/locale/spectrecoin_es_MX.qm \ + qt/locale/spectrecoin_es.qm \ + qt/locale/spectrecoin_es_UY.qm \ + qt/locale/spectrecoin_et.qm \ + qt/locale/spectrecoin_eu_ES.qm \ + qt/locale/spectrecoin_fa_IR.qm \ + qt/locale/spectrecoin_fa.qm \ + qt/locale/spectrecoin_fi.qm \ + qt/locale/spectrecoin_fr_CA.qm \ + qt/locale/spectrecoin_fr.qm \ + qt/locale/spectrecoin_gl.qm \ + qt/locale/spectrecoin_he.qm \ + qt/locale/spectrecoin_hi_IN.qm \ + qt/locale/spectrecoin_hr.qm \ + qt/locale/spectrecoin_hu.qm \ + qt/locale/spectrecoin_id_ID.qm \ + qt/locale/spectrecoin_it.qm \ + qt/locale/spectrecoin_ja.qm \ + qt/locale/spectrecoin_ka.qm \ + qt/locale/spectrecoin_kk_KZ.qm \ + qt/locale/spectrecoin_ko_KR.qm \ + qt/locale/spectrecoin_ky.qm \ + qt/locale/spectrecoin_la.qm \ + qt/locale/spectrecoin_lt.qm \ + qt/locale/spectrecoin_lv_LV.qm \ + qt/locale/spectrecoin_ms_MY.qm \ + qt/locale/spectrecoin_nb.qm \ + qt/locale/spectrecoin_nl.qm \ + qt/locale/spectrecoin_pam.qm \ + qt/locale/spectrecoin_pl.qm \ + qt/locale/spectrecoin_pt_BR.qm \ + qt/locale/spectrecoin_pt_PT.qm \ + qt/locale/spectrecoin_ro_RO.qm \ + qt/locale/spectrecoin_ru.qm \ + qt/locale/spectrecoin_sah.qm \ + qt/locale/spectrecoin_sk.qm \ + qt/locale/spectrecoin_sl_SI.qm \ + qt/locale/spectrecoin_sq.qm \ + qt/locale/spectrecoin_sr.qm \ + qt/locale/spectrecoin_sv.qm \ + qt/locale/spectrecoin_th_TH.qm \ + qt/locale/spectrecoin_tr.qm \ + qt/locale/spectrecoin_uk.qm \ + qt/locale/spectrecoin_ur_PK.qm \ + qt/locale/spectrecoin_vi.qm \ + qt/locale/spectrecoin_vi_VN.qm \ + qt/locale/spectrecoin_zh_CN.qm \ + qt/locale/spectrecoin_zh_HK.qm \ + qt/locale/spectrecoin_zh_TW.qm + +bin_PROGRAMS += aliaswallet + +aliaswallet_SOURCES = $(common_SOURCES) \ + qt/qrc_spectre.cpp \ + qt/moc_spectregui.cpp \ + qt/moc_spectrebridge.cpp \ + qt/moc_rpcconsole.cpp \ + qt/moc_peertablemodel.cpp \ + qt/moc_notificator.cpp \ + qt/moc_editaddressdialog.cpp \ + qt/moc_askpassphrasedialog.cpp \ + qt/moc_coincontroldialog.cpp \ + qt/moc_coincontroltreewidget.cpp \ + qt/moc_addresstablemodel.cpp \ + qt/moc_transactiontablemodel.cpp \ + qt/moc_transactiondesc.cpp \ + qt/moc_trafficgraphwidget.cpp \ + qt/moc_paymentserver.cpp \ + qt/moc_clientmodel.cpp \ + qt/moc_walletmodel.cpp \ + qt/moc_optionsmodel.cpp \ + qt/moc_guiutil.cpp \ + qt/moc_aboutdialog.cpp \ + qt/moc_csvmodelwriter.cpp \ + qt/moc_qvaluecombobox.cpp \ + qt/moc_qvalidatedlineedit.cpp \ + qt/moc_bitcoinaddressvalidator.cpp \ + qt/moc_monitoreddatamapper.cpp \ + qt/moc_bitcoinamountfield.cpp \ + qt/moc_setupwalletwizard.cpp \ + qt/moc_websocketclientwrapper.cpp \ + qt/moc_websockettransport.cpp \ + qt/transactiontablemodel.cpp \ + qt/coincontroldialog.cpp \ + qt/coincontroltreewidget.cpp \ + qt/aboutdialog.cpp \ + qt/addresstablemodel.cpp \ + qt/editaddressdialog.cpp \ + qt/bitcoinaddressvalidator.cpp \ + qt/clientmodel.cpp \ + qt/guiutil.cpp \ + qt/transactionrecord.cpp \ + qt/optionsmodel.cpp \ + qt/monitoreddatamapper.cpp \ + qt/transactiondesc.cpp \ + qt/bitcoinstrings.cpp \ + qt/bitcoinamountfield.cpp \ + qt/walletmodel.cpp \ + qt/csvmodelwriter.cpp \ + qt/qvalidatedlineedit.cpp \ + qt/bitcoinunits.cpp \ + qt/qvaluecombobox.cpp \ + qt/askpassphrasedialog.cpp \ + qt/notificator.cpp \ + qt/rpcconsole.cpp \ + qt/paymentserver.cpp \ + qt/peertablemodel.cpp \ + qt/scicon.cpp \ + qt/trafficgraphwidget.cpp \ + qt/spectregui.cpp \ + qt/spectre.cpp \ + qt/spectrebridge.cpp \ + qt/winshutdownmonitor.cpp \ + qt/setupwalletwizard.cpp \ + qt/websocketclientwrapper.cpp \ + qt/websockettransport.cpp + +aliaswallet_LDADD = $(aliaswalletd_LDADD) $(QT5_LIBS) $(QT5WEBKIT_LIBS) +aliaswallet_CPPFLAGS = $(aliaswalletd_CPPFLAGS) $(QT5_CFLAGS) $(QT5WEBKIT_CFLAGS) -DQT_DISABLE_DEPRECATED_BEFORE=0 +aliaswallet_LDFLAGS = $(aliaswalletd_LDFLAGS) $(QT5_LDFLAGS) $(QT5WEBKIT_LDFLAGS) +aliaswallet_LIBTOOLFLAGS = $(aliaswalletd_LIBTOOLFLAGS) + +if OS_MACOS + aliaswallet_SOURCES += qt/moc_macnotificationhandler.cpp \ + qt/macnotificationhandler.mm \ + qt/moc_macdockiconhandler.cpp \ + qt/macdockiconhandler.mm + aliaswallet_LDFLAGS += -framework Foundation -framework AppKit -framework CoreServices +endif +endif + +clean-local: + rm -f qt/moc_*.cpp + rm -f qt/ui_*.cpp + rm -f qt/qrc_*.cpp diff --git a/src/addrman.cpp b/src/addrman.cpp index 40b36d6c34..140e905eb4 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012 Pieter Wuille -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2012 Pieter Wuille +// +// SPDX-License-Identifier: MIT #include "addrman.h" #include "hash.h" @@ -80,13 +80,13 @@ CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int *pnId) { std::map::iterator it = mapAddr.find(addr); if (it == mapAddr.end()) - return NULL; + return nullptr; if (pnId) *pnId = (*it).second; std::map::iterator it2 = mapInfo.find((*it).second); if (it2 != mapInfo.end()) return &(*it2).second; - return NULL; + return nullptr; } CAddrInfo* CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId) @@ -390,9 +390,9 @@ CAddress CAddrMan::Select_(int nUnkBias) { if (size() == 0) return CAddress(); - + int nTries = fTestNet ? 100 : 100000; - + double nCorTried = sqrt(nTried) * (100.0 - nUnkBias); double nCorNew = sqrt(nNew) * nUnkBias; if ((nCorTried + nCorNew)*GetRandInt(1<<30)/(1<<30) < nCorTried) @@ -431,7 +431,7 @@ CAddress CAddrMan::Select_(int nUnkBias) fChanceFactor *= fTestNet ? 12 : 1.2; }; }; - + return CAddress(); } diff --git a/src/addrman.h b/src/addrman.h index b839d65fa6..52b7ff89c3 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -1,6 +1,7 @@ -// Copyright (c) 2012 Pieter Wuille -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2012 Pieter Wuille +// +// SPDX-License-Identifier: MIT + #ifndef _BITCOIN_ADDRMAN #define _BITCOIN_ADDRMAN 1 @@ -9,7 +10,6 @@ #include "util.h" #include "sync.h" - #include #include @@ -46,7 +46,7 @@ class CAddrInfo : public CAddress public: IMPLEMENT_SERIALIZE( - CAddress* pthis = (CAddress*)(this); + CAddress* pthis = static_cast(this); READWRITE(*pthis); READWRITE(source); READWRITE(nLastSuccess); @@ -198,11 +198,11 @@ class CAddrMan protected: // Find an entry. - CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL); + CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr); // find an entry, creating it if necessary. // nTime and nServices of found node is updated, if necessary. - CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL); + CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr); // Swap two elements in vRandom. void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2); @@ -244,9 +244,160 @@ class CAddrMan void Connected_(const CService &addr, int64_t nTime); public: +#ifdef _MSC_BUILD + unsigned int GetSerializeSize(int nType, int nVersion) const + { + CSerActionGetSerializeSize ser_action; + const bool fGetSize = true; + const bool fWrite = false; + const bool fRead = false; + unsigned int nSerSize = 0; + ser_streamplaceholder s; + assert(fGetSize||fWrite||fRead); + s.nType = nType; + s.nVersion = nVersion; + // serialized format: + // * version byte (currently 0) + // * nKey + // * nNew + // * nTried + // * number of "new" buckets + // * all nNew addrinfos in vvNew + // * all nTried addrinfos in vvTried + // * for each bucket: + // * number of elements + // * for each element: index + // + // Notice that vvTried, mapAddr and vVector are never encoded explicitly; + // they are instead reconstructed from the other information. + // + // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change, + // otherwise it is reconstructed as well. + // + // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports + // changes to the ADDRMAN_ parameters without breaking the on-disk structure. + { + LOCK(cs); + unsigned char nVersion = 0; + unsigned int nSerSize = 0; + READWRITE(nVersion); + READWRITE(nKey); + READWRITE(nNew); + READWRITE(nTried); - IMPLEMENT_SERIALIZE - (({ + CAddrMan *am = const_cast(this); + if (fWrite) + { + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT; + READWRITE(nUBuckets); + std::map mapUnkIds; + int nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nNew) break; // this means nNew was wrong, oh ow + mapUnkIds[(*it).first] = nIds; + CAddrInfo &info = (*it).second; + if (info.nRefCount) + { + READWRITE(info); + nIds++; + } + } + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nTried) break; // this means nTried was wrong, oh ow + CAddrInfo &info = (*it).second; + if (info.fInTried) + { + READWRITE(info); + nIds++; + } + } + for (std::vector >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++) + { + const std::set &vNew = (*it); + int nSize = vNew.size(); + READWRITE(nSize); + for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) + { + int nIndex = mapUnkIds[*it2]; + READWRITE(nIndex); + } + } + } else { + int nUBuckets = 0; + READWRITE(nUBuckets); + am->nIdCount = 0; + am->mapInfo.clear(); + am->mapAddr.clear(); + am->vRandom.clear(); + am->vvTried = std::vector >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)); + am->vvNew = std::vector >(ADDRMAN_NEW_BUCKET_COUNT, std::set()); + for (int n = 0; n < am->nNew; n++) + { + CAddrInfo &info = am->mapInfo[n]; + READWRITE(info); + am->mapAddr[info] = n; + info.nRandomPos = vRandom.size(); + am->vRandom.push_back(n); + if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) + { + am->vvNew[info.GetNewBucket(am->nKey)].insert(n); + info.nRefCount++; + } + } + am->nIdCount = am->nNew; + int nLost = 0; + for (int n = 0; n < am->nTried; n++) + { + CAddrInfo info; + READWRITE(info); + std::vector &vTried = am->vvTried[info.GetTriedBucket(am->nKey)]; + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + info.nRandomPos = vRandom.size(); + info.fInTried = true; + am->vRandom.push_back(am->nIdCount); + am->mapInfo[am->nIdCount] = info; + am->mapAddr[info] = am->nIdCount; + vTried.push_back(am->nIdCount); + am->nIdCount++; + } else { + nLost++; + } + } + am->nTried -= nLost; + for (int b = 0; b < nUBuckets; b++) + { + std::set &vNew = am->vvNew[b]; + int nSize = 0; + READWRITE(nSize); + for (int n = 0; n < nSize; n++) + { + int nIndex = 0; + READWRITE(nIndex); + CAddrInfo &info = am->mapInfo[nIndex]; + if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + { + info.nRefCount++; + vNew.insert(nIndex); + } + } + } + } + } + return nSerSize; + } + template + void Serialize(Stream& s, int nType, int nVersion) const + { + CSerActionSerialize ser_action; + const bool fGetSize = false; + const bool fWrite = true; + const bool fRead = false; + unsigned int nSerSize = 0; + assert(fGetSize||fWrite||fRead); // serialized format: // * version byte (currently 0) // * nKey @@ -270,6 +421,284 @@ class CAddrMan { LOCK(cs); unsigned char nVersion = 0; + unsigned int nSerSize = 0; + READWRITE(nVersion); + READWRITE(nKey); + READWRITE(nNew); + READWRITE(nTried); + + CAddrMan *am = const_cast(this); + if (fWrite) + { + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT; + READWRITE(nUBuckets); + std::map mapUnkIds; + int nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nNew) break; // this means nNew was wrong, oh ow + mapUnkIds[(*it).first] = nIds; + CAddrInfo &info = (*it).second; + if (info.nRefCount) + { + READWRITE(info); + nIds++; + } + } + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nTried) break; // this means nTried was wrong, oh ow + CAddrInfo &info = (*it).second; + if (info.fInTried) + { + READWRITE(info); + nIds++; + } + } + for (std::vector >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++) + { + const std::set &vNew = (*it); + int nSize = vNew.size(); + READWRITE(nSize); + for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) + { + int nIndex = mapUnkIds[*it2]; + READWRITE(nIndex); + } + } + } else { + int nUBuckets = 0; + READWRITE(nUBuckets); + am->nIdCount = 0; + am->mapInfo.clear(); + am->mapAddr.clear(); + am->vRandom.clear(); + am->vvTried = std::vector >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)); + am->vvNew = std::vector >(ADDRMAN_NEW_BUCKET_COUNT, std::set()); + for (int n = 0; n < am->nNew; n++) + { + CAddrInfo &info = am->mapInfo[n]; + READWRITE(info); + am->mapAddr[info] = n; + info.nRandomPos = vRandom.size(); + am->vRandom.push_back(n); + if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) + { + am->vvNew[info.GetNewBucket(am->nKey)].insert(n); + info.nRefCount++; + } + } + am->nIdCount = am->nNew; + int nLost = 0; + for (int n = 0; n < am->nTried; n++) + { + CAddrInfo info; + READWRITE(info); + std::vector &vTried = am->vvTried[info.GetTriedBucket(am->nKey)]; + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + info.nRandomPos = vRandom.size(); + info.fInTried = true; + am->vRandom.push_back(am->nIdCount); + am->mapInfo[am->nIdCount] = info; + am->mapAddr[info] = am->nIdCount; + vTried.push_back(am->nIdCount); + am->nIdCount++; + } else { + nLost++; + } + } + am->nTried -= nLost; + for (int b = 0; b < nUBuckets; b++) + { + std::set &vNew = am->vvNew[b]; + int nSize = 0; + READWRITE(nSize); + for (int n = 0; n < nSize; n++) + { + int nIndex = 0; + READWRITE(nIndex); + CAddrInfo &info = am->mapInfo[nIndex]; + if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + { + info.nRefCount++; + vNew.insert(nIndex); + } + } + } + } + } + } + template + void Unserialize(Stream& s, int nType, int nVersion) + { + CSerActionUnserialize ser_action; + const bool fGetSize = false; + const bool fWrite = false; + const bool fRead = true; + unsigned int nSerSize = 0; + assert(fGetSize||fWrite||fRead); + // serialized format: + // * version byte (currently 0) + // * nKey + // * nNew + // * nTried + // * number of "new" buckets + // * all nNew addrinfos in vvNew + // * all nTried addrinfos in vvTried + // * for each bucket: + // * number of elements + // * for each element: index + // + // Notice that vvTried, mapAddr and vVector are never encoded explicitly; + // they are instead reconstructed from the other information. + // + // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change, + // otherwise it is reconstructed as well. + // + // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports + // changes to the ADDRMAN_ parameters without breaking the on-disk structure. + { + LOCK(cs); + unsigned char nVersion = 0; + unsigned int nSerSize = 0; + READWRITE(nVersion); + READWRITE(nKey); + READWRITE(nNew); + READWRITE(nTried); + + CAddrMan *am = const_cast(this); + if (fWrite) + { + int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT; + READWRITE(nUBuckets); + std::map mapUnkIds; + int nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nNew) break; // this means nNew was wrong, oh ow + mapUnkIds[(*it).first] = nIds; + CAddrInfo &info = (*it).second; + if (info.nRefCount) + { + READWRITE(info); + nIds++; + } + } + nIds = 0; + for (std::map::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++) + { + if (nIds == nTried) break; // this means nTried was wrong, oh ow + CAddrInfo &info = (*it).second; + if (info.fInTried) + { + READWRITE(info); + nIds++; + } + } + for (std::vector >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++) + { + const std::set &vNew = (*it); + int nSize = vNew.size(); + READWRITE(nSize); + for (std::set::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++) + { + int nIndex = mapUnkIds[*it2]; + READWRITE(nIndex); + } + } + } else { + int nUBuckets = 0; + READWRITE(nUBuckets); + am->nIdCount = 0; + am->mapInfo.clear(); + am->mapAddr.clear(); + am->vRandom.clear(); + am->vvTried = std::vector >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)); + am->vvNew = std::vector >(ADDRMAN_NEW_BUCKET_COUNT, std::set()); + for (int n = 0; n < am->nNew; n++) + { + CAddrInfo &info = am->mapInfo[n]; + READWRITE(info); + am->mapAddr[info] = n; + info.nRandomPos = vRandom.size(); + am->vRandom.push_back(n); + if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) + { + am->vvNew[info.GetNewBucket(am->nKey)].insert(n); + info.nRefCount++; + } + } + am->nIdCount = am->nNew; + int nLost = 0; + for (int n = 0; n < am->nTried; n++) + { + CAddrInfo info; + READWRITE(info); + std::vector &vTried = am->vvTried[info.GetTriedBucket(am->nKey)]; + if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE) + { + info.nRandomPos = vRandom.size(); + info.fInTried = true; + am->vRandom.push_back(am->nIdCount); + am->mapInfo[am->nIdCount] = info; + am->mapAddr[info] = am->nIdCount; + vTried.push_back(am->nIdCount); + am->nIdCount++; + } else { + nLost++; + } + } + am->nTried -= nLost; + for (int b = 0; b < nUBuckets; b++) + { + std::set &vNew = am->vvNew[b]; + int nSize = 0; + READWRITE(nSize); + for (int n = 0; n < nSize; n++) + { + int nIndex = 0; + READWRITE(nIndex); + CAddrInfo &info = am->mapInfo[nIndex]; + if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) + { + info.nRefCount++; + vNew.insert(nIndex); + } + } + } + } + } + } +#endif + +#ifndef _MSC_BUILD + IMPLEMENT_SERIALIZE(({ + // serialized format: + // * version byte (currently 0) + // * nKey + // * nNew + // * nTried + // * number of "new" buckets + // * all nNew addrinfos in vvNew + // * all nTried addrinfos in vvTried + // * for each bucket: + // * number of elements + // * for each element: index + // + // Notice that vvTried, mapAddr and vVector are never encoded explicitly; + // they are instead reconstructed from the other information. + // + // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change, + // otherwise it is reconstructed as well. + // + // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports + // changes to the ADDRMAN_ parameters without breaking the on-disk structure. + { + LOCK(cs); + unsigned char nVersion = 0; + unsigned int nSerSize = 0; READWRITE(nVersion); READWRITE(nKey); READWRITE(nNew); @@ -378,6 +807,22 @@ class CAddrMan } } });) +#endif + + void Clear() + { + { + LOCK(cs); + vRandom.clear(); + vvTried = std::vector >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)); + vvNew = std::vector >(ADDRMAN_NEW_BUCKET_COUNT, std::set()); + nIdCount = 0; + nTried = 0; + nNew = 0; + mapInfo.clear(); + mapAddr.clear(); + } + } CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set()) { diff --git a/src/alert.cpp b/src/alert.cpp index e0c5ef41cc..460e3bf7d2 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -1,11 +1,14 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers // -// Alert system -// +// SPDX-License-Identifier: MIT #include #include #include -#include #include #include "alert.h" @@ -13,7 +16,7 @@ #include "key.h" #include "net.h" #include "sync.h" -#include "ui_interface.h" +#include "interface.h" std::map mapAlerts; @@ -40,10 +43,10 @@ void CUnsignedAlert::SetNull() std::string CUnsignedAlert::ToString() const { std::string strSetCancel; - BOOST_FOREACH(int n, setCancel) + for (int n : setCancel) strSetCancel += strprintf("%d ", n); std::string strSetSubVer; - BOOST_FOREACH(std::string str, setSubVer) + for (const std::string& str : setSubVer) strSetSubVer += "\"" + str + "\" "; return strprintf( "CAlert(\n" @@ -187,13 +190,41 @@ bool CAlert::ProcessAlert(bool fThread) nMaxVer == maxInt && setSubVer.empty() && nPriority == maxInt && - strStatusBar == "URGENT: Alert key compromised, upgrade required" + strStatusBar == "URGENT: Alert key compromised, upgrade required" && + strComment == "" && + strReserved == "" && + nVersion == 1 )) return false; } { LOCK(cs_mapAlerts); + + // Check if this alert has been cancelled + for (auto& item : mapAlerts) + { + const CAlert& alert = item.second; + if (alert.Cancels(*this)) + { + LogPrint("alert", "alert already cancelled by %d\n", alert.nID); + return false; + } + if ( + alert.nExpiration == maxInt && + alert.nCancel == (maxInt-1) && + alert.nMinVer == 0 && + alert.nMaxVer == maxInt && + alert.setSubVer.empty() && + alert.nPriority == maxInt && + alert.strStatusBar == "URGENT: Alert key compromised, upgrade required" && + alert.strComment == "" && + alert.strReserved == "" && + alert.nVersion == 1 + ) { // If we have a final alert, do not continue + return false; + } + } // Cancel previous alerts for (std::map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) { @@ -215,16 +246,10 @@ bool CAlert::ProcessAlert(bool fThread) } } - // Check if this alert has been cancelled - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) - { - const CAlert& alert = item.second; - if (alert.Cancels(*this)) - { - LogPrintf("alert already cancelled by %d\n", alert.nID); - return false; - } - } + // Do not allow more than 5 concurrent alerts + if (mapAlerts.size() >= 5) { + return false; + } // Add to mapAlerts mapAlerts.insert(std::make_pair(GetHash(), *this)); diff --git a/src/alert.h b/src/alert.h index 4eaa78f729..2ee09924c7 100644 --- a/src/alert.h +++ b/src/alert.h @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef _BITCOINALERT_H_ #define _BITCOINALERT_H_ diff --git a/src/allocators.h b/src/allocators.h index 85af8fe376..fe44756bdc 100644 --- a/src/allocators.h +++ b/src/allocators.h @@ -1,13 +1,19 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_ALLOCATORS_H #define BITCOIN_ALLOCATORS_H #include #include +#ifndef Q_MOC_RUN #include +#endif #include #include // for OPENSSL_cleanse() @@ -213,18 +219,18 @@ struct secure_allocator : public std::allocator template struct rebind { typedef secure_allocator<_Other> other; }; - T* allocate(std::size_t n, const void *hint = 0) + T* allocate(std::size_t n, const void *hint = nullptr) { T *p; p = std::allocator::allocate(n, hint); - if (p != NULL) + if (p != nullptr) LockedPageManager::instance.LockRange(p, sizeof(T) * n); return p; } void deallocate(T* p, std::size_t n) { - if (p != NULL) + if (p != nullptr) { OPENSSL_cleanse(p, sizeof(T) * n); LockedPageManager::instance.UnlockRange(p, sizeof(T) * n); @@ -259,7 +265,7 @@ struct zero_after_free_allocator : public std::allocator void deallocate(T* p, std::size_t n) { - if (p != NULL) + if (p != nullptr) OPENSSL_cleanse(p, sizeof(T) * n); std::allocator::deallocate(p, n); } diff --git a/src/android/AndroidManifest.xml b/src/android/AndroidManifest.xml new file mode 100644 index 0000000000..c22f8a44d6 --- /dev/null +++ b/src/android/AndroidManifest.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/android/build.gradle b/src/android/build.gradle new file mode 100644 index 0000000000..9d9a5c1505 --- /dev/null +++ b/src/android/build.gradle @@ -0,0 +1,72 @@ +/** + * SPDX-FileCopyrightText: © 2025 ALIAS Developers + * SPDX-FileCopyrightText: © 2020 Alias Developers + * + * SPDX-License-Identifier: MIT + */ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + } +} + +repositories { + google() + jcenter() +} + +apply plugin: 'com.android.application' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) +} + +android { + /******************************************************* + * The following variables: + * - androidBuildToolsVersion, + * - androidCompileSdkVersion + * - qt5AndroidDir - holds the path to qt android files + * needed to build any Qt application + * on Android. + * + * are defined in gradle.properties file. This file is + * updated by QtCreator and androiddeployqt tools. + * Changing them manually might break the compilation! + *******************************************************/ + + compileSdkVersion androidCompileSdkVersion.toInteger() + + buildToolsVersion '28.0.3' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] + aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] + res.srcDirs = [qt5AndroidDir + '/res', 'res'] + resources.srcDirs = ['resources'] + renderscript.srcDirs = ['src'] + assets.srcDirs = ['assets'] + jniLibs.srcDirs = ['libs'] + } + } + + lintOptions { + abortOnError false + } + + // Do not compress Qt binary resources file + aaptOptions { + noCompress 'rcc' + } + + defaultConfig { + resConfigs "en" + } +} diff --git a/src/android/res/values/libs.xml b/src/android/res/values/libs.xml new file mode 100644 index 0000000000..242082d6c4 --- /dev/null +++ b/src/android/res/values/libs.xml @@ -0,0 +1,25 @@ + + + + + + + https://download.qt.io/ministro/android/qt5/qt-5.14 + + + + + + + + + + + + + + + + + diff --git a/src/anonymize.cpp b/src/anonymize.cpp new file mode 100644 index 0000000000..0e778d6d9c --- /dev/null +++ b/src/anonymize.cpp @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 StealthCoin/StealthSend Developers +// SPDX-FileCopyrightText: © 2013 BritCoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#include "anonymize.h" +#include "util.h" +#include "util/fs.h" + +#include +#include + +extern const char tor_git_revision[]; +const char tor_git_revision[] = ""; + +char const* anonymize_tor_data_directory( +) { + static std::string const retrieved = ( + GetDefaultDataDir( + ) / "tor" + ).string( + ); + return retrieved.c_str( + ); +} + +char const* anonymize_service_directory( +) { + static std::string const retrieved = ( + GetDefaultDataDir( + ) / "onion" + ).string( + ); + return retrieved.c_str( + ); +} diff --git a/src/anonymize.h b/src/anonymize.h new file mode 100644 index 0000000000..8be0295010 --- /dev/null +++ b/src/anonymize.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 BritCoin Developers +// +// SPDX-License-Identifier: MIT + +/** + * \file anonymize.h + * \brief Headers for anonymize.cpp + **/ + +#ifndef TOR_ANONYMIZE_H +#define TOR_ANONYMIZE_H + +#ifdef __cplusplus +extern "C" { +#endif + + char const* anonymize_tor_data_directory(void); + char const* anonymize_service_directory(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/base58.h b/src/base58.h index 52a30f40b8..92e8a8f811 100644 --- a/src/base58.h +++ b/src/base58.h @@ -1,9 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin Developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - - +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT // // Why base-58 instead of standard base-64 encoding? // - Don't want 0OIl characters that look the same in some fonts and @@ -53,7 +54,7 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char CBigNum rem; while (bn > bn0) { - if (!BN_div(&dv, &rem, &bn, &bn58, pctx)) + if (!BN_div(dv.pbn, rem.pbn, bn.pbn, bn58.pbn, pctx)) throw bignum_error("EncodeBase58 : BN_div failed"); bn = dv; unsigned int c = rem.getulong(); @@ -91,7 +92,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) for (const char* p = psz; *p; p++) { const char* p1 = strchr(pszBase58, *p); - if (p1 == NULL) + if (p1 == nullptr) { while (isspace(*p)) p++; @@ -100,7 +101,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) break; } bnChar.setulong(p1 - pszBase58); - if (!BN_mul(&bn, &bn, &bn58, pctx)) + if (!BN_mul(bn.pbn, bn.pbn, bn58.pbn, pctx)) throw bignum_error("DecodeBase58 : BN_mul failed"); bn += bnChar; } @@ -210,7 +211,7 @@ class CBase58Data { std::vector vchTemp; DecodeBase58Check(psz, vchTemp); - + if (vchTemp.size() == BIP32_KEY_N_BYTES + 4) // no point checking smaller keys { if (0 == memcmp(&vchTemp[0], &Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY)[0], 4)) @@ -219,7 +220,7 @@ class CBase58Data if (0 == memcmp(&vchTemp[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4)) { // - never display secret in a CBitcoinAddress - + // - length already checked vchVersion = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY); CExtKeyPair ekp; @@ -230,14 +231,14 @@ class CBase58Data return true; }; }; - + if (vchTemp.size() < nVersionBytes) { vchData.clear(); vchVersion.clear(); return false; }; - + vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes); vchData.resize(vchTemp.size() - nVersionBytes); if (!vchData.empty()) @@ -287,11 +288,11 @@ class CBitcoinAddressVisitor : public boost::static_visitor CBitcoinAddress *addr; public: CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } - bool operator()(const CKeyID &id) const; - bool operator()(const CScriptID &id) const; - bool operator()(const CStealthAddress &sxAddr) const; - bool operator()(const CExtKeyPair &ek) const; - bool operator()(const CNoDestination &no) const; + bool operator()(const CKeyID &id) const override; + bool operator()(const CScriptID &id) const override; + bool operator()(const CStealthAddress &sxAddr) const override; + bool operator()(const CExtKeyPair &ek) const override; + bool operator()(const CNoDestination &no) const override; }; class CBitcoinAddress : public CBase58Data @@ -308,20 +309,20 @@ class CBitcoinAddress : public CBase58Data SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20); return true; } - + bool Set(const CKeyID &id, CChainParams::Base58Type prefix) { SetData(Params().Base58Prefix(prefix), &id, 20); return true; } - + bool Set(const CExtKeyPair &ek) { std::vector vchVersion; uint8_t data[74]; - + // - use public key only, should never be a need to reveal the secret in an address - + /* if (ek.IsValidV()) { @@ -329,10 +330,10 @@ class CBitcoinAddress : public CBase58Data ek.EncodeV(data); } else */ - + vchVersion = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY); ek.EncodeP(data); - + SetData(vchVersion, data, 74); return true; }; @@ -344,37 +345,35 @@ class CBitcoinAddress : public CBase58Data bool IsValid() const { - if (vchVersion.size() == 4 + if (vchVersion.size() == 4 && (vchVersion == Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY) || vchVersion == Params().Base58Prefix(CChainParams::EXT_SECRET_KEY))) return vchData.size() == BIP32_KEY_N_BYTES; - + bool fCorrectSize = vchData.size() == 20; bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) || vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS); return fCorrectSize && fKnownVersion; } - + bool IsValid(CChainParams::Base58Type prefix) const { bool fKnownVersion = vchVersion == Params().Base58Prefix(prefix); if (prefix == CChainParams::EXT_PUBLIC_KEY || prefix == CChainParams::EXT_SECRET_KEY) return fKnownVersion && vchData.size() == BIP32_KEY_N_BYTES; - + bool fCorrectSize = vchData.size() == 20; return fCorrectSize && fKnownVersion; } - + bool IsBIP32() const { return vchVersion == Params().Base58Prefix(CChainParams::EXT_SECRET_KEY) || vchVersion == Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY); } - CBitcoinAddress() - { - } + CBitcoinAddress() = default; CBitcoinAddress(const CTxDestination &dest) { @@ -395,13 +394,13 @@ class CBitcoinAddress : public CBase58Data CTxDestination Get() const { if (!IsValid()) return CNoDestination(); - + uint160 id; if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS)) { memcpy(&id, &vchData[0], 20); return CKeyID(id); - } else + } else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS)) { memcpy(&id, &vchData[0], 20); @@ -432,7 +431,7 @@ class CBitcoinAddress : public CBase58Data keyID = CKeyID(id); return true; } - + bool GetKeyID(CKeyID &keyID, CChainParams::Base58Type prefix) const { if (!IsValid(prefix)) return false; @@ -494,9 +493,7 @@ class CBitcoinSecret : public CBase58Data SetKey(vchSecret); } - CBitcoinSecret() - { - } + CBitcoinSecret() = default; }; @@ -508,7 +505,7 @@ template class CBitcoinExtK key.Encode(vch); SetData(Params().Base58Prefix(Type), vch, vch+Size); } - + void SetVch(const uint8_t *vch) { SetData(Params().Base58Prefix(Type), vch, vch+Size); } @@ -523,27 +520,27 @@ template class CBitcoinExtK CBitcoinExtKeyBase(const K &key) { SetKey(key); } - + int Set58(const char *base58) { std::vector vchBytes; if (!DecodeBase58(base58, vchBytes)) return 1; - + if (vchBytes.size() != BIP32_KEY_LEN) return 2; - + if (!VerifyChecksum(vchBytes)) return 3; - + if (0 != memcmp(&vchBytes[0], &Params().Base58Prefix(Type)[0], 4)) return 4; - + SetData(Params().Base58Prefix(Type), &vchBytes[4], &vchBytes[4]+Size); return 0; } - CBitcoinExtKeyBase() {} + CBitcoinExtKeyBase() = default; }; typedef CBitcoinExtKeyBase CBitcoinExtKey; @@ -553,27 +550,27 @@ typedef CBitcoinExtKeyBase CBitcoi class CExtKey58 : public CBase58Data { public: - CExtKey58() {}; - + CExtKey58() = default; + CExtKey58(const CExtKeyPair &key, CChainParams::Base58Type type) { SetKey(key, type); }; - + void SetKeyV(const CExtKeyPair &key) { SetKey(key, CChainParams::EXT_SECRET_KEY); }; - + void SetKeyP(const CExtKeyPair &key) { SetKey(key, CChainParams::EXT_PUBLIC_KEY); }; - + void SetKey(const CExtKeyPair &key, CChainParams::Base58Type type) { uint8_t vch[74]; - + switch (type) { case CChainParams::EXT_SECRET_KEY: @@ -586,10 +583,10 @@ class CExtKey58 : public CBase58Data key.EncodeP(vch); break; }; - + SetData(Params().Base58Prefix(type), vch, vch+74); }; - + CExtKeyPair GetKey() { CExtKeyPair ret; @@ -602,19 +599,19 @@ class CExtKey58 : public CBase58Data ret.DecodeP(&vchData[0]); return ret; }; - + int Set58(const char *base58) { std::vector vchBytes; if (!DecodeBase58(base58, vchBytes)) return 1; - + if (vchBytes.size() != BIP32_KEY_LEN) return 2; - + if (!VerifyChecksum(vchBytes)) return 3; - + CChainParams::Base58Type type; if (0 == memcmp(&vchBytes[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4)) type = CChainParams::EXT_SECRET_KEY; @@ -629,11 +626,11 @@ class CExtKey58 : public CBase58Data type = CChainParams::EXT_PUBLIC_KEY_BTC; else return 4; - + SetData(Params().Base58Prefix(type), &vchBytes[4], &vchBytes[4]+74); return 0; }; - + bool IsValid(CChainParams::Base58Type prefix) const { return vchVersion == Params().Base58Prefix(prefix) diff --git a/src/bignum.h b/src/bignum.h index 94bbe74074..3c3ecc7132 100644 --- a/src/bignum.h +++ b/src/bignum.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_BIGNUM_H #define BITCOIN_BIGNUM_H @@ -36,70 +39,72 @@ class CAutoBN_CTX CAutoBN_CTX() { pctx = BN_CTX_new(); - if (pctx == NULL) - throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned NULL"); + if (pctx == nullptr) + throw bignum_error("CAutoBN_CTX : BN_CTX_new() returned nullptr"); } ~CAutoBN_CTX() { - if (pctx != NULL) + if (pctx != nullptr) BN_CTX_free(pctx); } operator BN_CTX*() { return pctx; } BN_CTX& operator*() { return *pctx; } BN_CTX** operator&() { return &pctx; } - bool operator!() { return (pctx == NULL); } + bool operator!() { return (pctx == nullptr); } }; /** C++ wrapper for BIGNUM (OpenSSL bignum) */ -class CBigNum : public BIGNUM +class CBigNum { public: + BIGNUM* pbn; + CBigNum() { - BN_init(this); + this->pbn = BN_new(); } CBigNum(const CBigNum& b) { - BN_init(this); - if (!BN_copy(this, &b)) + this->pbn = BN_new(); + if (!BN_copy(this->pbn, b.pbn)) { - BN_clear_free(this); + BN_clear_free(this->pbn); throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); } } CBigNum& operator=(const CBigNum& b) { - if (!BN_copy(this, &b)) + if (!BN_copy(this->pbn, b.pbn)) throw bignum_error("CBigNum::operator= : BN_copy failed"); return (*this); } ~CBigNum() { - BN_clear_free(this); + BN_clear_free(this->pbn); } //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. - CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(long long n) { BN_init(this); setint64(n); } - CBigNum(unsigned char n) { BN_init(this); setulong(n); } - CBigNum(unsigned short n) { BN_init(this); setulong(n); } - CBigNum(unsigned int n) { BN_init(this); setulong(n); } - CBigNum(unsigned long n) { BN_init(this); setulong(n); } - CBigNum(unsigned long long n) { BN_init(this); setuint64(n); } - explicit CBigNum(uint256 n) { BN_init(this); setuint256(n); } + CBigNum(signed char n) { this->pbn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(short n) { this->pbn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(int n) { this->pbn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(long n) { this->pbn = BN_new(); if (n >= 0) setulong(n); else setint64(n); } + CBigNum(long long n) { this->pbn = BN_new(); setint64(n); } + CBigNum(unsigned char n) { this->pbn = BN_new(); setulong(n); } + CBigNum(unsigned short n) { this->pbn = BN_new(); setulong(n); } + CBigNum(unsigned int n) { this->pbn = BN_new(); setulong(n); } + CBigNum(unsigned long n) { this->pbn = BN_new(); setulong(n); } + CBigNum(unsigned long long n) { this->pbn = BN_new(); setuint64(n); } + explicit CBigNum(uint256 n) { this->pbn = BN_new(); setuint256(n); } explicit CBigNum(const std::vector& vch) { - BN_init(this); + this->pbn = BN_new(); setvch(vch); } @@ -108,10 +113,10 @@ class CBigNum : public BIGNUM * @param range The upper bound on the number. * @return */ - static CBigNum randBignum(const CBigNum& range) + static CBigNum randBignum(const CBigNum& range) { CBigNum ret; - if(!BN_rand_range(&ret, &range)){ + if(!BN_rand_range(ret.pbn, range.pbn)){ throw bignum_error("CBigNum:rand element : BN_rand_range failed"); } return ret; @@ -124,7 +129,7 @@ class CBigNum : public BIGNUM static CBigNum RandKBitBigum(const uint32_t k) { CBigNum ret; - if(!BN_rand(&ret, k, -1, 0)) + if(!BN_rand(ret.pbn, k, -1, 0)) { throw bignum_error("CBigNum:rand element : BN_rand failed"); } @@ -136,30 +141,30 @@ class CBigNum : public BIGNUM * @return the size */ int bitSize() const{ - return BN_num_bits(this); + return BN_num_bits(this->pbn); } void setulong(unsigned long n) { - if (!BN_set_word(this, n)) + if (!BN_set_word(this->pbn, n)) throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); } unsigned long getulong() const { - return BN_get_word(this); + return BN_get_word(this->pbn); } unsigned int getuint() const { - return BN_get_word(this); + return BN_get_word(this->pbn); } int getint() const { - unsigned long n = BN_get_word(this); - if (!BN_is_negative(this)) + unsigned long n = BN_get_word(this->pbn); + if (!BN_is_negative(this->pbn)) return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::max() : n); else return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); @@ -174,7 +179,10 @@ class CBigNum : public BIGNUM if (sn < (int64_t)0) { - // Since the minimum signed integer cannot be represented as positive so long as its type is signed, and it's not well-defined what happens if you make it unsigned before negating it, we instead increment the negative integer by 1, convert it, then increment the (now positive) unsigned integer by 1 to compensate + // Since the minimum signed integer cannot be represented as positive so long as its + // type is signed, and it's not well-defined what happens if you make it unsigned + // before negating it, we instead increment the negative integer by 1, convert it, + // then increment the (now positive) unsigned integer by 1 to compensate n = -(sn + 1); ++n; fNegative = true; @@ -206,16 +214,16 @@ class CBigNum : public BIGNUM pch[1] = (nSize >> 16) & 0xff; pch[2] = (nSize >> 8) & 0xff; pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); + BN_mpi2bn(pch, p - pch, this->pbn); } uint64_t getuint64() { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(this->pbn, nullptr); if (nSize < 4) return 0; std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(this->pbn, &vch[0]); if (vch.size() > 4) vch[4] &= 0x7f; uint64_t n = 0; @@ -248,7 +256,7 @@ class CBigNum : public BIGNUM pch[1] = (nSize >> 16) & 0xff; pch[2] = (nSize >> 8) & 0xff; pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); + BN_mpi2bn(pch, p - pch, this->pbn); } void setuint256(uint256 n) @@ -276,16 +284,16 @@ class CBigNum : public BIGNUM pch[1] = (nSize >> 16) & 0xff; pch[2] = (nSize >> 8) & 0xff; pch[3] = (nSize >> 0) & 0xff; - BN_mpi2bn(pch, p - pch, this); + BN_mpi2bn(pch, p - pch, this->pbn); } uint256 getuint256() const { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(this->pbn, nullptr); if (nSize < 4) return 0; std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(this->pbn, &vch[0]); if (vch.size() > 4) vch[4] &= 0x7f; uint256 n = 0; @@ -294,7 +302,6 @@ class CBigNum : public BIGNUM return n; } - void setvch(const std::vector& vch) { std::vector vch2(vch.size() + 4); @@ -307,16 +314,16 @@ class CBigNum : public BIGNUM vch2[3] = (nSize >> 0) & 0xff; // swap data to big endian reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); - BN_mpi2bn(&vch2[0], vch2.size(), this); + BN_mpi2bn(&vch2[0], vch2.size(), this->pbn); } std::vector getvch() const { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(this->pbn, nullptr); if (nSize <= 4) return std::vector(); std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(this->pbn, &vch[0]); vch.erase(vch.begin(), vch.begin() + 4); reverse(vch.begin(), vch.end()); return vch; @@ -330,16 +337,16 @@ class CBigNum : public BIGNUM if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff; if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff; - BN_mpi2bn(&vch[0], vch.size(), this); + BN_mpi2bn(&vch[0], vch.size(), this->pbn); return *this; } unsigned int GetCompact() const { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(this->pbn, nullptr); std::vector vch(nSize); nSize -= 4; - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(this->pbn, &vch[0]); unsigned int nCompact = nSize << 24; if (nSize >= 1) nCompact |= (vch[4] << 16); if (nSize >= 2) nCompact |= (vch[5] << 8); @@ -384,21 +391,21 @@ class CBigNum : public BIGNUM CBigNum bn0 = 0; std::string str; CBigNum bn = *this; - BN_set_negative(&bn, false); + BN_set_negative(bn.pbn, false); CBigNum dv; CBigNum rem; - if (BN_cmp(&bn, &bn0) == 0) + if (BN_cmp(bn.pbn, bn0.pbn) == 0) return "0"; - while (BN_cmp(&bn, &bn0) > 0) + while (BN_cmp(bn.pbn, bn0.pbn) > 0) { - if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) + if (!BN_div(dv.pbn, rem.pbn, bn.pbn, bnBase.pbn, pctx)) throw bignum_error("CBigNum::ToString() : BN_div failed"); bn = dv; unsigned int c = rem.getulong(); str += "0123456789abcdef"[c]; } - - if (BN_is_negative(this)) + + if (BN_is_negative(this->pbn)) str += "-"; reverse(str.begin(), str.end()); return str; @@ -445,7 +452,7 @@ class CBigNum : public BIGNUM CBigNum pow(const CBigNum& e) const { CAutoBN_CTX pctx; CBigNum ret; - if (!BN_exp(&ret, this, &e, pctx)) + if (!BN_exp(ret.pbn, this->pbn, e.pbn, pctx)) throw bignum_error("CBigNum::pow : BN_exp failed"); return ret; } @@ -458,9 +465,9 @@ class CBigNum : public BIGNUM CBigNum mul_mod(const CBigNum& b, const CBigNum& m) const { CAutoBN_CTX pctx; CBigNum ret; - if (!BN_mod_mul(&ret, this, &b, &m, pctx)) + if (!BN_mod_mul(ret.pbn, this->pbn, b.pbn, m.pbn, pctx)) throw bignum_error("CBigNum::mul_mod : BN_mod_mul failed"); - + return ret; } @@ -472,14 +479,14 @@ class CBigNum : public BIGNUM CBigNum pow_mod(const CBigNum& e, const CBigNum& m) const { CAutoBN_CTX pctx; CBigNum ret; - if( e < 0){ + if (e < 0) { // g^-x = (g^-1)^x CBigNum inv = this->inverse(m); CBigNum posE = e * -1; - if (!BN_mod_exp(&ret, &inv, &posE, &m, pctx)) + if (!BN_mod_exp(ret.pbn, inv.pbn, posE.pbn, m.pbn, pctx)) throw bignum_error("CBigNum::pow_mod: BN_mod_exp failed on negative exponent"); - }else - if (!BN_mod_exp(&ret, this, &e, &m, pctx)) + } else + if (!BN_mod_exp(ret.pbn, this->pbn, e.pbn, m.pbn, pctx)) throw bignum_error("CBigNum::pow_mod : BN_mod_exp failed"); return ret; @@ -494,7 +501,7 @@ class CBigNum : public BIGNUM CBigNum inverse(const CBigNum& m) const { CAutoBN_CTX pctx; CBigNum ret; - if (!BN_mod_inverse(&ret, this, &m, pctx)) + if (!BN_mod_inverse(ret.pbn, this->pbn, m.pbn, pctx)) throw bignum_error("CBigNum::inverse*= :BN_mod_inverse"); return ret; } @@ -508,7 +515,7 @@ class CBigNum : public BIGNUM static CBigNum generatePrime(const unsigned int numBits, bool safe = false) { CBigNum ret; - if(!BN_generate_prime_ex(&ret, numBits, (safe == true), NULL, NULL, NULL)) + if(!BN_generate_prime_ex(ret.pbn, numBits, (safe == true), nullptr, nullptr, nullptr)) throw bignum_error("CBigNum::generatePrime*= :BN_generate_prime_ex"); return ret; } @@ -521,7 +528,7 @@ class CBigNum : public BIGNUM CBigNum gcd( const CBigNum& b) const{ CAutoBN_CTX pctx; CBigNum ret; - if (!BN_gcd(&ret, this, &b, pctx)) + if (!BN_gcd(ret.pbn, this->pbn, b.pbn, pctx)) throw bignum_error("CBigNum::gcd*= :BN_gcd"); return ret; } @@ -534,26 +541,26 @@ class CBigNum : public BIGNUM */ bool isPrime(const int checks=BN_prime_checks) const { CAutoBN_CTX pctx; - int ret = BN_is_prime(this, checks, NULL, pctx, NULL); - if(ret < 0){ + int ret = BN_is_prime_ex(this->pbn, checks, pctx, nullptr); + if (ret < 0) { throw bignum_error("CBigNum::isPrime :BN_is_prime"); } return ret; } bool isOne() const { - return BN_is_one(this); + return BN_is_one(this->pbn); } bool operator!() const { - return BN_is_zero(this); + return BN_is_zero(this->pbn); } CBigNum& operator+=(const CBigNum& b) { - if (!BN_add(this, this, &b)) + if (!BN_add(this->pbn, this->pbn, b.pbn)) throw bignum_error("CBigNum::operator+= : BN_add failed"); return *this; } @@ -567,7 +574,7 @@ class CBigNum : public BIGNUM CBigNum& operator*=(const CBigNum& b) { CAutoBN_CTX pctx; - if (!BN_mul(this, this, &b, pctx)) + if (!BN_mul(this->pbn, this->pbn, b.pbn, pctx)) throw bignum_error("CBigNum::operator*= : BN_mul failed"); return *this; } @@ -586,7 +593,7 @@ class CBigNum : public BIGNUM CBigNum& operator<<=(unsigned int shift) { - if (!BN_lshift(this, this, shift)) + if (!BN_lshift(this->pbn, this->pbn, shift)) throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); return *this; } @@ -597,13 +604,13 @@ class CBigNum : public BIGNUM // if built on ubuntu 9.04 or 9.10, probably depends on version of OpenSSL CBigNum a = 1; a <<= shift; - if (BN_cmp(&a, this) > 0) + if (BN_cmp(a.pbn, this->pbn) > 0) { *this = 0; return *this; } - if (!BN_rshift(this, this, shift)) + if (!BN_rshift(this->pbn, this->pbn, shift)) throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); return *this; } @@ -612,7 +619,7 @@ class CBigNum : public BIGNUM CBigNum& operator++() { // prefix operator - if (!BN_add(this, this, BN_value_one())) + if (!BN_add(this->pbn, this->pbn, BN_value_one())) throw bignum_error("CBigNum::operator++ : BN_add failed"); return *this; } @@ -629,7 +636,7 @@ class CBigNum : public BIGNUM { // prefix operator CBigNum r; - if (!BN_sub(&r, this, BN_value_one())) + if (!BN_sub(r.pbn, this->pbn, BN_value_one())) throw bignum_error("CBigNum::operator-- : BN_sub failed"); *this = r; return *this; @@ -656,7 +663,7 @@ class CBigNum : public BIGNUM inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) { CBigNum r; - if (!BN_add(&r, &a, &b)) + if (!BN_add(r.pbn, a.pbn, b.pbn)) throw bignum_error("CBigNum::operator+ : BN_add failed"); return r; } @@ -664,7 +671,7 @@ inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) { CBigNum r; - if (!BN_sub(&r, &a, &b)) + if (!BN_sub(r.pbn, a.pbn, b.pbn)) throw bignum_error("CBigNum::operator- : BN_sub failed"); return r; } @@ -672,7 +679,7 @@ inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) inline const CBigNum operator-(const CBigNum& a) { CBigNum r(a); - BN_set_negative(&r, !BN_is_negative(&r)); + BN_set_negative(r.pbn, !BN_is_negative(r.pbn)); return r; } @@ -680,7 +687,7 @@ inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_mul(&r, &a, &b, pctx)) + if (!BN_mul(r.pbn, a.pbn, b.pbn, pctx)) throw bignum_error("CBigNum::operator* : BN_mul failed"); return r; } @@ -689,7 +696,7 @@ inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_div(&r, NULL, &a, &b, pctx)) + if (!BN_div(r.pbn, nullptr, a.pbn, b.pbn, pctx)) throw bignum_error("CBigNum::operator/ : BN_div failed"); return r; } @@ -698,7 +705,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_nnmod(&r, &a, &b, pctx)) + if (!BN_nnmod(r.pbn, a.pbn, b.pbn, pctx)) throw bignum_error("CBigNum::operator% : BN_div failed"); return r; } @@ -706,7 +713,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) { CBigNum r; - if (!BN_lshift(&r, &a, shift)) + if (!BN_lshift(r.pbn, a.pbn, shift)) throw bignum_error("CBigNum:operator<< : BN_lshift failed"); return r; } @@ -718,12 +725,12 @@ inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) return r; } -inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } -inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } -inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } -inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } -inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } -inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } +inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) == 0); } +inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) != 0); } +inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) <= 0); } +inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) >= 0); } +inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) < 0); } +inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.pbn, b.pbn) > 0); } inline std::ostream& operator<<(std::ostream &strm, const CBigNum &b) { return strm << b.ToString(10); } diff --git a/src/bloom.cpp b/src/bloom.cpp index d3883644f1..80c7298d86 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "bloom.h" @@ -42,7 +45,7 @@ void CBloomFilter::insert(const vector& vKey) { if (isFull) return; - + for (unsigned int i = 0; i < nHashFuncs; i++) { unsigned int nIndex = Hash(i, vKey); @@ -117,24 +120,24 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) return true; if (isEmpty) return false; - + const uint256& hash = tx.GetHash(); - - + + if (((nFlags & BLOOM_ACCEPT_STEALTH) && tx.HasStealthOutput()) || contains(hash)) { fFound = true; // -- don't return here! }; - + for (unsigned int i = 0; i < tx.vout.size(); i++) { const CTxOut& txout = tx.vout[i]; // Match if the filter contains any arbitrary script data element in any scriptPubKey in tx // If this matches, also add the specific output that was matched. - // This means clients don't have to update the filter themselves when a new relevant tx + // This means clients don't have to update the filter themselves when a new relevant tx // is discovered in order to find spending transactions, which avoids round-tripping and race conditions. CScript::const_iterator pc = txout.scriptPubKey.begin(); vector data; @@ -143,20 +146,20 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) opcodetype opcode; if (!txout.scriptPubKey.GetOp(pc, opcode, data)) break; - + if (data.size() == 33) // coinstake { uint160 pkHash = Hash160(data); vector dataHash160(pkHash.begin(), pkHash.end()); - + if (dataHash160.size() != 0 && contains(dataHash160)) fFound = true; }; - + if (!fFound && data.size() != 0 && contains(data)) fFound = true; - + if (fFound) { if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_ALL) @@ -179,7 +182,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) if (fFound) return true; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { // Match if the filter contains an outpoint tx spends if (contains(txin.prevout)) @@ -210,7 +213,7 @@ void CBloomFilter::UpdateEmptyFull() full &= vData[i] == 0xff; empty &= vData[i] == 0; }; - + isFull = full; isEmpty = empty; } diff --git a/src/bloom.h b/src/bloom.h index 7658c5dc1e..9ce9853fcd 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -1,6 +1,9 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_BLOOM_H #define BITCOIN_BLOOM_H @@ -28,20 +31,20 @@ enum bloomflags // Only adds outpoints to the filter if the output is a pay-to-pubkey/pay-to-multisig script BLOOM_UPDATE_P2PUBKEY_ONLY = 2, BLOOM_UPDATE_MASK = 3, - + BLOOM_ACCEPT_STEALTH = (1 << 2), - - + + }; /** * BloomFilter is a probabilistic filter which SPV clients provide * so that we can filter the transactions we sends them. - * + * * This allows for significantly more efficient transaction and block downloads. - * + * * Because bloom filters are probabilistic, an SPV node can increase the false- - * positive rate, making us send them transactions which aren't actually theirs, + * positive rate, making us send them transactions which aren't actually theirs, * allowing clients to trade more bandwidth for more privacy by obfuscating which * keys are owned by them. */ @@ -56,7 +59,7 @@ class CBloomFilter unsigned char nFlags; unsigned int Hash(unsigned int nHashNum, const std::vector& vDataToHash) const; - + // Creates a new bloom filter which will provide the given fp rate when filled with the given number of elements // Note that if the given parameters will result in a filter outside the bounds of the protocol limits, // the filter created will be as close to the given parameters as possible within the protocol limits. @@ -74,7 +77,7 @@ class CBloomFilter READWRITE(nTweak); READWRITE(nFlags); ) - + bool IsFull() {return isFull;}; unsigned int GetSize() {return vData.size();}; diff --git a/src/build.h.in b/src/build.h.in new file mode 100644 index 0000000000..f0ea40202a --- /dev/null +++ b/src/build.h.in @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +#define BUILD_DESC "" +#define BUILD_DATE "22:10:13.08" +#define GIT_HASH "@CLIENT_VERSION_GIT_SHA1@" \ No newline at end of file diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 6c2912d502..2af4577b96 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "assert.h" @@ -24,19 +27,16 @@ int64_t CChainParams::GetProofOfWorkReward(int nHeight, int64_t nFees) const // miner's coin base reward int64_t nSubsidy = 0; - if (nHeight <= 0) + if(nHeight == 1) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 2000000 : 20000000) * COIN; // 20Mill Pre-mine on MainNet, 2Mill pre-mine on TestNet + + else if(nHeight <= nLastPOWBlock) nSubsidy = 0; - else - if (nHeight <= nLastFairLaunchBlock) - nSubsidy = 1 * COIN; - else - if (nHeight <= nLastPOWBlock) - nSubsidy = (NetworkID() == CChainParams::TESTNET ? 10000 : 400) * COIN; if (fDebug && GetBoolArg("-printcreation")) LogPrintf("GetProofOfWorkReward() : create=%s nSubsidy=%d\n", FormatMoney(nSubsidy).c_str(), nSubsidy); - return nSubsidy + nFees; + return nSubsidy; }; @@ -45,39 +45,47 @@ int64_t CChainParams::GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64 // miner's coin stake reward based on coin age spent (coin-days) int64_t nSubsidy; - if (IsProtocolV3(pindexPrev->nHeight)) - nSubsidy = (pindexPrev->nMoneySupply / COIN) * COIN_YEAR_REWARD / (365 * 24 * (60 * 60 / 64)); + if (IsForkV4SupplyIncrease(pindexPrev)) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 300000 : 3000000) * COIN; + else if (IsProtocolV3(pindexPrev->nHeight)) + nSubsidy = Params().IsForkV3(pindexPrev->GetBlockTime()) ? + nStakeReward : + (pindexPrev->nMoneySupply / COIN) * COIN_YEAR_REWARD / (365 * 24 * (60 * 60 / 64)); else nSubsidy = nCoinAge * COIN_YEAR_REWARD * 33 / (365 * 33 + 8); if (fDebug && GetBoolArg("-printcreation")) - LogPrintf("GetProofOfStakeReward(): create=%s nCoinAge=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge); + { + if (IsProtocolV3(pindexPrev->nHeight)) + LogPrintf("GetProofOfStakeReward(): create=%s\n", FormatMoney(nSubsidy).c_str()); + else + LogPrintf("GetProofOfStakeReward(): create=%s nCoinAge=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge); + } return nSubsidy + nFees; } -// -// Main network -// +int64_t CChainParams::GetProofOfAnonStakeReward(const CBlockIndex* pindexPrev, int64_t nFees) const +{ + int64_t nSubsidy = nAnonStakeReward; + if (IsForkV4SupplyIncrease(pindexPrev)) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 300000 : 3000000) * COIN; -// Convert the pnSeeds6 array into usable address objects. -static void convertSeed6(std::vector &vSeedsOut, const SeedSpec6 *data, unsigned int count) + if (fDebug && GetBoolArg("-printcreation")) + LogPrintf("GetProofOfAnonStakeReward(): create=%s\n", FormatMoney(nSubsidy).c_str()); + + return nSubsidy + nFees; +} + +bool CChainParams::IsForkV4SupplyIncrease(const CBlockIndex* pindexPrev) const { - // It'll only connect to one or two seed nodes because once it connects, - // it'll get a pile of addresses with newer timestamps. - // Seed nodes are given a random 'last seen time' of between one and two - // weeks ago. - const int64_t nOneWeek = 7*24*60*60; - for (unsigned int i = 0; i < count; i++) - { - struct in6_addr ip; - memcpy(&ip, data[i].addr, sizeof(ip)); - CAddress addr(CService(ip, data[i].port)); - addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; - vSeedsOut.push_back(addr); - } + return pindexPrev->GetBlockTime() >= nForkV4Time && pindexPrev->pprev->GetBlockTime() < nForkV4Time; } +// +// Main network +// + // Convert the pnSeeds array into usable address objects. static void convertSeeds(std::vector &vSeedsOut, const unsigned int *data, unsigned int count, int port) { @@ -108,7 +116,7 @@ static void convertSeeds(std::vector &vSeedsOut, const unsigned int *d class CBaseChainParams : public CChainParams { public: CBaseChainParams() { - const char* pszTimestamp = "www.cryptocoinsnews.com/news/bitlicense-regulations-forked-github-bitcoin-community/2014/07/19"; + const char* pszTimestamp = "https://www.cryptocoinsnews.com/encrypted-services-exec-bitcoins-price-history-follows-gartners-hype-cycle/"; CTransaction txNew; txNew.nTime = GENESIS_BLOCK_TIME; txNew.vin.resize(1); @@ -121,15 +129,13 @@ class CBaseChainParams : public CChainParams { genesis.nVersion = 1; genesis.nTime = GENESIS_BLOCK_TIME; - vSeeds.push_back(CDNSSeedData("main.shadow.cash", "seed.shadow.cash")); - vSeeds.push_back(CDNSSeedData("seed2.shadow.cash", "seed2.shadow.cash")); - vSeeds.push_back(CDNSSeedData("seed3.shadow.cash", "seed3.shadow.cash")); - vSeeds.push_back(CDNSSeedData("seed4.shadow.cash", "seed4.shadow.cash")); - vSeeds.push_back(CDNSSeedData("shadowproject.io", "seed.shadowproject.io")); - vSeeds.push_back(CDNSSeedData("shadowchain.info", "seed.shadowchain.info")); - } - virtual const CBlock& GenesisBlock() const { return genesis; } - virtual const std::vector& FixedSeeds() const { + vSeeds.push_back(CDNSSeedData("node1.spectreproject.io", "node1.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node2.spectreproject.io", "node2.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node3.spectreproject.io", "node3.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node4.spectreproject.io", "node4.spectreproject.io")); + } + const CBlock& GenesisBlock() const override { return genesis; } + const std::vector& FixedSeeds() const override { return vFixedSeeds; } protected: @@ -145,50 +151,58 @@ class CMainParams : public CBaseChainParams { // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. - pchMessageStart[0] = 0xfa; - pchMessageStart[1] = 0xf2; - pchMessageStart[2] = 0xef; - pchMessageStart[3] = 0xb4; - - vAlertPubKey = ParseHex("031d5def92b2d59943e57aaa8b1adbb110ff215fc4ebdc6fb5c9a797e2b1dea527"); + pchMessageStart[0] = 0xb5; + pchMessageStart[1] = 0x22; + pchMessageStart[2] = 0x5c; + pchMessageStart[3] = 0xd3; - nDefaultPort = 51737; - nRPCPort = 51736; - nBIP44ID = 0x80000023; + vAlertPubKey = ParseHex("04f7bbad03208ea942e292080854d422d046d457949ea70ad3306438fc8357343dccaa73e52291ebe07de85c6701d88d87af2d29c2e3b024fb0ad53f045a6d3ad6"); - nLastPOWBlock = 31000; - nLastFairLaunchBlock = 120; + nDefaultPort = 37347; + nRPCPort = 36657; + nBIP44ID = 0x800000d5; - nFirstPosv2Block = 453000; - nFirstPosv3Block = 783000; + //nLastPOWBlock = 2016; // Running for 1 Week after ICO + nLastPOWBlock = 17000; + nFirstPosv2Block = 17001; + nFirstPosv3Block = 17010; bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20); // "standard" scrypt target limit for proof of work, results with 0,000244140625 proof-of-work difficulty bnProofOfStakeLimit = CBigNum(~uint256(0) >> 20); bnProofOfStakeLimitV2 = CBigNum(~uint256(0) >> 48); + nStakeMinConfirmationsLegacy = 288; + nStakeMinConfirmations = 450; // block time 96 seconds * 450 = 12 hours + genesis.nBits = bnProofOfWorkLimit.GetCompact(); - genesis.nNonce = 261836; - hashGenesisBlock = genesis.GetHash(); + genesis.nNonce = 715015; - assert(hashGenesisBlock == uint256("0x00000eca234f07edc98aaf3f2a7b7478dc58992a9cd439323d099c6a590ca2bb")); - assert(genesis.hashMerkleRoot == uint256("0x26a3ff5d3dc46b091e7b58b6022982e6d27dff1bab3bd1da6beb4790983c87c4")); + hashGenesisBlock = genesis.GetHash(); + assert(hashGenesisBlock == uint256("0x000001fd6111f0d71d90b7d8c827c6028dbc867f6c527d90794a0d22f68fecd4")); + assert(genesis.hashMerkleRoot == uint256("0x48d79d88cdf7d5c84dbb2ffb4fcaab253cebe040a4e7b46cdd507fbb93623e3f")); base58Prefixes[PUBKEY_ADDRESS] = list_of(63).convert_to_container >(); - base58Prefixes[SCRIPT_ADDRESS] = list_of(125).convert_to_container >(); - base58Prefixes[SECRET_KEY] = list_of(191).convert_to_container >(); + base58Prefixes[SCRIPT_ADDRESS] = list_of(136).convert_to_container >(); + base58Prefixes[SECRET_KEY] = list_of(179).convert_to_container >(); base58Prefixes[STEALTH_ADDRESS] = list_of(40).convert_to_container >(); - base58Prefixes[EXT_PUBLIC_KEY] = list_of(0xEE)(0x80)(0x28)(0x6A).convert_to_container >(); - base58Prefixes[EXT_SECRET_KEY] = list_of(0xEE)(0x80)(0x31)(0xE8).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x2C)(0x51)(0x3B)(0xD7).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = list_of(0x2C)(0x51)(0xC1)(0x5A).convert_to_container >(); base58Prefixes[EXT_KEY_HASH] = list_of(137).convert_to_container >(); // x base58Prefixes[EXT_ACC_HASH] = list_of(83).convert_to_container >(); // a base58Prefixes[EXT_PUBLIC_KEY_BTC] = list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); // xprv base58Prefixes[EXT_SECRET_KEY_BTC] = list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); // xpub - //convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main)); convertSeeds(vFixedSeeds, pnSeed, ARRAYLEN(pnSeed), nDefaultPort); + + nForkV2Time = 1534888800; // MAINNET V2 chain fork (GMT: Tuesday, 21. August 2018 22.00) + nForkV3Time = 1558123200; // MAINNET V3 chain fork (GMT: Friday, 17. May 2019 20:00:00) + nForkV4Time = 1569614400; // MAINNET V4 chain fork (GMT: Friday, 27. September 2019 20:00:00) + + devContributionAddress = "SdrdWNtjD7V6BSt3EyQZKCnZDkeE28cZhr"; + supplyIncreaseAddress = "SSGCEMb6xESgmuGXkx7yozGDxhVSXzBP3a"; } - virtual Network NetworkID() const { return CChainParams::MAIN; } + Network NetworkID() const override { return CChainParams::MAIN; } }; static CMainParams mainParams; @@ -205,31 +219,33 @@ class CTestNetParams : public CBaseChainParams { // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. - pchMessageStart[0] = 0x07; - pchMessageStart[1] = 0x11; - pchMessageStart[2] = 0x05; - pchMessageStart[3] = 0x0b; + pchMessageStart[0] = 0xa3; + pchMessageStart[1] = 0x2c; + pchMessageStart[2] = 0x44; + pchMessageStart[3] = 0xb4; - vAlertPubKey = ParseHex("0373d8dce43eb98374bcfff2352cd559e6774fd6a87eef73b2fbdb39b2b0bc0082"); + vAlertPubKey = ParseHex("04e564bc9bf28e6d395cd89c4d2bdb235c3873f59b1330d2e6a30c6fa85d8a8637693ae367ce39c2fe0f4e8e3c7c3a34feb82305388f19030aa4fcd4955abeb810"); - nDefaultPort = 51997; - nRPCPort = 51996; + nDefaultPort = 37111; + nRPCPort = 36757; nBIP44ID = 0x80000001; - nLastPOWBlock = 110; - nLastFairLaunchBlock = 10; - - nFirstPosv2Block = 110; + nLastPOWBlock = 20; + nFirstPosv2Block = 20; nFirstPosv3Block = 500; - bnProofOfWorkLimit = CBigNum(~uint256(0) >> 16); + bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); bnProofOfStakeLimit = CBigNum(~uint256(0) >> 20); - bnProofOfStakeLimitV2 = CBigNum(~uint256(0) >> 16); + bnProofOfStakeLimitV2 = CBigNum(~uint256(0) >> 46); + + nStakeMinConfirmationsLegacy = 28; + nStakeMinConfirmations = 30; genesis.nBits = bnProofOfWorkLimit.GetCompact(); - genesis.nNonce = 55887; + genesis.nNonce = 20; + hashGenesisBlock = genesis.GetHash(); - assert(hashGenesisBlock == uint256("0x0000910a87c1385247edc82808ec498a2d738fea5f0d3f8801512d6b84ad6f72")); + assert(hashGenesisBlock == uint256("0x0a3e03a153b1713ebc1f03fefa5d013bba4d2677ae189fcb727396b98043d95c")); base58Prefixes[PUBKEY_ADDRESS] = list_of(127).convert_to_container >(); base58Prefixes[SCRIPT_ADDRESS] = list_of(196).convert_to_container >(); @@ -242,10 +258,17 @@ class CTestNetParams : public CBaseChainParams { base58Prefixes[EXT_PUBLIC_KEY_BTC] = list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); // tprv base58Prefixes[EXT_SECRET_KEY_BTC] = list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); // tpub - //convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test)); convertSeeds(vFixedSeeds, pnTestnetSeed, ARRAYLEN(pnTestnetSeed), nDefaultPort); + + nForkV2Time = 1532466000; // TESTNET V2 chain fork (GMT: Tuesday, 24. July 2018 21.00) + nForkV3Time = 1546470000; // TESTNET V3 chain fork (01/02/2019 @ 11:00pm (UTC)) + nForkV4Time = 1567972800; // TESTNET V4 chain fork (Sunday, 8. September 2019 20:00:00) + + + devContributionAddress = "tSJoPZoXumJyDmGKYo9Y7SZkJvymESFYkD"; + supplyIncreaseAddress = devContributionAddress; } - virtual Network NetworkID() const { return CChainParams::TESTNET; } + Network NetworkID() const override { return CChainParams::TESTNET; } }; static CTestNetParams testNetParams; @@ -262,24 +285,25 @@ class CRegTestParams : public CTestNetParams { nFirstPosv2Block = -1; nFirstPosv3Block = -1; - pchMessageStart[0] = 0xfa; - pchMessageStart[1] = 0xbf; - pchMessageStart[2] = 0xb5; - pchMessageStart[3] = 0xda; + pchMessageStart[0] = 0x05; + pchMessageStart[1] = 0xc5; + pchMessageStart[2] = 0x04; + pchMessageStart[3] = 0x3a; bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); - genesis.nTime = 1411111111; + genesis.nTime = 1479594600; genesis.nBits = bnProofOfWorkLimit.GetCompact(); genesis.nNonce = 2; + hashGenesisBlock = genesis.GetHash(); nDefaultPort = 18444; - assert(hashGenesisBlock == uint256("0xb86b5854a5a77e1eb0a6023b7d6013ebc9840bd87aad7d9e56da458f87015d3f")); + assert(hashGenesisBlock == uint256("0x562dba63b74b056329585b9779306f3d3caf447b5df40fb088cebbfb31fd5d5d")); vSeeds.clear(); // Regtest mode doesn't have any DNS seeds. } - virtual bool RequireRPCPassword() const { return false; } - virtual Network NetworkID() const { return CChainParams::REGTEST; } + bool RequireRPCPassword() const override { return false; } + Network NetworkID() const override { return CChainParams::REGTEST; } }; static CRegTestParams regTestParams; diff --git a/src/chainparams.h b/src/chainparams.h index e05ad945bf..81690f4949 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_CHAIN_PARAMS_H #define BITCOIN_CHAIN_PARAMS_H @@ -64,8 +67,8 @@ class CChainParams const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } - const bool IsProtocolV2(int nHeight) const { return nHeight > nFirstPosv2Block; } - const bool IsProtocolV3(int nHeight) const { return nHeight > nFirstPosv3Block; } + bool IsProtocolV2(int nHeight) const { return nHeight > nFirstPosv2Block; } + bool IsProtocolV3(int nHeight) const { return nHeight > nFirstPosv3Block; } const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } const CBigNum& ProofOfStakeLimit(int nHeight) const { return IsProtocolV2(nHeight) ? bnProofOfStakeLimitV2 : bnProofOfStakeLimit; } @@ -87,10 +90,26 @@ class CChainParams int LastPOWBlock() const { return nLastPOWBlock; } - int LastFairLaunchBlock() const { return nLastFairLaunchBlock; } + //int LastFairLaunchBlock() const { return nLastFairLaunchBlock; } int64_t GetProofOfWorkReward(int nHeight, int64_t nFees) const; int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) const; + int64_t GetProofOfAnonStakeReward(const CBlockIndex* pindexPrev, int64_t nFees) const; + + const std::string GetDevContributionAddress() const { return devContributionAddress; } + const std::string GetSupplyIncreaseAddress() const { return supplyIncreaseAddress; } + + bool IsForkV2(int64_t nTime) const { return nTime > nForkV2Time; } + bool IsForkV3(int64_t nTime) const { return nTime > nForkV3Time; } + bool IsForkV4(int64_t nTime) const { return nTime >= nForkV4Time; } + bool IsForkV4SupplyIncrease(const CBlockIndex* pindexPrev) const; + int GetForkId(int64_t nTime) const { return (nTime >= nForkV4Time) ? 4 : (nTime > nForkV3Time) ? 3 : (nTime > nForkV2Time) ? 2 : 0; } + + const CBigNum BnProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const CBigNum BnProofOfStakeLimit() const { return bnProofOfStakeLimit; } + + int GetStakeMinConfirmations(int64_t nTime) const { return IsForkV3(nTime) ? nStakeMinConfirmations : nStakeMinConfirmationsLegacy; } + int GetAnonStakeMinConfirmations() const { return nStakeMinConfirmations; } protected: CChainParams() {}; @@ -110,11 +129,20 @@ class CChainParams CBigNum bnProofOfStakeLimit; CBigNum bnProofOfStakeLimitV2; + int nStakeMinConfirmationsLegacy; + int nStakeMinConfirmations; + std::string strDataDir; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; int nLastPOWBlock; - int nLastFairLaunchBlock; + + std::string devContributionAddress; + std::string supplyIncreaseAddress; + + int64_t nForkV2Time; + int64_t nForkV3Time; + int64_t nForkV4Time; }; /** @@ -142,7 +170,7 @@ void SelectParams(CChainParams::Network network); */ bool SelectParamsFromCommandLine(); -inline bool TestNet() { +const inline bool TestNet() { // Note: it's deliberate that this returns "false" for regression test mode. return Params().NetworkID() == CChainParams::TESTNET; } diff --git a/src/chainparams_compat.cpp b/src/chainparams_compat.cpp new file mode 100644 index 0000000000..ceb8525ce5 --- /dev/null +++ b/src/chainparams_compat.cpp @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include + +// Note: The actual implementation of Params(), TestNetParams(), MainNetParams(), +// SelectParams(), and SelectParamsFromCommandLine() is in chainparams.cpp +// This compatibility layer provides additional helper functions and will serve +// as a bridge when fully migrating to the new kernel/chainparams structure. + +// Forward declarations for static instances in chainparams.cpp +// These are defined in chainparams.cpp as static instances +extern CMainParams mainParams; +extern CTestNetParams testNetParams; +extern CRegTestParams regTestParams; + +bool SelectParamsFromCommandLine() +{ + // Select chain params from command line arguments + // This maintains backward compatibility with old argument parsing + + std::string chain = gArgs.GetChainName(); + if (chain == CBaseChainParams::MAIN) { + SelectParams(CChainParams::MAIN); + return true; + } else if (chain == CBaseChainParams::TESTNET) { + SelectParams(CChainParams::TESTNET); + return true; + } else if (chain == CBaseChainParams::REGTEST) { + SelectParams(CChainParams::REGTEST); + return true; + } + + return false; +} + +namespace ChainParamsCompat { + +const CChainParams& GetParams() +{ + return Params(); +} + +ChainType NetworkToChainType(CChainParams::Network network) +{ + switch (network) { + case CChainParams::MAIN: + return ChainType::MAIN; + case CChainParams::TESTNET: + return ChainType::TESTNET; + case CChainParams::REGTEST: + return ChainType::REGTEST; + default: + return ChainType::MAIN; + } +} + +CChainParams::Network ChainTypeToNetwork(ChainType chain) +{ + switch (chain) { + case ChainType::MAIN: + return CChainParams::MAIN; + case ChainType::TESTNET: + return CChainParams::TESTNET; + case ChainType::REGTEST: + return CChainParams::REGTEST; + default: + return CChainParams::MAIN; + } +} + +} // namespace ChainParamsCompat + diff --git a/src/chainparams_compat.h b/src/chainparams_compat.h new file mode 100644 index 0000000000..ea2f2658b2 --- /dev/null +++ b/src/chainparams_compat.h @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINPARAMS_COMPAT_H +#define BITCOIN_CHAINPARAMS_COMPAT_H + +#include +#include +#include +#include + +/** + * Compatibility layer for old CChainParams interface + * Provides backward compatibility for code using the old chainparams.h interface + */ + +/** + * Global functions for backward compatibility + * These maintain the old interface while using the new kernel/chainparams structure + */ +const CChainParams &Params(); +const CChainParams &TestNetParams(); +const CChainParams &MainNetParams(); +void SelectParams(CChainParams::Network network); +bool SelectParamsFromCommandLine(); + +/** + * Compatibility wrapper for old CChainParams methods + * This allows old code to continue working while using the new structure + */ +namespace ChainParamsCompat { + // Get the active chain params (old interface) + const CChainParams& GetParams(); + + // Convert old Network enum to new ChainType + ChainType NetworkToChainType(CChainParams::Network network); + + // Convert new ChainType to old Network enum + CChainParams::Network ChainTypeToNetwork(ChainType chain); +} + +#endif // BITCOIN_CHAINPARAMS_COMPAT_H + diff --git a/src/chainparams_migration.cpp b/src/chainparams_migration.cpp new file mode 100644 index 0000000000..bf5d36809c --- /dev/null +++ b/src/chainparams_migration.cpp @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include + +namespace ChainParamsMigration { + +const CChainParams& GetParams() +{ + // For now, use compatibility layer + // Eventually, this will return from the new kernel/chainparams structure + return Params(); +} + +ChainType ConvertNetworkToChainType(CChainParams::Network network) +{ + switch (network) { + case CChainParams::MAIN: + return ChainType::MAIN; + case CChainParams::TESTNET: + return ChainType::TESTNET; + case CChainParams::REGTEST: + return ChainType::REGTEST; + default: + return ChainType::MAIN; + } +} + +CChainParams::Network ConvertChainTypeToNetwork(ChainType chain) +{ + switch (chain) { + case ChainType::MAIN: + return CChainParams::MAIN; + case ChainType::TESTNET: + return CChainParams::TESTNET; + case ChainType::REGTEST: + return CChainParams::REGTEST; + default: + return CChainParams::MAIN; + } +} + +bool UseNewChainParams() +{ + // Check if we should use new chainparams structure + // For now, return false to use old structure + // Set to true when migration is complete + return gArgs.GetBoolArg("-newchainparams", false); +} + +MessageStartChars GetMessageStart() +{ + const CChainParams& params = GetParams(); + return params.MessageStart(); +} + +uint16_t GetDefaultPort() +{ + const CChainParams& params = GetParams(); + return params.GetDefaultPort(); +} + +int GetBIP44ID() +{ + const CChainParams& params = GetParams(); + return params.BIP44ID(); +} + +int GetRPCPort() +{ + const CChainParams& params = GetParams(); + return params.RPCPort(); +} + +bool RequireRPCPassword() +{ + const CChainParams& params = GetParams(); + return params.RequireRPCPassword(); +} + +std::string GetNetworkIDString() +{ + const CChainParams& params = GetParams(); + return params.NetworkIDString(); +} + +std::string GetDevContributionAddress() +{ + const CChainParams& params = GetParams(); + return params.GetDevContributionAddress(); +} + +std::string GetSupplyIncreaseAddress() +{ + const CChainParams& params = GetParams(); + return params.GetSupplyIncreaseAddress(); +} + +const std::vector& GetBase58Prefix(CChainParams::Base58Type type) +{ + const CChainParams& params = GetParams(); + return params.Base58Prefix(type); +} + +int64_t GetProofOfWorkReward(int nHeight, int64_t nFees) +{ + const CChainParams& params = GetParams(); + return params.GetProofOfWorkReward(nHeight, nFees); +} + +int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) +{ + const CChainParams& params = GetParams(); + return params.GetProofOfStakeReward(pindexPrev, nCoinAge, nFees); +} + +int GetLastPOWBlock() +{ + const CChainParams& params = GetParams(); + return params.LastPOWBlock(); +} + +int GetStakeMinConfirmations(int64_t nTime) +{ + const CChainParams& params = GetParams(); + return params.GetStakeMinConfirmations(nTime); +} + +} // namespace ChainParamsMigration + diff --git a/src/chainparams_migration.h b/src/chainparams_migration.h new file mode 100644 index 0000000000..abf6965f66 --- /dev/null +++ b/src/chainparams_migration.h @@ -0,0 +1,117 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINPARAMS_MIGRATION_H +#define BITCOIN_CHAINPARAMS_MIGRATION_H + +#include +#include +#include +#include + +class CBlockIndex; + +/** + * Migration helpers for gradually moving from old chainparams to new kernel/chainparams + * + * These functions help bridge the gap between old and new chainparams structures + * during the migration process + */ + +namespace ChainParamsMigration { + +/** + * Get chain params using new structure + * Returns the active chain params from the new kernel/chainparams structure + */ +const CChainParams& GetParams(); + +/** + * Convert old Network enum to new ChainType + */ +ChainType ConvertNetworkToChainType(CChainParams::Network network); + +/** + * Convert new ChainType to old Network enum + */ +CChainParams::Network ConvertChainTypeToNetwork(ChainType chain); + +/** + * Check if we should use new chainparams structure + * Returns true if migration to new structure is complete + */ +bool UseNewChainParams(); + +/** + * Get message start characters from new structure + */ +MessageStartChars GetMessageStart(); + +/** + * Get default port from new structure + */ +uint16_t GetDefaultPort(); + +/** + * Get BIP44 ID from new structure + */ +int GetBIP44ID(); + +/** + * Get RPC port from chain params + */ +int GetRPCPort(); + +/** + * Check if RPC password is required + */ +bool RequireRPCPassword(); + +/** + * Get network ID string + */ +std::string GetNetworkIDString(); + +/** + * Get dev contribution address + */ +std::string GetDevContributionAddress(); + +/** + * Get supply increase address + */ +std::string GetSupplyIncreaseAddress(); + +/** + * Get Base58 prefix for a given type + */ +const std::vector& GetBase58Prefix(CChainParams::Base58Type type); + +/** + * Get proof of work reward + */ +int64_t GetProofOfWorkReward(int nHeight, int64_t nFees); + +/** + * Get proof of stake reward + */ +int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees); + +/** + * Get last PoW block + */ +int GetLastPOWBlock(); + +/** + * Get stake min confirmations + */ +int GetStakeMinConfirmations(int64_t nTime); + +} // namespace ChainParamsMigration + +#endif // BITCOIN_CHAINPARAMS_MIGRATION_H + diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp new file mode 100644 index 0000000000..6b3d4965ee --- /dev/null +++ b/src/chainparamsbase.cpp @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#include + +// Forward declaration - will be implemented when we migrate ArgsManager +class ArgsManager; +void SetupChainParamsBaseOptions(ArgsManager& argsman) +{ + // TODO: Implement when ArgsManager is migrated + // For now, this is a placeholder +} + +static std::unique_ptr globalChainBaseParams; + +const CBaseChainParams& BaseParams() +{ + assert(globalChainBaseParams); + return *globalChainBaseParams; +} + +/** + * Port numbers for Alias network + * Main: RPC 36657, Onion 37347 + * Testnet: RPC 36757, Onion 37111 + */ +std::unique_ptr CreateBaseChainParams(const ChainType chain) +{ + switch (chain) { + case ChainType::MAIN: + return std::make_unique("", 36657, 37347); // Alias ports + case ChainType::TESTNET: + return std::make_unique("testnet", 36757, 37111); // Alias testnet ports + case ChainType::SIGNET: + return std::make_unique("signet", 36757, 37111); // Use testnet ports for signet + case ChainType::REGTEST: + return std::make_unique("regtest", 18444, 18444); + } + assert(false); +} + +void SelectBaseParams(const ChainType chain) +{ + globalChainBaseParams = CreateBaseChainParams(chain); + // TODO: Implement gArgs.SelectConfigNetwork when ArgsManager is migrated + // gArgs.SelectConfigNetwork(ChainTypeToString(chain)); +} + diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h new file mode 100644 index 0000000000..31880376b6 --- /dev/null +++ b/src/chainparamsbase.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2014-2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CHAINPARAMSBASE_H +#define BITCOIN_CHAINPARAMSBASE_H + +#include + +#include +#include + +class ArgsManager; + +/** + * CBaseChainParams defines the base parameters (shared between alias-cli and aliasd) + * of a given instance of the Alias system. + */ +class CBaseChainParams +{ +public: + const std::string& DataDir() const { return strDataDir; } + uint16_t RPCPort() const { return m_rpc_port; } + uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; } + + CBaseChainParams() = delete; + CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port) + : m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {} + +private: + const uint16_t m_rpc_port; + const uint16_t m_onion_service_target_port; + std::string strDataDir; +}; + +/** + * Creates and returns a std::unique_ptr of the chosen chain. + */ +std::unique_ptr CreateBaseChainParams(const ChainType chain); + +/** + * Set the arguments for chainparams + */ +void SetupChainParamsBaseOptions(ArgsManager& argsman); + +/** + * Return the currently selected parameters. This won't change after app + * startup, except for unit tests. + */ +const CBaseChainParams& BaseParams(); + +/** Sets the params returned by Params() to those for the given chain. */ +void SelectBaseParams(const ChainType chain); + +#endif // BITCOIN_CHAINPARAMSBASE_H + diff --git a/src/chainparamsseeds.h b/src/chainparamsseeds.h index 15151e0db2..76ac50a08a 100644 --- a/src/chainparamsseeds.h +++ b/src/chainparamsseeds.h @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef CHAINPARAMSSEEDS_H #define CHAINPARAMSSEEDS_H diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 49871c9bea..e8fe28789f 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -1,9 +1,11 @@ -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include // for 'map_list_of()' -#include #include "checkpoints.h" @@ -26,39 +28,26 @@ namespace Checkpoints // MapCheckpoints mapCheckpoints = boost::assign::map_list_of - ( 0, uint256("0x00000eca234f07edc98aaf3f2a7b7478dc58992a9cd439323d099c6a590ca2bb") ) // Params().HashGenesisBlock()) - ( 5000, uint256("0xe90df0416d506c6d41ea693c88604e6efde1467408adeccf7166cdec9192c03b") ) - ( 10000, uint256("0x1f0aa0f5e122d0dbba13adf896eb2a6645c150f4710d0a595d2eec886a9d17e4") ) - ( 15000, uint256("0x00000000024472d3430e135eccc90852469b0803a05eb54dd9d7d249b8903e11") ) - ( 20000, uint256("0x0000000000534b3b94bd3cce077ff71f376b5620c6352c37ba6c78731372e9f4") ) - ( 25000, uint256("0x0000000000e0eea4f099e4123b846e21572ba00fbf687ad6d8c9fe99a4631ff5") ) - ( 30000, uint256("0xb798139d55efee3285f5287f751751132a07979ac3b4584351293fd93e0355f6") ) - ( 40000, uint256("0x28f84253a82ec149dafc1de9cb6116118b13438f4f0c1b0536643bf4911f181f") ) - ( 50000, uint256("0x77b8eca44ac760d9990ba8d68beabf73bf156093e076f50b4eb00bff2d0ded52") ) - ( 60000, uint256("0xef24a387dd6ba7fb9aa9c7edfc3fbfc3ccdd2406a1be8e24426eca41d19996d5") ) - ( 70000, uint256("0xe6369ee665c6a4a00bac6fa707123887144a5855eb45cd7a1d164d27707a0e93") ) - ( 80000, uint256("0x09b00f6efb3a94de1c58ad578d19c1d7d74b0a6e101f750478ae987a713c6143") ) - ( 90000, uint256("0xbf7040b9157c4611265371b9b2d6250aa956c6c237c4222a70a93dad800ff7d9") ) - ( 100000, uint256("0x6768cdd2f7630b68d61bf82cdd133bed2e7c858aba7e58190ed541c707a82daf") ) - ( 110000, uint256("0xb582e172d169bc67adc79969c35851c9156b5a4ad57c3fb3647a3aed20c8ba51") ) - ( 120000, uint256("0xa4d5f4a951f2cb5f6beafcbf8490a4645ac7585f0389d730613d4e22a96590eb") ) - ( 130000, uint256("0xa51baaa8f0b5f35217479b4defd61f3ae18b5792033a723dd9bd802a78b48803") ) - ( 140000, uint256("0x179d20535a7cd197c9e79258aac98c193cffa0265ce2ec0ea8c71b2e7f1fc021") ) - ( 150000, uint256("0x5d78df4991a4f10879452680f4643c27ef603f3928ff0d6ac05b5f14e5182029") ) - ( 160000, uint256("0x2fecb1a06ec490922e500b653948923952a6241c478df754f894c3b66d95f234") ) - ( 170000, uint256("0x04aa633b0850a8ca967ab40436c3068c385000d2ad08def923c8cb1328affa49") ) - ( 180000, uint256("0x79f341c763f658833280f62e70d04ecdb4c8e22181dca4e423692dd6d2dc7c92") ) - ( 190000, uint256("0x19ff2576455a3256772efebc1d88c356ebe18c74005454880cf46fab50c627c7") ) - ( 200000, uint256("0xd9af28b1b16e20aff1bdafdbdeaa793af8475681e3c2b5b6ad13d28ae6da6b1e") ) - ( 245000, uint256("0xe075bf70c40a7c18cc7bf305b2922ca690a13473b6edf05b4a452a85539fe50c") ) - ( 250000, uint256("0x19a6a7fe4d2b6db91160a2b0e46bf5045e8b9f3c3e15016c48e77657cadaa5b8") ) - ( 300000, uint256("0xb7f4f3b08a10eb7045cdfc7070856530dfae6fa4630b983b2922be80dfd91f3e") ) - ( 350000, uint256("0x27e5167742fa86a107a7823eac252985199fcf4e0aa8fa438af3d9b0e609824f") ) - ( 400000, uint256("0x25d4b6ab78cf3648b5b86bbcfe5f975a02ae1006231f84a19f9af598a0ae7557") ) - ( 500000, uint256("0xa85a7561b73c2549bf909fb3b51b384d915b8f83c321fc4977b201d4be2a8a0b") ) - ( 590000, uint256("0x680d2a36efdf4989c82cf144c36ba7ca398d0ba557f00ae51de07cba649823b4") ) - ( 765000, uint256("0x40fd13a50feaca5a54dd7834b97b2ddce2fee85b42a95ea2079edd3a81f22857") ) - ; + ( 0, uint256("0x000001fd6111f0d71d90b7d8c827c6028dbc867f6c527d90794a0d22f68fecd4") ) // Params().HashGenesisBlock()) + ( 10000, uint256("0x89fa592395c4fff97e04ade632dfc33bee19fc46d489abf51331ee68a20ad19d") ) + ( 15000, uint256("0xb54f2cc3bc31a0f7110ef5f95a1c00744793f5419b1d43044fe393a777edca39") ) + ( 20000, uint256("0x87294db40d1af9101876293140cb2d82aef893881fbdb2a48ef0b0e062b6966a") ) + ( 25000, uint256("0x70aaaf2d6dd706fa4689a5e6e17994342e661ea37f72333e63534cf0cc3d7dc1") ) + ( 100000, uint256("0x4f61bb5f1b22065242784fdb0232ed6ef66ec3e5049d412038f4753dca931cd1") ) + ( 200000, uint256("0x62f50e7c60480ded7aceed530a6d2f2b204647443425316e5f5714da489d55e3") ) + ( 300000, uint256("0xe355a6acab9a5a8ae5f5ba0336e3efd40145726106dd1a33a314a86a1dfb8fca") ) + ( 400000, uint256("0xe09449a9923e5f99d224fbc088ae5c79c6fa2caf511c2a702c27d2afa570b9b7") ) + ( 500000, uint256("0x3797b3133f61859680141058755cc8224db7b17f6c06f9228b7e2fd7b7e48cf5") ) + ( 600000, uint256("0x6b8e1852d66a954e94ee85b239ca1a04ee18f676e8ed6b9980f2eb0ccfa0ca9e") ) + ( 700000, uint256("0x501b1398372508e8806f49de18a579d482895331b958dda932f0ec451a590497") ) + ( 800000, uint256("0xa502c68dc02f39237b2d961ade76d403869939004965eff53d529d436b117c3a") ) + ( 900000, uint256("0x79ae3d0df2e1fc905781ce893d3ead49799f8100c606ae613389dd3f7c1161f2") ) + ( 1000000, uint256("0x9e2738c1c40209ee73a9ca0ea1edaa3610d768007b614fb334bdbcb46d2d1991") ) + ( 1100000, uint256("0x33dfe0abae17bc1cff0a8f3d3f9c4471666d9092182963baa61a2cb3d0ad9283") ) + ( 1200000, uint256("0x135c94cb8cdf81173ceb6d01f98df1b74ab0bf95aa3553a2158fef3bc733794d") ) + ( 1232433, uint256("0x5a17e0f06d3863b5678b5f24b4b1e203dc0d94ec55b4f41f5d9d2a961686b0c2") ) + ( 1245000, uint256("0xa0cd983150296cb14d2e4006464a1b0814bd53bf76f35f00cf8d0530dd0f511e") ) + ; // TestNet has no checkpoints MapCheckpoints mapCheckpointsTestnet; @@ -93,7 +82,7 @@ namespace Checkpoints if (t != mapBlockIndex.end()) return t->second; } - return NULL; + return nullptr; } CBlockThinIndex* GetLastCheckpoint(const std::map& mapBlockThinIndex) @@ -107,11 +96,11 @@ namespace Checkpoints if (t != mapBlockThinIndex.end()) return t->second; } - return NULL; + return nullptr; } - // Automatically select a suitable sync-checkpoint + // Automatically select a suitable sync-checkpoint const CBlockIndex* AutoSelectSyncCheckpoint() { const CBlockIndex *pindex = pindexBest; diff --git a/src/checkpoints.h b/src/checkpoints.h index 212598225c..9b3b2c16a4 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -1,6 +1,10 @@ -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_CHECKPOINT_H #define BITCOIN_CHECKPOINT_H diff --git a/src/clientversion.h.in b/src/clientversion.h.in new file mode 100644 index 0000000000..f3957e0095 --- /dev/null +++ b/src/clientversion.h.in @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef CLIENTVERSION_H +#define CLIENTVERSION_H + +// +// client versioning +// + +// These need to be macros, as version.cpp's and alias-qt.rc's voodoo requires it +#define CLIENT_VERSION_MAJOR @CLIENT_VERSION_MAJOR@ +#define CLIENT_VERSION_MINOR @CLIENT_VERSION_MINOR@ +#define CLIENT_VERSION_REVISION @CLIENT_VERSION_REVISION@ +#define CLIENT_VERSION_BUILD @CLIENT_VERSION_BUILD@ +#define GIT_HASH "@CLIENT_VERSION_GIT_SHA1@" + +// Converts the parameter X to a string after macro replacement on X has been performed. +// Don't merge these into one macro! +#define STRINGIZE(X) DO_STRINGIZE(X) +#define DO_STRINGIZE(X) #X + +#endif // CLIENTVERSION_H diff --git a/src/clientversion.h b/src/clientversion.h.obsolete similarity index 57% rename from src/clientversion.h rename to src/clientversion.h.obsolete index 1be6ecc5f1..d43a0bf31d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h.obsolete @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef CLIENTVERSION_H #define CLIENTVERSION_H @@ -6,10 +12,10 @@ // // These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 1 -#define CLIENT_VERSION_MINOR 5 +#define CLIENT_VERSION_MAJOR 4 +#define CLIENT_VERSION_MINOR 3 #define CLIENT_VERSION_REVISION 0 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 0 // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! diff --git a/src/coincontrol.h b/src/coincontrol.h index 236b586552..72a99ecefa 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef COINCONTROL_H #define COINCONTROL_H @@ -11,34 +17,34 @@ class CCoinControl { SetNull(); } - + void SetNull() { destChange = CNoDestination(); setSelected.clear(); } - + bool HasSelected() const { return (setSelected.size() > 0); } - + bool IsSelected(const uint256& hash, unsigned int n) const { COutPoint outpt(hash, n); return (setSelected.count(outpt) > 0); } - + void Select(COutPoint& output) { setSelected.insert(output); } - + void UnSelect(COutPoint& output) { setSelected.erase(output); } - + void UnSelectAll() { setSelected.clear(); @@ -48,7 +54,7 @@ class CCoinControl { vOutpoints.assign(setSelected.begin(), setSelected.end()); } - + private: std::set setSelected; diff --git a/src/common/args.h b/src/common/args.h new file mode 100644 index 0000000000..db5be7e4eb --- /dev/null +++ b/src/common/args.h @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2023 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_COMMON_ARGS_H +#define ALIAS_COMMON_ARGS_H + +#include + +#include +#include +#include +#include +#include +#include + +class ArgsManager { +public: + enum Flags : uint32_t { + ALLOW_ANY = 0x01, + NETWORK_ONLY = 0x02, + SENSITIVE = 0x04, + COMMAND = 0x08, + DEBUG_ONLY = 0x10, + HIDDEN = 0x20, + DISALLOW_NEGATION = 0x40, + DISALLOW_ELISION = 0x80, + }; + + ArgsManager(); + ~ArgsManager(); + + void SelectConfigNetwork(const std::string& network); + bool ParseParameters(int argc, const char* const argv[], std::string& error); + bool ReadConfigFiles(std::string& error, bool ignore_invalid_keys = false); + + std::set GetUnsuitableSectionOnlyArgs() const; + std::vector GetUnrecognizedSections() const; + + const fs::path& GetBlocksDirPath() const; + const fs::path& GetDataDirBase() const; + const fs::path& GetDataDirNet() const; + void ClearPathCache(); + + std::vector GetArgs(const std::string& arg) const; + bool IsArgSet(const std::string& arg) const; + bool IsArgNegated(const std::string& arg) const; + std::string GetArg(const std::string& arg, const std::string& default_val) const; + std::optional GetArg(const std::string& arg) const; + fs::path GetPathArg(const std::string& arg, const fs::path& default_val = {}) const; + int64_t GetIntArg(const std::string& arg, int64_t default_val) const; + std::optional GetIntArg(const std::string& arg) const; + bool GetBoolArg(const std::string& arg, bool default_val) const; + std::optional GetBoolArg(const std::string& arg) const; + + bool SoftSetArg(const std::string& arg, const std::string& value); + bool SoftSetBoolArg(const std::string& arg, bool value); + void ForceSetArg(const std::string& arg, const std::string& value); + + std::string GetChainTypeString() const; + + void AddArg(const std::string& name, const std::string& help, unsigned int flags, const std::string& category); + void AddHiddenArgs(const std::vector& args); + void ClearArgs(); + + std::string GetHelpMessage() const; + + void LogArgs() const; + +protected: + struct Arg { + std::string m_help_text; + unsigned int m_flags; + }; + + mutable std::mutex cs_args; + std::map> m_settings; + std::map> m_config_args; + std::string m_network; + std::set m_network_only_args; + std::map m_available_args; + bool m_accept_any_command{true}; + std::list m_command; + + mutable fs::path m_cached_blocks_path; + mutable fs::path m_cached_datadir_path; + mutable fs::path m_cached_network_datadir_path; + + [[nodiscard]] bool ReadConfigStream(std::istream& stream, const std::string& filepath, std::string& error, bool ignore_invalid_keys = false); + + std::optional GetArgHelper(const std::string& arg) const; + std::vector GetArgsHelper(const std::string& arg) const; +}; + +extern ArgsManager gArgs; + +bool HelpRequested(const ArgsManager& args); +void SetupHelpOptions(ArgsManager& args); + +std::string HelpMessageGroup(const std::string& message); +std::string HelpMessageOpt(const std::string& option, const std::string& message); + +void PrintExceptionContinue(const std::exception* pex, const std::string& thread_name); + +fs::path AbsPathForConfigVal(const ArgsManager& args, const fs::path& path, bool net_specific = true); + +#endif // ALIAS_COMMON_ARGS_H diff --git a/src/compat.h b/src/compat.h index 6b7639652c..954baf4432 100644 --- a/src/compat.h +++ b/src/compat.h @@ -1,7 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef _BITCOIN_COMPAT_H #define _BITCOIN_COMPAT_H 1 @@ -31,7 +35,6 @@ typedef u_int SOCKET; #endif - #ifdef WIN32 #define MSG_NOSIGNAL 0 #define MSG_DONTWAIT 0 diff --git a/src/consensus/params.h b/src/consensus/params.h new file mode 100644 index 0000000000..aeb3854553 --- /dev/null +++ b/src/consensus/params.h @@ -0,0 +1,179 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CONSENSUS_PARAMS_H +#define BITCOIN_CONSENSUS_PARAMS_H + +#include + +#include +#include +#include +#include + +namespace Consensus { + +/** + * A buried deployment is one where the height of the activation has been hardcoded into + * the client implementation long after the consensus change has activated. See BIP 90. + */ +enum BuriedDeployment : int16_t { + // buried deployments get negative values to avoid overlap with DeploymentPos + DEPLOYMENT_HEIGHTINCB = std::numeric_limits::min(), + DEPLOYMENT_CLTV, + DEPLOYMENT_DERSIG, + DEPLOYMENT_CSV, + DEPLOYMENT_SEGWIT, +}; +constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_SEGWIT; } + +enum DeploymentPos : uint16_t { + DEPLOYMENT_TESTDUMMY, + DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342) + // NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp + MAX_VERSION_BITS_DEPLOYMENTS +}; +constexpr bool ValidDeployment(DeploymentPos dep) { return dep < MAX_VERSION_BITS_DEPLOYMENTS; } + +/** + * Struct for each individual consensus rule change using BIP9. + */ +struct BIP9Deployment { + /** Bit position to select the particular bit in nVersion. */ + int bit{28}; + /** Start MedianTime for version bits miner confirmation. Can be a date in the past */ + int64_t nStartTime{NEVER_ACTIVE}; + /** Timeout/expiry MedianTime for the deployment attempt. */ + int64_t nTimeout{NEVER_ACTIVE}; + /** If lock in occurs, delay activation until at least this block + * height. Note that activation will only occur on a retarget + * boundary. + */ + int min_activation_height{0}; + + /** Constant for nTimeout very far in the future. */ + static constexpr int64_t NO_TIMEOUT = std::numeric_limits::max(); + + /** Special value for nStartTime indicating that the deployment is always active. + * This is useful for testing, as it means tests don't need to deal with the activation + * process (which takes at least 3 BIP9 intervals). Only tests that specifically test the + * behaviour during activation cannot use this. */ + static constexpr int64_t ALWAYS_ACTIVE = -1; + + /** Special value for nStartTime indicating that the deployment is never active. + * This is useful for integrating the code changes for a new feature + * prior to deploying it on some or all networks. */ + static constexpr int64_t NEVER_ACTIVE = -2; +}; + +/** + * Parameters that influence chain consensus. + * Alias-specific additions for PoSv3/PoAS and fork support. + */ +struct Params { + uint256 hashGenesisBlock; + + int nSubsidyHalvingInterval; + /** + * Hashes of blocks that + * - are known to be consensus valid, and + * - buried in the chain, and + * - fail if the default script verify flags are applied. + */ + std::map script_flag_exceptions; + /** Block height and hash at which BIP34 becomes active */ + int BIP34Height; + uint256 BIP34Hash; + /** Block height at which BIP65 becomes active */ + int BIP65Height; + /** Block height at which BIP66 becomes active */ + int BIP66Height; + /** Block height at which CSV (BIP68, BIP112 and BIP113) becomes active */ + int CSVHeight; + /** Block height at which Segwit (BIP141, BIP143 and BIP147) becomes active. + * Note that segwit v0 script rules are enforced on all blocks except the + * BIP 16 exception blocks. */ + int SegwitHeight; + /** Don't warn about unknown BIP 9 activations below this height. */ + int MinBIP9WarningHeight; + + // Alias-specific consensus parameters + bool m_alias_mode = true; + + /** Alias fork times */ + int64_t nForkV2Time = 0; // V2 chain fork time + int64_t nForkV3Time = 0; // V3 chain fork time + int64_t nForkV4Time = 0; // V4 chain fork time + + /** Alias PoS parameters */ + int nLastPOWBlock = 0; // Last block that allows PoW + int nFirstPosv2Block = 0; // First block using PoSv2 + int nFirstPosv3Block = 0; // First block using PoSv3 + + /** Ring signature parameters (Alias-specific) */ + size_t m_min_ringsize = 10; // Fixed ring size for Alias + size_t m_max_ringsize = 10; // Fixed ring size for Alias + size_t m_max_anon_inputs = 32; + int64_t m_max_anon_output = 1000 * 100000000LL; // 1000 ALIAS in satoshi + + /** Minimum depth a Particl Anon output is spendable at (Alias uses similar) */ + int nMinRCTOutputDepth = 12; + + /** + * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, + * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. + * Examples: 1916 for 95%, 1512 for testchains. + */ + uint32_t nRuleChangeActivationThreshold; + uint32_t nMinerConfirmationWindow; + BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]; + /** Proof of work parameters */ + uint256 powLimit; + bool fPowAllowMinDifficultyBlocks; + bool fPowNoRetargeting; + int64_t nPowTargetSpacing; // Alias: 96 seconds + int64_t nPowTargetTimespan; // Alias: 24 hours (moving average) + std::chrono::seconds PowTargetSpacing() const + { + return std::chrono::seconds{nPowTargetSpacing}; + } + int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; } + /** The best chain should have at least this much work */ + uint256 nMinimumChainWork; + /** By default assume that the signatures in ancestors of this block are valid */ + uint256 defaultAssumeValid; + + /** + * If true, witness commitments contain a payload equal to a Bitcoin Script solution + * to the signet challenge. See BIP325. + */ + bool signet_blocks{false}; + std::vector signet_challenge; + + int DeploymentHeight(BuriedDeployment dep) const + { + switch (dep) { + case DEPLOYMENT_HEIGHTINCB: + return BIP34Height; + case DEPLOYMENT_CLTV: + return BIP65Height; + case DEPLOYMENT_DERSIG: + return BIP66Height; + case DEPLOYMENT_CSV: + return CSVHeight; + case DEPLOYMENT_SEGWIT: + return SegwitHeight; + } // no default case, so the compiler can warn about missing cases + return std::numeric_limits::max(); + } +}; + +} // namespace Consensus + +#endif // BITCOIN_CONSENSUS_PARAMS_H + diff --git a/src/core.cpp b/src/core.cpp index ea07be730b..5c5bcf8aee 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -1,8 +1,165 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "core.h" +void addAnonOutput(CPubKey& pkAo, CAnonOutput& anonOutput, txMixins_container& txMixinsContainer) +{ + // create pair with vout index of tx and pubKey + const auto & pairOutPubkey = std::make_pair(anonOutput.outpoint.n, pkAo); + // check if CTxMixins does already exist in container for tx hash + const auto & txHashIndex = txMixinsContainer.get(); + const auto it = txHashIndex.find(anonOutput.outpoint.hash); + if (it != txHashIndex.end()) + // add anon pubKey to existing CTxMixins in container + it->vOutPubKeys.push_back(pairOutPubkey); + else + { + CTxMixins txMixins(anonOutput.outpoint.hash); + txMixins.vOutPubKeys.push_back(pairOutPubkey); + txMixinsContainer.push_back(txMixins); + } +} + +void CMixins::AddAnonOutput(CPubKey& pkAo, CAnonOutput& anonOutput, int blockHeight) +{ + CTxMixinsContainers& txMixinsContainers = mapMixins[anonOutput.nValue]; + + if (blockHeight - anonOutput.nBlockHeight < 2700) // blocks of last 3 days + // add anon to recent mixins container + addAnonOutput(pkAo, anonOutput, txMixinsContainers.get(RECENT)); + else + // add anon to old mixins container + addAnonOutput(pkAo, anonOutput, txMixinsContainers.get(OLD)); +} + +void removeEmptyTx(txMixins_container& txMixinsContainer, std::set& setPickedTxInd) +{ + // Remove transactions which don't provide any more anons + for (auto iter = setPickedTxInd.rbegin(); iter != setPickedTxInd.rend(); ++iter) + { + const CTxMixins& txMixins = txMixinsContainer.at(*iter); + if (txMixins.vOutPubKeys.empty()) + { + if (fDebugRingSig) + LogPrintf("CMixins::removeEmptyTx() : erase tx %s.\n", txMixins.txHash.ToString()); + txMixinsContainer.erase(txMixinsContainer.begin() + *iter); + } + } +} + +void pick(std::vector>& vUsedTx, CTxMixinsContainers& txMixinsContainers, int containerId, std::set& setPickedTxInd, std::vector& vPickedAnons) +{ + txMixins_container& txMixinsContainer = txMixinsContainers.get(containerId); + // Pick a random transaction + uint64_t nAvailableTx = txMixinsContainer.size() - setPickedTxInd.size(); + uint64_t iPickTx = GetRand(nAvailableTx); + // adust the pick index to skip already used transactions + for (const auto & iPickedTx : setPickedTxInd) + if (iPickedTx <= iPickTx) + iPickTx++; + + const CTxMixins& txMixins = txMixinsContainer.at(iPickTx); + // Remember for this picking loop, the transaction from which the anon was picked + setPickedTxInd.insert(iPickTx); + + // Pick random a anon from the picked transaction + uint64_t iPickAnon = GetRand(txMixins.vOutPubKeys.size()); + const auto & [iVout, pubKey] = txMixins.vOutPubKeys.at(iPickAnon); + vPickedAnons.push_back(pubKey); + if (fDebugRingSig) + LogPrintf("CMixins::pick() : pick mixin %d from %s tx %s vout %d.\n", + vPickedAnons.size(), containerId == OLD ? "OLD" : "RECENT", txMixins.txHash.ToString(), iVout); + + // Erase the anon, every anon can only be used once as mixin per transaction + txMixins.vOutPubKeys.erase(txMixins.vOutPubKeys.begin() + iPickAnon); + + // Remember for CMixins state, the transaction from which the anon was picked + auto pairContTx = std::make_pair(containerId, txMixins.txHash); + if (std::find(vUsedTx.begin(), vUsedTx.end(), pairContTx) == vUsedTx.end()) + vUsedTx.push_back(pairContTx); +} + + +bool CMixins::Pick(int64_t nValue, uint8_t nMixins, std::vector& vPickedAnons) +{ + int64_t nStart = GetTimeMicros(); + std::set setPickedTxInd[2]; + CTxMixinsContainers& txMixinsContainers = mapMixins[nValue]; + uint64_t nUsedTx = vUsedTx.size(); + + if (fDebugRingSig) + LogPrintf("CMixins::Pick() : pick %d mixins of value %d from %d recent and %d old transactions. Previously picked txs: %d.\n", + nMixins, nValue, txMixinsContainers.get(RECENT).size(), txMixinsContainers.get(OLD).size(), nUsedTx); + + if (txMixinsContainers.get(OLD).size() + txMixinsContainers.get(RECENT).size() < nMixins) + return false; + + for (uint8_t i = 0; i < nMixins; i++) + { + uint64_t mode = GetRand(100); + if (mode < 33 && nUsedTx > 0) + { + // take mixin from used transactions + if (fDebugRingSig) + LogPrintf("CMixins::Pick() : try to pick from %d previously picked tx.\n", nUsedTx); + // shuffle previous picked transaction list to make sure order of tx pick does not reveal its fake nature + std::shuffle(vUsedTx.begin(), vUsedTx.begin() + nUsedTx, urng); + bool foundMixin = false; + uint64_t iUsedTx = 0; + for (const auto & [iContainer, txHash] : vUsedTx) + { + if (iUsedTx++ >= nUsedTx) + break; + + txMixins_container& txMixinsContainer = txMixinsContainers.get(iContainer); + auto & txHashIndex = txMixinsContainer.get(); + auto it = txHashIndex.find(txHash); + if (it != txHashIndex.end()) + { + // Get index of tx in containers random index + uint64_t iPickTx = txMixinsContainer.iterator_to(*it) - txMixinsContainer.begin(); + + // check if tx was already used for this ring sig + if (setPickedTxInd[iContainer].find(iPickTx) != setPickedTxInd[iContainer].end()) + continue; + + // Pick random a anon from the transacton + uint64_t iPickAnon = GetRand(it->vOutPubKeys.size()); + const auto & [iVout, pubKey] = it->vOutPubKeys.at(iPickAnon); + vPickedAnons.push_back(pubKey); + if (fDebugRingSig) + LogPrintf("CMixins::Pick() : pick mixin %d from prev tx %s vout %d.\n", vPickedAnons.size(), txHash.ToString(), iVout); + // Erase the anon, every anon can only be used once as mixin per transaction + it->vOutPubKeys.erase(it->vOutPubKeys.begin() + iPickAnon); + + // Remember for this picking loop, the transaction from which the anon was picked + setPickedTxInd[iContainer].insert(iPickTx); + foundMixin = true; + break; + } + } + if (foundMixin) + continue; + } + + uint64_t nAvailableOldTx = txMixinsContainers.get(OLD).size() - setPickedTxInd[OLD].size(); + uint64_t nAvailableRecentTx = txMixinsContainers.get(RECENT).size() - setPickedTxInd[RECENT].size(); + int containerId = nAvailableRecentTx > 0 && (mode >= 66 || nAvailableOldTx == 0) ? RECENT : OLD; + pick(vUsedTx, txMixinsContainers, containerId, setPickedTxInd[containerId], vPickedAnons); + } + // Remove transactions which don't provide any more anons + removeEmptyTx(txMixinsContainers.get(RECENT), setPickedTxInd[RECENT]); + removeEmptyTx(txMixinsContainers.get(OLD), setPickedTxInd[OLD]); + + if (fDebugRingSig) + LogPrintf("CMixins::Pick() : picked %d mixins in %d µs.\n", nMixins, GetTimeMicros() - nStart); + return true; +} + diff --git a/src/core.h b/src/core.h index 536f4dd2f3..2e2489bcd9 100644 --- a/src/core.h +++ b/src/core.h @@ -1,9 +1,12 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT -#ifndef SDC_CORE_H -#define SDC_CORE_H +#ifndef SPEC_CORE_H +#define SPEC_CORE_H #include #include @@ -15,12 +18,19 @@ #include "script.h" #include "ringsig.h" +#include +#include + +#include +#include +#include +#include + enum GetMinFee_mode { GMF_BLOCK, GMF_RELAY, GMF_SEND, - GMF_ANON, }; class CTransaction; @@ -71,10 +81,10 @@ class CInPoint CTransaction* ptx; unsigned int n; - CInPoint() { SetNull(); } - CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; } - void SetNull() { ptx = NULL; n = (unsigned int) -1; } - bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); } + CInPoint() : ptx(nullptr), n((unsigned int)-1) { } + CInPoint(CTransaction* ptxIn, unsigned int nIn) : ptx(ptxIn), n(nIn) { } + void SetNull() { ptx = nullptr; n = (unsigned int) -1; } + bool IsNull() const { return (ptx == nullptr && n == (unsigned int) -1); } }; @@ -280,24 +290,27 @@ class CKeyImageSpent { // stored in txdb, key is keyimage public: - CKeyImageSpent() {}; + CKeyImageSpent() : inputNo(0), nValue(0), nBlockHeight(0) { } CKeyImageSpent(uint256& txnHash_, uint32_t inputNo_, int64_t nValue_) + : txnHash(txnHash_) + , inputNo(inputNo_) + , nValue(nValue_) + , nBlockHeight(0) { - txnHash = txnHash_; - inputNo = inputNo_; - nValue = nValue_; - }; + } uint256 txnHash; // hash of spending transaction uint32_t inputNo; // keyimage is for inputNo of txnHash int64_t nValue; // reporting only + int nBlockHeight; // block which included the spent IMPLEMENT_SERIALIZE ( READWRITE(txnHash); READWRITE(inputNo); READWRITE(nValue); + READWRITE(nBlockHeight); ) }; @@ -306,26 +319,29 @@ class CAnonOutput // stored in txdb, key is pubkey public: - CAnonOutput() {}; + CAnonOutput() : nValue(0), nBlockHeight(0), nCompromised(0), fCoinStake(0) { } - CAnonOutput(COutPoint& outpoint_, int64_t nValue_, int nBlockHeight_, uint8_t nCompromised_) + CAnonOutput(COutPoint& outpoint_, int64_t nValue_, int nBlockHeight_, uint8_t nCompromised_, char fCoinStake_) + : outpoint(outpoint_) + , nValue(nValue_) + , nBlockHeight(nBlockHeight_) + , nCompromised(nCompromised_) + , fCoinStake(fCoinStake_) { - outpoint = outpoint_; - nValue = nValue_; - nBlockHeight = nBlockHeight_; - nCompromised = nCompromised_; - }; + } COutPoint outpoint; int64_t nValue; // rather store 2 bytes, digit + power 10 ? int nBlockHeight; uint8_t nCompromised; // TODO: mark if output can be identified (spent with ringsig 1) + char fCoinStake; IMPLEMENT_SERIALIZE ( READWRITE(outpoint); READWRITE(nValue); READWRITE(nBlockHeight); READWRITE(nCompromised); + READWRITE(fCoinStake); ) }; @@ -334,49 +350,67 @@ class CAnonOutputCount public: CAnonOutputCount() + : nValue(0) + , nExists(0) + , nUnconfirmed(0) + , nSpends(0) + , nOwned(0) + , nLastHeight(0) + , nCompromised(0) + , nCompromisedHeight(0) + , nMature(0) + , nMixins(0) + , nMixinsStaking(0) + , nStakes(0) { - nValue = 0; - nExists = 0; - nSpends = 0; - nOwned = 0; - nLeastDepth = 0; - nCompromised = 0; } - CAnonOutputCount(int64_t nValue_, int nExists_, int nSpends_, int nOwned_, int nLeastDepth_, int nCompromised_) + CAnonOutputCount(int64_t nValue_, int nExists_, int nUnconfirmed_, int nSpends_, int nOwned_, int nLastHeight_, int nCompromised_, int nMature_, int nMixins_, int nMixinsStaking_, int nStakes_, int nCompromisedHeight_) { nValue = nValue_; nExists = nExists_; nSpends = nSpends_; + nUnconfirmed = nUnconfirmed_; nOwned = nOwned_; - nLeastDepth = nLeastDepth_; + nLastHeight = nLastHeight_; nCompromised = nCompromised_; + nMature = nMature_; + nMixins = nMixins_; + nMixinsStaking = nMixinsStaking_; + nStakes = nStakes_; + nCompromisedHeight = nCompromisedHeight_; } - void set(int64_t nValue_, int nExists_, int nSpends_, int nOwned_, int nLeastDepth_, int nCompromised_) + void set(int64_t nValue_, int nExists_, int nUnconfirmed_, int nSpends_, int nOwned_, int nLastHeight_, int nCompromised_, int nMature_, int nMixins_, int nMixinsStaking_, int nStakes_, int nCompromisedHeight_) { nValue = nValue_; nExists = nExists_; nSpends = nSpends_; + nUnconfirmed = nUnconfirmed_; nOwned = nOwned_; - nLeastDepth = nLeastDepth_; + nLastHeight = nLastHeight_; nCompromised = nCompromised_; + nMature = nMature_; + nMixins = nMixins_; + nMixinsStaking = nMixinsStaking_; + nStakes = nStakes_; + nCompromisedHeight = nCompromisedHeight_; } - void addCoin(int nCoinDepth, int64_t nCoinValue) + void addCoin(int nBlockHeight, int64_t nCoinValue, bool fStake) { nExists++; nValue = nCoinValue; - if (nCoinDepth < nLeastDepth) - nLeastDepth = nCoinDepth; + nStakes += fStake; + if (nBlockHeight > nLastHeight) + nLastHeight = nBlockHeight; } - void updateDepth(int nCoinDepth, int64_t nCoinValue) + void updateDepth(int nBlockHeight, int64_t nCoinValue) { nValue = nCoinValue; - if (nLeastDepth == 0 - || nCoinDepth < nLeastDepth) - nLeastDepth = nCoinDepth; + if (nBlockHeight > nLastHeight) + nLastHeight = nBlockHeight; } void incSpends(int64_t nCoinValue) @@ -403,14 +437,29 @@ class CAnonOutputCount nValue = nCoinValue; } + int numOfUnspends() + { + return nExists - nSpends; + } + + int numOfMatureUnspends() + { + return nMature - nSpends; + } + int64_t nValue; int nExists; + int nUnconfirmed; int nSpends; int nOwned; // todo - int nLeastDepth; + int nLastHeight; int nCompromised; - + int nCompromisedHeight; + int nMature; + int nMixins; + int nMixinsStaking; + int nStakes; }; @@ -429,5 +478,57 @@ class CStakeModifier int64_t nTime; }; -#endif // SDC_CORE_H + +struct CTxMixins +{ + CTxMixins(uint256 txHash_) : txHash(txHash_) { } + + uint256 txHash; + mutable std::vector> vOutPubKeys; +}; + +using namespace boost::multi_index; +// tags +struct TXHASH{}; +typedef boost::multi_index_container< + CTxMixins, + indexed_by< + random_access<>, + ordered_unique, member > + > +> txMixins_container; + +enum TxMixinsContainerId { OLD, RECENT }; +class CTxMixinsContainers +{ +private: + txMixins_container old; + txMixins_container recent; +public: + txMixins_container& get(int containerId) + { + return containerId == RECENT ? recent : old; + } +}; + +class CMixins +{ +// for mixin selection +public: + CMixins() : CMixins(initUrng()) {} + void AddAnonOutput(CPubKey& pkAo, CAnonOutput& anonOutput, int blockHeight); + bool Pick(int64_t nValue, uint8_t nMixins, std::vector& vPickedAnons); +private: + CMixins(std::mt19937 urng) : urng(urng) {} + static std::mt19937 initUrng() + { + std::random_device rd; + return std::mt19937(rd()); + } + std::vector> vUsedTx; // vector with used transaction hashes as pair of containerId and tx hash + std::map mapMixins; // value to CTxMixinsSet + std::mt19937 urng; +}; + +#endif // SPEC_CORE_H diff --git a/src/crypter.cpp b/src/crypter.cpp index 7299668db9..a1bb0b27d5 100644 --- a/src/crypter.cpp +++ b/src/crypter.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2009-2012 The Bitcoin Developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "crypter.h" @@ -9,7 +12,6 @@ #include #include -#include #include #include #ifdef WIN32 @@ -73,15 +75,15 @@ bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector (nCLen); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); - if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); - if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); - EVP_CIPHER_CTX_cleanup(&ctx); + ctx = EVP_CIPHER_CTX_new(); + if (fOk) fOk = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, chKey, chIV); + if (fOk) fOk = EVP_EncryptUpdate(ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); + if (fOk) fOk = EVP_EncryptFinal_ex(ctx, (&vchCiphertext[0])+nCLen, &nFLen); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; @@ -100,15 +102,15 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM vchPlaintext = CKeyingMaterial(nPLen); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); - if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); - EVP_CIPHER_CTX_cleanup(&ctx); + ctx = EVP_CIPHER_CTX_new(); + if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, chKey, chIV); + if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); + if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0])+nPLen, &nFLen); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; @@ -166,50 +168,50 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) { if (fDebug) LogPrintf("CCryptoKeyStore::Unlock()\n"); - + { LOCK(cs_KeyStore); if (!SetCrypted()) return false; - + int nUnlocked = 0; - + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); for (; mi != mapCryptedKeys.end(); ++mi) { const CPubKey &vchPubKey = (*mi).second.first; const std::vector &vchCryptedSecret = (*mi).second.second; CSecret vchSecret; - + if (vchCryptedSecret.size() < 1) // key was recieved from stealth/anon txn with wallet locked, will be expanded after this { if (fDebug) LogPrintf("Skipping unexpanded key %s.\n", vchPubKey.GetHash().ToString().c_str()); continue; }; - + if (!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) { LogPrintf("DecryptSecret() failed.\n"); return false; }; - + if (vchSecret.size() != 32) return false; - + CKey key; key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed()); - + if (key.GetPubKey() != vchPubKey) { LogPrintf("Unlock failed: PubKey mismatch %s.\n", vchPubKey.GetHash().ToString().c_str()); return false; }; - + nUnlocked++; break; }; - + if (nUnlocked < 1) // at least 1 key must pass the test { if (mapCryptedKeys.size() > 0) @@ -218,12 +220,12 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) return false; }; }; - + vMasterKey = vMasterKeyIn; } - + NotifyStatusChanged(this); - + return true; } @@ -244,7 +246,7 @@ bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) CKeyingMaterial vchSecret(key.begin(), key.end()); if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) return false; - + // -- NOTE: this is CWallet::AddCryptedKey if (!AddCryptedKey(pubkey, vchCryptedSecret)) return false; @@ -314,7 +316,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) return false; fUseCrypto = true; - BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys) + for (auto& mKey : mapKeys) { const CKey &key = mKey.second; CPubKey vchPubKey = key.GetPubKey(); diff --git a/src/crypter.h b/src/crypter.h index 277ccf075b..3a4d15815c 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -1,6 +1,10 @@ -// Copyright (c) 2009-2012 The Bitcoin Developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef __CRYPTER_H__ #define __CRYPTER_H__ @@ -50,16 +54,13 @@ class CMasterKey READWRITE(nDeriveIterations); READWRITE(vchOtherDerivationParameters); ) - CMasterKey() + CMasterKey() : nDerivationMethod(1), nDeriveIterations(25000) { // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M // ie slightly lower than the lowest hardware we need bother supporting - nDeriveIterations = 25000; - nDerivationMethod = 1; - vchOtherDerivationParameters = std::vector(0); } - CMasterKey(unsigned int nDerivationMethodIndex) + CMasterKey(unsigned int nDerivationMethodIndex) : nDerivationMethod(0), nDeriveIterations(25000) { switch (nDerivationMethodIndex) { @@ -67,14 +68,12 @@ class CMasterKey default: nDeriveIterations = 25000; nDerivationMethod = 0; - vchOtherDerivationParameters = std::vector(0); - break; + break; case 1: // scrypt+sha512 nDeriveIterations = 10000; nDerivationMethod = 1; - vchOtherDerivationParameters = std::vector(0); - break; + break; } } @@ -103,10 +102,8 @@ class CCrypter fKeySet = false; } - CCrypter() + CCrypter() : fKeySet(false) { - fKeySet = false; - // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap) // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process. @@ -170,8 +167,8 @@ class CCryptoKeyStore : public CBasicKeyStore bool LockKeyStore(); - virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); - + bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) override; + bool AddKey(const CKey& key); bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); bool HaveKey(const CKeyID &address) const diff --git a/src/currency.h b/src/currency.h new file mode 100644 index 0000000000..b076152c11 --- /dev/null +++ b/src/currency.h @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef CURRENCY_H +#define CURRENCY_H + +enum Currency +{ + PUBLIC, + PRIVATE +}; + +#endif // CURRENCY_H diff --git a/src/db.cpp b/src/db.cpp index 63d55d1f1d..57ca626ee8 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -1,15 +1,17 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "db.h" #include "net.h" #include "hash.h" #include "main.h" -#include "ui_interface.h" -#include -#include +#include "interface.h" +#include "util/fs.h" #ifndef WIN32 #include "sys/stat.h" @@ -57,19 +59,20 @@ void CDBEnv::Close() EnvShutdown(); } -bool CDBEnv::Open(boost::filesystem::path pathEnv_) +bool CDBEnv::Open(fs::path pathEnv_) { if (fDbEnvInit) return true; - + boost::this_thread::interruption_point(); - + pathEnv = pathEnv_; - boost::filesystem::path pathDataDir = pathEnv; + fs::path pathDataDir = pathEnv; strPath = pathDataDir.string(); - boost::filesystem::path pathLogDir = pathDataDir / "database"; - boost::filesystem::create_directory(pathLogDir); - boost::filesystem::path pathErrorFile = pathDataDir / "db.log"; + fs::path pathLogDir = pathDataDir / "database"; + fs::create_directory(pathLogDir); + fs::path pathErrorFile = pathDataDir / "db.log"; + LogPrintf("db version is %s\n", dbenv.version(nullptr, nullptr, nullptr)); LogPrintf("dbenv.open LogDir=%s ErrorFile=%s\n", pathLogDir.string().c_str(), pathErrorFile.string().c_str()); unsigned int nEnvFlags = 0; @@ -130,7 +133,7 @@ void CDBEnv::MakeMock() #ifdef DB_LOG_IN_MEMORY dbenv.log_set_config(DB_LOG_IN_MEMORY, 1); #endif - int ret = dbenv.open(NULL, + int ret = dbenv.open(nullptr, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | @@ -152,11 +155,11 @@ CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDB assert(mapFileUseCount.count(strFile) == 0); Db db(&dbenv, 0); - int result = db.verify(strFile.c_str(), NULL, NULL, 0); + int result = db.verify(strFile.c_str(), nullptr, nullptr, 0); if (result == 0) return VERIFY_OK; else - if (recoverFunc == NULL) + if (recoverFunc == nullptr) return RECOVER_FAIL; // Try to recover: @@ -176,7 +179,7 @@ bool CDBEnv::Salvage(std::string strFile, bool fAggressive, stringstream strDump; Db db(&dbenv, 0); - int result = db.verify(strFile.c_str(), NULL, &strDump, flags); + int result = db.verify(strFile.c_str(), nullptr, &strDump, flags); if (result == DB_VERIFY_BAD) { LogPrintf("Error: Salvage found errors, all data may not be recoverable.\n"); @@ -229,7 +232,7 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) CDB::CDB(const std::string& strFilename, const char* pszMode) : - pdb(NULL), activeTxn(NULL) + pdb(nullptr), activeTxn(nullptr) { int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); @@ -249,7 +252,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : strFile = strFilename; ++bitdb.mapFileUseCount[strFile]; pdb = bitdb.mapDb[strFile]; - if (pdb == NULL) + if (pdb == nullptr) { pdb = new Db(&bitdb.dbenv, 0); @@ -272,7 +275,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode) : if (ret != 0) { delete pdb; - pdb = NULL; + pdb = nullptr; --bitdb.mapFileUseCount[strFile]; strFile = ""; throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile.c_str())); @@ -305,8 +308,8 @@ void CDB::Close() return; if (activeTxn) activeTxn->abort(); - activeTxn = NULL; - pdb = NULL; + activeTxn = nullptr; + pdb = nullptr; // Flush database activity from memory pool to disk log unsigned int nMinutes = 0; @@ -329,13 +332,13 @@ void CDBEnv::CloseDb(const string& strFile) { { LOCK(cs_db); - if (mapDb[strFile] != NULL) + if (mapDb[strFile] != nullptr) { // Close the database handle Db* pdb = mapDb[strFile]; pdb->close(0); delete pdb; - mapDb[strFile] = NULL; + mapDb[strFile] = nullptr; } } } @@ -345,7 +348,7 @@ bool CDBEnv::RemoveDb(const string& strFile) this->CloseDb(strFile); LOCK(cs_db); - int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); + int rc = dbenv.dbremove(nullptr, strFile.c_str(), nullptr, DB_AUTO_COMMIT); return (rc == 0); } @@ -370,7 +373,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) CDB db(strFile.c_str(), "r"); Db* pdbCopy = new Db(&bitdb.dbenv, 0); - int ret = pdbCopy->open(NULL, // Txn pointer + int ret = pdbCopy->open(nullptr, // Txn pointer strFileRes.c_str(), // Filename "main", // Logical db name DB_BTREE, // Database type @@ -411,7 +414,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } Dbt datKey(&ssKey[0], ssKey.size()); Dbt datValue(&ssValue[0], ssValue.size()); - int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE); + int ret2 = pdbCopy->put(nullptr, &datKey, &datValue, DB_NOOVERWRITE); if (ret2 > 0) fSuccess = false; } @@ -427,10 +430,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) if (fSuccess) { Db dbA(&bitdb.dbenv, 0); - if (dbA.remove(strFile.c_str(), NULL, 0)) + if (dbA.remove(strFile.c_str(), nullptr, 0)) fSuccess = false; Db dbB(&bitdb.dbenv, 0); - if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) + if (dbB.rename(strFileRes.c_str(), nullptr, strFile.c_str(), 0)) fSuccess = false; } if (!fSuccess) @@ -516,7 +519,7 @@ bool CAddrDB::Write(const CAddrMan& addr) ssPeers << hash; // open temp output file, and associate with CAutoFile - boost::filesystem::path pathTmp = GetDataDir() / tmpfn; + fs::path pathTmp = GetDataDir() / tmpfn; FILE *file = fopen(pathTmp.string().c_str(), "wb"); CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION); if (!fileout) @@ -548,7 +551,7 @@ bool CAddrDB::Read(CAddrMan& addr) return error("CAddrman::Read() : open failed"); // use file size to size memory buffer - int fileSize = boost::filesystem::file_size(pathAddr); + int fileSize = fs::file_size(pathAddr); int dataSize = fileSize - sizeof(uint256); // Don't try to resize to a negative number if file is small if ( dataSize < 0 ) dataSize = 0; diff --git a/src/db.h b/src/db.h index 08888fdf9c..7fa202d491 100644 --- a/src/db.h +++ b/src/db.h @@ -1,7 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_DB_H #define BITCOIN_DB_H @@ -36,7 +40,7 @@ class CDBEnv bool fDetachDB; bool fDbEnvInit; bool fMockDb; - boost::filesystem::path pathEnv; + fs::path pathEnv; std::string strPath; void EnvShutdown(); @@ -70,7 +74,7 @@ class CDBEnv typedef std::pair, std::vector > KeyValPair; bool Salvage(std::string strFile, bool fAggressive, std::vector& vResult); - bool Open(boost::filesystem::path pathEnv_); + bool Open(fs::path pathEnv_); void Close(); void Flush(bool fShutdown); @@ -83,10 +87,10 @@ class CDBEnv DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC) { - DbTxn* ptxn = NULL; - int ret = dbenv.txn_begin(NULL, &ptxn, flags); + DbTxn* ptxn = nullptr; + int ret = dbenv.txn_begin(nullptr, &ptxn, flags); if (!ptxn || ret != 0) - return NULL; + return nullptr; return ptxn; } }; @@ -131,7 +135,7 @@ class CDB datValue.set_flags(DB_DBT_MALLOC); int ret = pdb->get(activeTxn, &datKey, &datValue, nFlags); memset(datKey.get_data(), 0, datKey.get_size()); - if (datValue.get_data() == NULL) + if (datValue.get_data() == nullptr) return false; // Unserialize value @@ -154,29 +158,29 @@ class CDB { if (!pdb) return false; - + if (fReadOnly) assert(!"Write called on database in read-only mode"); - + // Key CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.reserve(1000); ssKey << key; Dbt datKey(&ssKey[0], ssKey.size()); - + // Value CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.reserve(10000); ssValue << value; Dbt datValue(&ssValue[0], ssValue.size()); - + // Write int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE)); - + // Clear memory in case it was a private key memset(datKey.get_data(), 0, datKey.get_size()); memset(datValue.get_data(), 0, datValue.get_size()); - + return (ret == 0); } @@ -225,11 +229,11 @@ class CDB Dbc* GetCursor() { if (!pdb) - return NULL; - Dbc* pcursor = NULL; - int ret = pdb->cursor(NULL, &pcursor, 0); + return nullptr; + Dbc* pcursor = nullptr; + int ret = pdb->cursor(nullptr, &pcursor, 0); if (ret != 0) - return NULL; + return nullptr; return pcursor; } @@ -256,7 +260,7 @@ class CDB int ret = pcursor->get(&datKey, &datValue, fFlags); if (ret != 0) return ret; - else if (datKey.get_data() == NULL || datValue.get_data() == NULL) + else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr) return 99999; // Convert to streams @@ -291,7 +295,7 @@ class CDB if (!pdb || !activeTxn) return false; int ret = activeTxn->commit(0); - activeTxn = NULL; + activeTxn = nullptr; return (ret == 0); } @@ -300,7 +304,7 @@ class CDB if (!pdb || !activeTxn) return false; int ret = activeTxn->abort(); - activeTxn = NULL; + activeTxn = nullptr; return (ret == 0); } @@ -315,7 +319,7 @@ class CDB return Write(std::string("version"), nVersion); } - bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL); + bool static Rewrite(const std::string& strFile, const char* pszSkip = nullptr); }; @@ -323,7 +327,7 @@ class CDB class CAddrDB { private: - boost::filesystem::path pathAddr; + fs::path pathAddr; public: CAddrDB(); bool Write(const CAddrMan& addr); diff --git a/src/eckey.cpp b/src/eckey.cpp index ff87ed186b..edc53974f7 100644 --- a/src/eckey.cpp +++ b/src/eckey.cpp @@ -1,8 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "eckey.h" @@ -13,22 +16,22 @@ namespace { int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) { int ok = 0; - BN_CTX *ctx = NULL; - EC_POINT *pub_key = NULL; + BN_CTX *ctx = nullptr; + EC_POINT *pub_key = nullptr; if (!eckey) return 0; const EC_GROUP *group = EC_KEY_get0_group(eckey); - if ((ctx = BN_CTX_new()) == NULL) + if ((ctx = BN_CTX_new()) == nullptr) goto err; pub_key = EC_POINT_new(group); - if (pub_key == NULL) + if (pub_key == nullptr) goto err; - if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) + if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, ctx)) goto err; EC_KEY_set_private_key(eckey,priv_key); @@ -40,7 +43,7 @@ int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) if (pub_key) EC_POINT_free(pub_key); - if (ctx != NULL) + if (ctx != nullptr) BN_CTX_free(ctx); return(ok); @@ -54,54 +57,57 @@ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned ch if (!eckey) return 0; int ret = 0; - BN_CTX *ctx = NULL; - - BIGNUM *x = NULL; - BIGNUM *e = NULL; - BIGNUM *order = NULL; - BIGNUM *sor = NULL; - BIGNUM *eor = NULL; - BIGNUM *field = NULL; - EC_POINT *R = NULL; - EC_POINT *O = NULL; - EC_POINT *Q = NULL; - BIGNUM *rr = NULL; - BIGNUM *zero = NULL; + BN_CTX *ctx = nullptr; + + const BIGNUM *pr = nullptr; + const BIGNUM *ps = nullptr; + BIGNUM *x = nullptr; + BIGNUM *e = nullptr; + BIGNUM *order = nullptr; + BIGNUM *sor = nullptr; + BIGNUM *eor = nullptr; + BIGNUM *field = nullptr; + EC_POINT *R = nullptr; + EC_POINT *O = nullptr; + EC_POINT *Q = nullptr; + BIGNUM *rr = nullptr; + BIGNUM *zero = nullptr; int n = 0; int i = recid / 2; const EC_GROUP *group = EC_KEY_get0_group(eckey); - if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } + if ((ctx = BN_CTX_new()) == nullptr) { ret = -1; goto err; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } x = BN_CTX_get(ctx); if (!BN_copy(x, order)) { ret=-1; goto err; } if (!BN_mul_word(x, i)) { ret=-1; goto err; } - if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } + ECDSA_SIG_get0(ecsig, &pr, &ps); + if (!BN_add(x, x, pr)) { ret=-1; goto err; } field = BN_CTX_get(ctx); - if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } + if (!EC_GROUP_get_curve_GFp(group, field, nullptr, nullptr, ctx)) { ret=-2; goto err; } if (BN_cmp(x, field) >= 0) { ret=0; goto err; } - if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if ((R = EC_POINT_new(group)) == nullptr) { ret = -2; goto err; } if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } if (check) { - if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } - if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } + if ((O = EC_POINT_new(group)) == nullptr) { ret = -2; goto err; } + if (!EC_POINT_mul(group, O, nullptr, R, order, ctx)) { ret=-2; goto err; } if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } } - if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } + if ((Q = EC_POINT_new(group)) == nullptr) { ret = -2; goto err; } n = EC_GROUP_get_degree(group); e = BN_CTX_get(ctx); if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); zero = BN_CTX_get(ctx); - if (!BN_zero(zero)) { ret=-1; goto err; } + BN_zero(zero); if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } rr = BN_CTX_get(ctx); - if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } + if (!BN_mod_inverse(rr, pr, order, ctx)) { ret=-1; goto err; } sor = BN_CTX_get(ctx); - if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } + if (!BN_mod_mul(sor, ps, rr, order, ctx)) { ret=-1; goto err; } eor = BN_CTX_get(ctx); if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } @@ -114,9 +120,9 @@ int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned ch BN_CTX_end(ctx); BN_CTX_free(ctx); } - if (R != NULL) EC_POINT_free(R); - if (O != NULL) EC_POINT_free(O); - if (Q != NULL) EC_POINT_free(Q); + if (R != nullptr) EC_POINT_free(R); + if (O != nullptr) EC_POINT_free(O); + if (Q != nullptr) EC_POINT_free(Q); return ret; } @@ -134,16 +140,16 @@ void CECKey::GetSecretBytes(unsigned char vch[32]) const void CECKey::SetSecretBytes(const unsigned char vch[32]) { - BIGNUM bn; - BN_init(&bn); - assert(BN_bin2bn(vch, 32, &bn)); - assert(EC_KEY_regenerate_key(pkey, &bn)); - BN_clear_free(&bn); + BIGNUM *bn; + bn = BN_new(); + assert(BN_bin2bn(vch, 32, bn)); + assert(EC_KEY_regenerate_key(pkey, bn)); + BN_clear_free(bn); } void CECKey::GetPrivKey(CPrivKey &privkey, bool fCompressed) { EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); - int nSize = i2d_ECPrivateKey(pkey, NULL); + int nSize = i2d_ECPrivateKey(pkey, nullptr); assert(nSize); privkey.resize(nSize); unsigned char* pbegin = &privkey[0]; @@ -167,7 +173,7 @@ bool CECKey::SetPrivKey(const CPrivKey &privkey, bool fSkipCheck) { void CECKey::GetPubKey(CPubKey &pubkey, bool fCompressed) { EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); - int nSize = i2o_ECPublicKey(pkey, NULL); + int nSize = i2o_ECPublicKey(pkey, nullptr); assert(nSize); assert(nSize <= 65); unsigned char c[65]; @@ -185,7 +191,7 @@ bool CECKey::SetPubKey(const CPubKey &pubkey) { bool CECKey::Sign(const uint256 &hash, std::vector& vchSig) { vchSig.clear(); ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); - if (sig == NULL) + if (sig == nullptr) return false; BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); @@ -194,9 +200,15 @@ bool CECKey::Sign(const uint256 &hash, std::vector& vchSig) { BIGNUM *halforder = BN_CTX_get(ctx); EC_GROUP_get_order(group, order, ctx); BN_rshift1(halforder, order); - if (BN_cmp(sig->s, halforder) > 0) { + const BIGNUM *pr = nullptr; + const BIGNUM *ps = nullptr; + ECDSA_SIG_get0(sig, &pr, &ps); + if (BN_cmp(ps, halforder) > 0) { // enforce low S values, by negating the value (modulo the order) if above order/2. - BN_sub(sig->s, order, sig->s); + BIGNUM *pr0 = BN_dup(pr); + BIGNUM *ps0 = BN_new(); + BN_sub(ps0, order, ps); + ECDSA_SIG_set0(sig, pr0, ps0); } BN_CTX_end(ctx); BN_CTX_free(ctx); @@ -219,11 +231,14 @@ bool CECKey::Verify(const uint256 &hash, const std::vector& vchSi bool CECKey::SignCompact(const uint256 &hash, unsigned char *p64, int &rec) { bool fOk = false; ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); - if (sig==NULL) + if (sig==nullptr) return false; memset(p64, 0, 64); - int nBitsR = BN_num_bits(sig->r); - int nBitsS = BN_num_bits(sig->s); + const BIGNUM *pr = nullptr; + const BIGNUM *ps = nullptr; + ECDSA_SIG_get0(sig, &pr, &ps); + int nBitsR = BN_num_bits(pr); + int nBitsS = BN_num_bits(ps); if (nBitsR <= 256 && nBitsS <= 256) { CPubKey pubkey; GetPubKey(pubkey, true); @@ -240,8 +255,8 @@ bool CECKey::SignCompact(const uint256 &hash, unsigned char *p64, int &rec) { } } assert(fOk); - BN_bn2bin(sig->r,&p64[32-(nBitsR+7)/8]); - BN_bn2bin(sig->s,&p64[64-(nBitsS+7)/8]); + BN_bn2bin(pr, &p64[32-(nBitsR+7)/8]); + BN_bn2bin(ps, &p64[64-(nBitsS+7)/8]); } ECDSA_SIG_free(sig); return fOk; @@ -256,8 +271,11 @@ bool CECKey::Recover(const uint256 &hash, const unsigned char *p64, int rec) if (rec<0 || rec>=3) return false; ECDSA_SIG *sig = ECDSA_SIG_new(); - BN_bin2bn(&p64[0], 32, sig->r); - BN_bin2bn(&p64[32], 32, sig->s); + BIGNUM *pr = nullptr; + BIGNUM *ps = nullptr; + BN_bin2bn(&p64[0], 32, pr); + BN_bin2bn(&p64[32], 32, ps); + ECDSA_SIG_set0(sig, pr, ps); bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1; ECDSA_SIG_free(sig); return ret; diff --git a/src/eckey.h b/src/eckey.h index 555aacaa70..b1f0b65d35 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -1,8 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef CEC_KEY_H #define CEC_KEY_H @@ -13,6 +16,8 @@ #include #include "key.h" +#include "util.h" +#include // RAII Wrapper around OpenSSL's EC_KEY class CECKey { @@ -21,14 +26,15 @@ class CECKey { public: CECKey() { + //PKEY will crash if NDEBUG is enabled. Make sure the calls to "asserts" are turned on" pkey = EC_KEY_new_by_curve_name(NID_secp256k1); - assert(pkey != NULL); + assert(pkey != nullptr); } ~CECKey() { EC_KEY_free(pkey); } - + EC_KEY* GetECKey() {return pkey;}; void GetSecretBytes(unsigned char vch[32]) const; @@ -54,7 +60,7 @@ class CECKey { // If this function succeeds, the recovered public key is guaranteed to be valid // (the signature is a valid signature of the given data for that key) bool Recover(const uint256 &hash, const unsigned char *p64, int rec); - + bool TweakPublic(const unsigned char vchTweak[32]); }; diff --git a/src/extkey.cpp b/src/extkey.cpp index ffcec589ee..0f5a3dbb70 100644 --- a/src/extkey.cpp +++ b/src/extkey.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "extkey.h" @@ -44,7 +47,7 @@ const char *ExtKeyGetString(int ind) case 13: return "Failed to unlock"; default: return "Unknown error, check log"; }; - + }; std::vector &SetCompressedInt64(std::vector &v, uint64_t n) @@ -53,7 +56,7 @@ std::vector &SetCompressedInt64(std::vector &v, uint64_t n) v.resize(b); if (b > 0) memcpy(&v[0], (uint8_t*) &n, b); - + return v; }; @@ -66,7 +69,7 @@ int64_t GetCompressedInt64(const std::vector &v, uint64_t &n) else if (b < 9) memcpy((uint8_t*) &n, &v[0], b); - + return (int64_t)n; }; @@ -81,9 +84,9 @@ bool GetCKeyID(const std::vector &v, CKeyID &n) { if (v.size() != 20) return false; - + memcpy((uint8_t*) &n, &v[0], 20); - + return true; }; @@ -92,7 +95,7 @@ std::vector &SetString(std::vector &v, const char *s) size_t len = strlen(s); v.resize(len); memcpy(&v[0], (uint8_t*) &s, len); - + return v; }; @@ -100,7 +103,7 @@ std::vector &SetChar(std::vector &v, const uint8_t c) { v.resize(1); v[0] = c; - + return v; }; @@ -108,7 +111,7 @@ std::vector &PushUInt32(std::vector &v, const uint32_t i) { size_t o = v.size(); v.resize(o+4); - + memcpy(&v[o], (uint8_t*) &i, 4); return v; }; @@ -122,12 +125,12 @@ static uint32_t strtou32max(const char *nptr, int base) char c; uintmax_t cutoff; int neg, any, cutlim; - + s = nptr; do { c = *s++; } while (isspace((unsigned char)c)); - + if (c == '-') { neg = 1; c = *s++; @@ -198,24 +201,24 @@ static inline int validDigit(char c, int base) int ExtractExtKeyPath(const std::string &sPath, std::vector &vPath) { char data[512]; - + vPath.clear(); - + if (sPath.length() > sizeof(data) -2) return 2; if (sPath.length() < 1) return 3; - + memcpy(data, sPath.data(), sPath.length()); data[sPath.length()] = '\0'; - + int nSlashes = 0; for (size_t k = 0; k < sPath.length(); ++k) { if (sPath[k] == '/') { nSlashes++; - + // - catch start or end '/', and '//' if (k == 0 || k == sPath.length()-1 @@ -223,11 +226,11 @@ int ExtractExtKeyPath(const std::string &sPath, std::vector &vPath) return 7; }; }; - + vPath.reserve(nSlashes + 1); - + char *p = strtok(data, "/"); - + while (p) { uint32_t nChild; @@ -236,9 +239,9 @@ int ExtractExtKeyPath(const std::string &sPath, std::vector &vPath) nChild = 0; } else { - + bool fHarden = false; - + // - don't allow octal, only hex and binary int nBase = *p == '0' && (*(p+1) == 'b' || *(p+1) == 'B') ? 2 : *p == '0' && (*(p+1) == 'x' || *(p+1) == 'X') ? 16 : 10; @@ -256,12 +259,12 @@ int ExtractExtKeyPath(const std::string &sPath, std::vector &vPath) if (!validDigit(*p, nBase)) return 4; }; - + errno = 0; nChild = strtou32max(ps, nBase); if (errno != 0) return 5; - + if (fHarden) { if ((nChild >> 31) == 0) @@ -273,20 +276,20 @@ int ExtractExtKeyPath(const std::string &sPath, std::vector &vPath) }; }; }; - + vPath.push_back(nChild); - - p = strtok(NULL, "/"); - + + p = strtok(nullptr, "/"); + if (nChild == 0 && vPath.size() != 1 && p) return 6; }; - + if (vPath.size() < 1) return 3; - + return 0; }; @@ -295,14 +298,14 @@ int PathToString(const std::vector &vPath, std::string &sPath, char cH) sPath = ""; if (vPath.size() % 4 != 0) return 1; - + sPath = "m"; for (size_t o = 0; o < vPath.size(); o+=4) { uint32_t n; memcpy(&n, &vPath[o], 4); sPath += "/"; - + bool fHardened = false; if ((n >> 31) == 1) { @@ -313,17 +316,17 @@ int PathToString(const std::vector &vPath, std::string &sPath, char cH) if (fHardened) sPath += cH; }; - + return 0; }; std::string CEKAStealthKey::ToStealthAddress() const { // - return base58 encoded public stealth address - + std::vector raw; raw = Params().Base58Prefix(CChainParams::STEALTH_ADDRESS); - + raw.push_back(nFlags); raw.insert(raw.end(), pkScan.begin(), pkScan.end()); raw.push_back(1); // number of spend pubkeys @@ -331,17 +334,18 @@ std::string CEKAStealthKey::ToStealthAddress() const raw.push_back(0); // number of signatures raw.push_back(0); // ? AppendChecksum(raw); - + return EncodeBase58(raw); }; -int CEKAStealthKey::SetSxAddr(CStealthAddress &sxAddr) +int CEKAStealthKey::SetSxAddr(CStealthAddress &sxAddr) const { sxAddr.scan_pubkey = pkScan; sxAddr.spend_pubkey = pkSpend; sxAddr.scan_secret.resize(EC_SECRET_SIZE); memcpy(&sxAddr.scan_secret[0], skScan.begin(), EC_SECRET_SIZE); - + sxAddr.label = sLabel; + return 0; }; @@ -365,13 +369,13 @@ std::string CExtKeyAccount::GetIDString58() const int CExtKeyAccount::HaveKey(const CKeyID &id, bool fUpdate, CEKAKey &ak) { // - rv 0 = no, 1 = yes, 2 = lookahead, 3 = lookahead + updated - + LOCK(cs_account); // - if fUpdate, promote key if found in look ahead AccKeyMap::const_iterator mi = mapKeys.find(id); if (mi != mapKeys.end()) return 1; - + mi = mapLookAhead.find(id); if (mi != mapLookAhead.end()) { @@ -385,18 +389,18 @@ int CExtKeyAccount::HaveKey(const CKeyID &id, bool fUpdate, CEKAKey &ak) }; return 2; }; - + AccKeySCMap::const_iterator miSck = mapStealthChildKeys.find(id); if (miSck != mapStealthChildKeys.end()) return 1; - + return 0; }; bool CExtKeyAccount::GetKey(const CKeyID &id, CKey &keyOut) const { LOCK(cs_account); - + AccKeyMap::const_iterator mi; AccKeySCMap::const_iterator miSck; if ((mi = mapKeys.find(id)) != mapKeys.end()) @@ -412,42 +416,42 @@ bool CExtKeyAccount::GetKey(const CKeyID &id, CKey &keyOut) const { return false; }; - + // [rm] necessary? if (fDebug && keyOut.GetPubKey().GetID() != id) { return error("Stored key mismatch."); }; - + return true; } bool CExtKeyAccount::GetKey(const CEKAKey &ak, CKey &keyOut) const { LOCK(cs_account); - + if (ak.nParent >= vExtKeys.size()) return error("%s: Account key invalid parent ext key %d, account %s.", __func__, ak.nParent, GetIDString58().c_str()); - + const CStoredExtKey *chain = vExtKeys[ak.nParent]; - + if (chain->fLocked) return error("%s: Chain locked, account %s.", __func__, GetIDString58().c_str()); - + if (!chain->kp.Derive(keyOut, ak.nKey)) return false; - + return true; }; bool CExtKeyAccount::GetKey(const CEKASCKey &asck, CKey &keyOut) const { LOCK(cs_account); - + AccStealthKeyMap::const_iterator miSk = mapStealthKeys.find(asck.idStealthKey); if (miSk == mapStealthKeys.end()) return error("%s: CEKASCKey Stealth key not in this account!", __func__); - + return (0 == ExpandStealthChildKey(&miSk->second, asck.sShared, keyOut)); }; @@ -469,43 +473,43 @@ bool CExtKeyAccount::GetPubKey(const CKeyID &id, CPubKey &pkOut) const { return false; }; - + if (fDebug) // [rm] necessary { if (pkOut.GetID() != id) return errorN(1, "%s: Extracted public key mismatch.", __func__); }; - + return true; }; bool CExtKeyAccount::GetPubKey(const CEKAKey &ak, CPubKey &pkOut) const { LOCK(cs_account); - + if (ak.nParent >= vExtKeys.size()) return error("%s: Account key invalid parent ext key %d, account %s.", __func__, ak.nParent, GetIDString58().c_str()); - + const CStoredExtKey *chain = GetChain(ak.nParent); - + if (!chain) return error("%s: Chain unknown, account %s.", __func__, GetIDString58().c_str()); - + if (!chain->kp.Derive(pkOut, ak.nKey)) return false; - + return true; }; bool CExtKeyAccount::GetPubKey(const CEKASCKey &asck, CPubKey &pkOut) const { LOCK(cs_account); - + AccStealthKeyMap::const_iterator miSk = mapStealthKeys.find(asck.idStealthKey); if (miSk == mapStealthKeys.end()) return error("%s: CEKASCKey Stealth key not in this account!", __func__); - - + + return (0 == ExpandStealthChildPubKey(&miSk->second, asck.sShared, pkOut)); }; @@ -516,34 +520,34 @@ bool CExtKeyAccount::SaveKey(const CKeyID &id, CEKAKey &keyIn) AccKeyMap::const_iterator mi = mapKeys.find(id); if (mi != mapKeys.end()) return false; // already saved - + if (mapLookAhead.erase(id) != 1) { CBitcoinAddress addr(id); LogPrintf("Warning: SaveKey %s key not found in look ahead %s.\n", GetIDString58().c_str(), addr.ToString().c_str()); }; - + mapKeys[id] = keyIn; - + CStoredExtKey *pc; - if ((pc = GetChain(keyIn.nParent)) != NULL) + if ((pc = GetChain(keyIn.nParent)) != nullptr) { if (keyIn.nKey == pc->nGenerated) // TODO: gaps? pc->nGenerated++; - + if (pc->nFlags & EAF_ACTIVE && pc->nFlags & EAF_RECEIVE_ON) AddLookAhead(keyIn.nParent, 1); }; - + if (fDebug) { CBitcoinAddress addr(id); LogPrintf("Saved key %s, %s.\n", GetIDString58().c_str(), addr.ToString().c_str()); - + // - check match CStoredExtKey *pa; - if ((pa = GetChain(keyIn.nParent)) != NULL) + if ((pa = GetChain(keyIn.nParent)) != nullptr) { if ((keyIn.nKey >> 31) == 1 && pa->fLocked == 1) @@ -551,21 +555,21 @@ bool CExtKeyAccount::SaveKey(const CKeyID &id, CEKAKey &keyIn) LogPrintf("Can't check hardened key when wallet locked.\n"); return true; }; - + CPubKey pk; if (!GetPubKey(keyIn, pk)) return error("GetPubKey failed."); - + if (pk.GetID() != id) return error("Key mismatch!!!"); - + LogPrintf("key match verified.\n"); } else { return error("Unknown chain."); }; }; - + return true; }; @@ -575,26 +579,26 @@ bool CExtKeyAccount::SaveKey(const CKeyID &id, CEKASCKey &keyIn) AccKeySCMap::const_iterator mi = mapStealthChildKeys.find(id); if (mi != mapStealthChildKeys.end()) return false; // already saved - + AccStealthKeyMap::const_iterator miSk = mapStealthKeys.find(keyIn.idStealthKey); if (miSk == mapStealthKeys.end()) return error("SaveKey(): CEKASCKey Stealth key not in this account!"); - + mapStealthChildKeys[id] = keyIn; - + if (fDebug) { CBitcoinAddress addr(id); LogPrintf("SaveKey(): CEKASCKey %s, %s.\n", GetIDString58().c_str(), addr.ToString().c_str()); }; - + return true; }; bool CExtKeyAccount::IsLocked(const CEKAStealthKey &aks) { // TODO: check aks belongs to account?? - + CStoredExtKey *pc = GetChain(aks.akSpend.nParent); if (pc && !pc->fLocked) return false; @@ -607,14 +611,14 @@ int CExtKeyAccount::AddLookAhead(uint32_t nChain, uint32_t nKeys) CStoredExtKey *pc = GetChain(nChain); if (!pc) return errorN(1, "%s: Unknown chain, %d.", __func__, nChain); - + if (fDebug) LogPrintf("%s: chain %s, keys %d.\n", __func__, pc->GetIDString58(), nKeys); - + AccKeyMap::const_iterator mi; uint32_t nChild = pc->nGenerated; uint32_t nChildOut = nChild; - + CKeyID keyId; CPubKey pk; for (uint32_t k = 0; k < nKeys; ++k) @@ -629,7 +633,7 @@ int CExtKeyAccount::AddLookAhead(uint32_t nChain, uint32_t nKeys) continue; }; nChild = nChildOut+1; - + keyId = pk.GetID(); if ((mi = mapKeys.find(keyId)) != mapKeys.end()) { @@ -643,48 +647,48 @@ int CExtKeyAccount::AddLookAhead(uint32_t nChain, uint32_t nKeys) fGotKey = true; break; }; - + if (!fGotKey) { LogPrintf("%s: DeriveKey loop failed, chain %d, child %d.\n", __func__, nChain, nChild); continue; }; - + mapLookAhead[keyId] = CEKAKey(nChain, nChildOut); - + if (fDebug) { CBitcoinAddress addr(keyId); LogPrintf("%s: added %s\n", __func__, addr.ToString().c_str()); }; }; - + return 0; }; int CExtKeyAccount::ExpandStealthChildKey(const CEKAStealthKey *aks, const ec_secret &sShared, CKey &kOut) const { // - derive the secret key of the stealth address and then the secret key out - + LOCK(cs_account); - + if (!aks) return errorN(1, "%s: Sanity checks failed.", __func__); - + CKey kSpend; if (!GetKey(aks->akSpend, kSpend)) return errorN(1, "%s: GetKey() failed.", __func__); - + ec_secret sSpendR; ec_secret sSpend; - + memcpy(&sSpend.e[0], kSpend.begin(), EC_SECRET_SIZE); - + if (StealthSharedToSecretSpend(sShared, sSpend, sSpendR) != 0) return errorN(1, "%s: StealthSharedToSecretSpend() failed.", __func__); - + kOut.Set(&sSpendR.e[0], true); - + if (!kOut.IsValid()) return errorN(1, "%s: Invalid key.", __func__); return 0; @@ -693,22 +697,22 @@ int CExtKeyAccount::ExpandStealthChildKey(const CEKAStealthKey *aks, const ec_se int CExtKeyAccount::ExpandStealthChildPubKey(const CEKAStealthKey *aks, const ec_secret &sShared, CPubKey &pkOut) const { // - works with locked wallet - + LOCK(cs_account); - + if (!aks) return errorN(1, "%s: Sanity checks failed.", __func__); - + ec_point pkExtract; - + if (StealthSharedToPublicKey(aks->pkSpend, sShared, pkExtract) != 0) return errorN(1, "%s: StealthSharedToPublicKey() failed.", __func__); - + pkOut = CPubKey(pkExtract); - + if (!pkOut.IsValid()) return errorN(1, "%s: Invalid public key.", __func__); - + return 0; }; @@ -719,14 +723,14 @@ int CExtKeyAccount::WipeEncryption() { if (!((*it)->nFlags & EAF_IS_CRYPTED)) continue; - + if ((*it)->fLocked) return errorN(1, "Attempting to undo encryption of a locked key."); - + (*it)->nFlags &= ~EAF_IS_CRYPTED; (*it)->vchCryptedSecret.clear(); }; - + return 0; }; @@ -735,17 +739,17 @@ bool IsBIP32(const char *base58) std::vector vchBytes; if (!DecodeBase58(base58, vchBytes)) return false; - + if (vchBytes.size() != BIP32_KEY_LEN) return false; - + if (0 == memcmp(&vchBytes[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) || 0 == memcmp(&vchBytes[0], &Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY)[0], 4)) return true; - + if (!VerifyChecksum(vchBytes)) return false; - + return false; }; @@ -753,43 +757,43 @@ bool IsBIP32(const char *base58) int LoopExtKeysInDB(bool fInactive, bool fInAccount, LoopExtKeyCallback &callback) { AssertLockHeld(pwalletMain->cs_wallet); - + CWalletDB wdb(pwalletMain->strWalletFile); - + Dbc *pcursor; if (!(pcursor = wdb.GetAtCursor())) throw std::runtime_error(strprintf("%s : cannot create DB cursor", __func__).c_str()); - + CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - + CKeyID ckeyId; CStoredExtKey sek; std::string strType; - + uint32_t fFlags = DB_SET_RANGE; ssKey << std::string("ek32"); - + while (wdb.ReadAtCursor(pcursor, ssKey, ssValue, fFlags) == 0) { fFlags = DB_NEXT; - + ssKey >> strType; if (strType != "ek32") break; - + ssKey >> ckeyId; ssValue >> sek; - + if (!fInAccount && sek.nFlags & EAF_IN_ACCOUNT) continue; - + callback.ProcessKey(ckeyId, sek); }; - + pcursor->close(); - + return 0; }; @@ -798,38 +802,38 @@ int LoopExtAccountsInDB(bool fInactive, LoopExtKeyCallback &callback) AssertLockHeld(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile); // - list accounts - + Dbc *pcursor; if (!(pcursor = wdb.GetAtCursor())) throw std::runtime_error(strprintf("%s : cannot create DB cursor", __func__).c_str()); - + CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); CKeyID idAccount; CExtKeyAccount sea; CBitcoinAddress addr; std::string strType, sError; - + uint32_t fFlags = DB_SET_RANGE; ssKey << std::string("eacc"); - + while (wdb.ReadAtCursor(pcursor, ssKey, ssValue, fFlags) == 0) { fFlags = DB_NEXT; - + ssKey >> strType; if (strType != "eacc") break; - + ssKey >> idAccount; ssValue >> sea; - + sea.vExtKeys.resize(sea.vExtKeyIDs.size()); for (size_t i = 0; i < sea.vExtKeyIDs.size(); ++i) { CKeyID &id = sea.vExtKeyIDs[i]; CStoredExtKey *sek = new CStoredExtKey(); - + if (wdb.ReadExtKey(id, *sek)) { sea.vExtKeys[i] = sek; @@ -837,17 +841,17 @@ int LoopExtAccountsInDB(bool fInactive, LoopExtKeyCallback &callback) { addr.Set(idAccount, CChainParams::EXT_ACC_HASH); LogPrintf("WARNING: Could not read key %d of account %s\n", i, addr.ToString().c_str()); - sea.vExtKeys[i] = NULL; + sea.vExtKeys[i] = nullptr; delete sek; }; }; callback.ProcessAccount(idAccount, sea); - + sea.FreeChains(); }; - + pcursor->close(); - + return 0; }; @@ -861,11 +865,11 @@ static int GetWord(int o, const char *pwl, int max, std::string &sWord) if (*pt == '\n') o--; pt++; - + if (pt >= pwl+max) return 1; }; - + while (pt < (pwl+max)) { if (*pt == '\n') @@ -873,7 +877,7 @@ static int GetWord(int o, const char *pwl, int max, std::string &sWord) sWord += *pt; pt++; }; - + return 1; }; @@ -908,13 +912,13 @@ int GetWordOffset(const char *p, const char *pwl, int max, int &o) }; pt++; }; - + return 1; }; static const unsigned char *mnLanguages[] = { - NULL, + nullptr, english_txt, french_txt, japanese_txt, @@ -939,39 +943,39 @@ int MnemonicDetectLanguage(const std::string &sWordList) char tmp[2048]; if (sWordList.size() >= 2048) return errorN(-1, "%s: Word List too long.", __func__); - + // try to detect the language // try max 4 words // allow errors to account for spelling mistakes for (int l = 1; l < WLL_MAX; ++l) { strcpy(tmp, sWordList.c_str()); - + char *pwl = (char*) mnLanguages[l]; int m = mnLanguageLens[l]; - + int maxTries = 4; int nHit = 0; int nMiss = 0; char *p; p = strtok(tmp, " "); - while (p != NULL) + while (p != nullptr) { int ofs; if (0 == GetWordOffset(p, pwl, m, ofs)) nHit++; else nMiss++; - + if (!maxTries--) break; - p = strtok(NULL, " "); + p = strtok(nullptr, " "); }; - + if (nHit > nMiss) return l; }; - + return 0; }; @@ -979,27 +983,27 @@ int MnemonicEncode(int nLanguage, const std::vector &vEntropy, std::str { if (fDebug) LogPrintf("%s: language %d.\n", __func__, nLanguage); - + if (nLanguage < 1 || nLanguage > WLL_MAX) { sError = "Unknown language."; return errorN(1, "%s: %s", __func__, sError.c_str()); }; - + // -- checksum is 1st n bytes of the sha256 hash uint8_t hash[32]; SHA256(&vEntropy[0], vEntropy.size(), (uint8_t*)hash); - + int nCsSize = vEntropy.size() / 4; // 32 / 8 - + if (nCsSize < 1 || nCsSize > 256) { sError = "Entropy bytes out of range."; return errorN(2, "%s: %s", __func__, sError.c_str()); }; - + std::vector vIn = vEntropy; - + int ncb = nCsSize/8; int r = nCsSize % 8; if (r != 0) @@ -1007,26 +1011,26 @@ int MnemonicEncode(int nLanguage, const std::vector &vEntropy, std::str std::vector vTmp(32); memcpy(&vTmp[0], &hash, ncb); memset(&vTmp[ncb], 0, 32-ncb); - + vIn.insert(vIn.end(), vTmp.begin(), vTmp.end()); - + std::vector vWord; - + int nBits = vEntropy.size() * 8 + nCsSize; - + int i = 0; while (i < nBits) { int o = 0; int s = i / 8; int r = i % 8; - + uint8_t b1 = vIn[s]; uint8_t b2 = vIn[s+1]; - + o = (b1 << r) & 0xFF; o = o << (11 - 8); - + if (r > 5) { uint8_t b3 = vIn[s+2]; @@ -1036,36 +1040,36 @@ int MnemonicEncode(int nLanguage, const std::vector &vEntropy, std::str { o |= ((int)b2) >> ((8 - (11 - 8))-r); }; - + o = o & 0x7FF; - + vWord.push_back(o); i += 11; }; - + char *pwl = (char*) mnLanguages[nLanguage]; int m = mnLanguageLens[nLanguage]; - + for (size_t k = 0; k < vWord.size(); ++k) { int o = vWord[k]; - + std::string sWord; - + if (0 != GetWord(o, pwl, m, sWord)) { sError = strprintf("Word extract failed %d.", o); return errorN(3, "%s: %s", __func__, sError.c_str()); }; - + if (sWordList != "") sWordList += " "; sWordList += sWord; }; - + if (nLanguage == WLL_JAPANESE) ReplaceStrInPlace(sWordList, " ", "\u3000"); - + return 0; }; @@ -1073,36 +1077,36 @@ int MnemonicDecode(int nLanguage, const std::string &sWordListIn, std::vector WLL_MAX) { sError = "Unknown language."; return errorN(1, "%s: %s", __func__, sError.c_str()); }; - + char tmp[2048]; if (sWordList.size() >= 2048) { sError = "Word List too long."; return errorN(2, "%s: %s", __func__, sError.c_str()); }; - + strcpy(tmp, sWordList.c_str()); - + char *pwl = (char*) mnLanguages[nLanguage]; int m = mnLanguageLens[nLanguage]; - + std::vector vWordInts; - + char *p; p = strtok(tmp, " "); - while (p != NULL) + while (p != nullptr) { int ofs; if (0 != GetWordOffset(p, pwl, m, ofs)) @@ -1110,37 +1114,37 @@ int MnemonicDecode(int nLanguage, const std::string &sWordListIn, std::vector> (r+3)) & 0x7FF; - + if (s < (int)el-1) { if (r > 5) @@ -1157,43 +1161,43 @@ int MnemonicDecode(int nLanguage, const std::string &sWordListIn, std::vector vCS; - + vCS.resize(nBytesChecksum); memcpy(&vCS[0], &vEntropy[nBytesEntropy], nBytesChecksum); - + vEntropy.resize(nBytesEntropy); - + uint8_t hash[32]; SHA256(&vEntropy[0], vEntropy.size(), (uint8_t*)hash); - + std::vector vCSTest; - + vCSTest.resize(nBytesChecksum); memcpy(&vCSTest[0], &hash, nBytesChecksum); - + int r = nLenChecksum % 8; - + if (r > 0) vCSTest[nBytesChecksum-1] &= (((1< vEntropy; if (0 != (rv = MnemonicDecode(nLanguage, sWordListIn, vEntropy, sError, true))) return rv; - + if (0 != (rv = MnemonicEncode(nLanguage, vEntropy, sWordListOut, sError))) return rv; - + if (0 != (rv = MnemonicDecode(nLanguage, sWordListOut, vEntropy, sError))) return rv; - + return 0; }; diff --git a/src/extkey.h b/src/extkey.h index e7df3223a6..8843cb7f61 100644 --- a/src/extkey.h +++ b/src/extkey.h @@ -1,6 +1,9 @@ -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #ifndef EXT_KEY_H #define EXT_KEY_H @@ -17,8 +20,8 @@ static const uint32_t BIP32_KEY_LEN = 82; // raw, 74 + 4 bytes id + 4 checksum static const uint32_t BIP32_KEY_N_BYTES = 74; // raw without id and checksum static const uint32_t MAX_KEY_PACK_SIZE = 100; -static const uint32_t N_DEFAULT_LOOKAHEAD = 10; -static const uint32_t N_DEFAULT_EKVT_LOOKAHEAD = 20; +static const uint32_t N_DEFAULT_LOOKAHEAD = 100; +static const uint32_t N_DEFAULT_EKVT_LOOKAHEAD = 100; static const uint32_t BIP44_PURPOSE = (((uint32_t)44) | (1 << 31)); @@ -61,7 +64,7 @@ enum WordListLanguages WLL_SPANISH = 4, WLL_CHINESE_S = 5, WLL_CHINESE_T = 6, - + WLL_MAX }; @@ -71,39 +74,35 @@ enum WordListLanguages class CStoredExtKey { public: - CStoredExtKey() + CStoredExtKey() : fLocked(0), nFlags(0), nGenerated(0), nHGenerated(0) { - fLocked = 0; - nFlags = 0; - nGenerated = 0; - nHGenerated = 0; } - + std::string GetIDString58() const; - + CKeyID GetID() const { return kp.GetID(); }; - + bool operator <(const CStoredExtKey& y) const { return kp < y.kp; }; - + bool operator ==(const CStoredExtKey& y) const { // - Compare pubkeys instead of CExtKeyPair for speed return kp.pubkey == y.kp.pubkey; }; - - + + template int DeriveKey(T &keyOut, uint32_t nChildIn, uint32_t &nChildOut, bool fHardened = false) { if (fHardened && !kp.IsValidV()) return errorN(1, "Ext key does not contain a secret."); - + for (uint32_t i = 0; i < MAX_DERIVE_TRIES; ++i) { if ((nChildIn >> 31) == 1) @@ -113,36 +112,36 @@ class CStoredExtKey return errorN(1, "No more hardened keys can be derived from master."); return errorN(1, "No more keys can be derived from master."); }; - + uint32_t nNum = fHardened ? nChildIn | 1 << 31 : nChildIn; - + if (kp.Derive(keyOut, nNum)) { nChildOut = nNum; // nChildOut has bit 31 set for harnened keys return 0; }; - + nChildIn++; }; return 1; }; - + template int DeriveNextKey(T &keyOut, uint32_t &nChildOut, bool fHardened = false, bool fUpdate = true) { uint32_t nChild = fHardened ? nHGenerated : nGenerated; - + int rv; if ((rv = DeriveKey(keyOut, nChild, nChildOut, fHardened)) != 0) return rv; - + nChild = nChildOut & ~(1 << 31); // clear the hardened bit if (fUpdate) SetCounter(nChild+1, fHardened); - + return 0; }; - + int SetCounter(uint32_t nC, bool fHardened) { if (fHardened) @@ -151,12 +150,12 @@ class CStoredExtKey nGenerated = nC; return 0; }; - + uint32_t GetCounter(bool fHardened) { return fHardened ? nHGenerated : nGenerated; }; - + IMPLEMENT_SERIALIZE ( // - Never save secret data when key is encrypted @@ -168,7 +167,7 @@ class CStoredExtKey { READWRITE(kp); }; - + READWRITE(vchCryptedSecret); READWRITE(sLabel); READWRITE(nFlags); @@ -176,18 +175,18 @@ class CStoredExtKey READWRITE(nHGenerated); READWRITE(mapValue); ); - + // - when encrypted, pk can't be derived from vk CExtKeyPair kp; std::vector vchCryptedSecret; - + std::string sLabel; - + uint8_t fLocked; // not part of nFlags so not saved uint32_t nFlags; uint32_t nGenerated; uint32_t nHGenerated; - + mapEKValue_t mapValue; }; @@ -198,18 +197,18 @@ class CEKAKey public: CEKAKey() {}; CEKAKey(uint32_t nParent_, uint32_t nKey_) : nParent(nParent_), nKey(nKey_) {}; - + IMPLEMENT_SERIALIZE ( READWRITE(nParent); READWRITE(nKey); READWRITE(sLabel); ); - + uint32_t nParent; // vExtKeys uint32_t nKey; //uint32_t nChecksum; // TODO: is it worth storing 4 bytes of the id (160 hash here) - + std::string sLabel; // TODO: use later }; @@ -219,20 +218,25 @@ class CEKASCKey public: CEKASCKey() {}; CEKASCKey(CKeyID &idStealthKey_, ec_secret &sShared_) : idStealthKey(idStealthKey_), sShared(sShared_) {}; - + IMPLEMENT_SERIALIZE ( READWRITE(idStealthKey); READWRITE(sShared); READWRITE(sLabel); ); - + // TODO: store an offset instead of the full id of the stealth address CKeyID idStealthKey; // id of parent stealth key (received on) ec_secret sShared; - + //uint32_t nChecksum; // TODO: is it worth storing 4 bytes of the id (160 hash here) std::string sLabel; // TODO: use later + + // overloaded == operator + bool operator==(const CEKASCKey& o) const { + return idStealthKey == o.idStealthKey && (memcmp(&sShared.e[0], &o.sShared.e[0], EC_COMPRESSED_SIZE) == 0); + } }; class CEKAStealthKey @@ -240,32 +244,28 @@ class CEKAStealthKey public: CEKAStealthKey() {}; CEKAStealthKey(uint32_t nScanParent_, uint32_t nScanKey_, CKey scanSecret_, uint32_t nSpendParent_, uint32_t nSpendKey_, CKey spendSecret_) + : nFlags(0), nScanParent(nScanParent_), nScanKey(nScanKey_), skScan(scanSecret_), akSpend(nSpendParent_, nSpendKey_) { // - spend secret is not stored - nFlags = 0; - nScanParent = nScanParent_; - nScanKey = nScanKey_; - skScan = scanSecret_; CPubKey pk = skScan.GetPubKey(); pkScan.resize(pk.size()); memcpy(&pkScan[0], pk.begin(), pk.size()); - - akSpend = CEKAKey(nSpendParent_, nSpendKey_); + pk = spendSecret_.GetPubKey(); pkSpend.resize(pk.size()); memcpy(&pkSpend[0], pk.begin(), pk.size()); }; - + std::string ToStealthAddress() const; - int SetSxAddr(CStealthAddress &sxAddr); - + int SetSxAddr(CStealthAddress &sxAddr) const; + CKeyID GetID() const { // - not likely to be called very often return skScan.GetPubKey().GetID(); }; - - + + IMPLEMENT_SERIALIZE ( READWRITE(nFlags); @@ -277,15 +277,15 @@ class CEKAStealthKey READWRITE(pkScan); READWRITE(pkSpend); ); - - + + uint8_t nFlags; // options of CStealthAddress std::string sLabel; uint32_t nScanParent; // vExtKeys uint32_t nScanKey; CKey skScan; CEKAKey akSpend; - + ec_point pkScan; ec_point pkSpend; }; @@ -295,13 +295,13 @@ class CEKAKeyPack public: CEKAKeyPack() {}; CEKAKeyPack(CKeyID id_, CEKAKey &ak_) : id(id_), ak(ak_) {}; - + IMPLEMENT_SERIALIZE ( READWRITE(id); READWRITE(ak); ); - + CKeyID id; CEKAKey ak; }; @@ -311,13 +311,13 @@ class CEKASCKeyPack public: CEKASCKeyPack() {}; CEKASCKeyPack(CKeyID id_, CEKASCKey &asck_) : id(id_), asck(asck_) {}; - + IMPLEMENT_SERIALIZE ( READWRITE(id); READWRITE(asck); ); - + CKeyID id; CEKASCKey asck; }; @@ -327,13 +327,13 @@ class CEKAStealthKeyPack public: CEKAStealthKeyPack() {}; CEKAStealthKeyPack(CKeyID id_, CEKAStealthKey &aks_) : id(id_), aks(aks_) {}; - + IMPLEMENT_SERIALIZE ( READWRITE(id); READWRITE(aks); ); - + CKeyID id; CEKAStealthKey aks; }; @@ -346,17 +346,10 @@ typedef std::map AccStealthKeyMap; class CExtKeyAccount { // stored by idAccount public: - CExtKeyAccount() + CExtKeyAccount() : nActiveExternal(0), nActiveInternal(0), nActiveStealth(0), nHeightCheckedUncrypted(0), nFlags(0), nPack(0), nPackStealth(0) { - nActiveExternal = 0; - nActiveInternal = 0; - nActiveStealth = 0; - nHeightCheckedUncrypted = 0; - nFlags = 0; - nPack = 0; - nPackStealth = 0; }; - + int FreeChains() { // - Keys are normally freed by the wallet @@ -364,89 +357,89 @@ class CExtKeyAccount for (it = vExtKeys.begin(); it != vExtKeys.end(); ++it) { delete *it; - *it = NULL; + *it = nullptr; }; return 0; }; - + std::string GetIDString58() const; - + CKeyID GetID() const { if (vExtKeyIDs.size() < 1) return CKeyID(0); return vExtKeyIDs[0]; }; - + int HaveKey(const CKeyID &id, bool fUpdate, CEKAKey &ak); bool GetKey(const CKeyID &id, CKey &keyOut) const; bool GetKey(const CEKAKey &ak, CKey &keyOut) const; bool GetKey(const CEKASCKey &asck, CKey &keyOut) const; - + bool GetPubKey(const CKeyID &id, CPubKey &pkOut) const; bool GetPubKey(const CEKAKey &ak, CPubKey &pkOut) const; bool GetPubKey(const CEKASCKey &asck, CPubKey &pkOut) const; - + bool SaveKey(const CKeyID &id, CEKAKey &keyIn); bool SaveKey(const CKeyID &id, CEKASCKey &keyIn); - + bool IsLocked(const CEKAStealthKey &aks); - + CStoredExtKey *GetChain(uint32_t nChain) const { if (nChain >= vExtKeys.size()) - return NULL; + return nullptr; return vExtKeys[nChain]; }; - + CStoredExtKey *ChainExternal() { return GetChain(nActiveExternal); }; - + CStoredExtKey *ChainInternal() { return GetChain(nActiveInternal); }; - + CStoredExtKey *ChainStealth() { return GetChain(nActiveStealth); }; - + CStoredExtKey *ChainAccount() { if (vExtKeys.size() < 1) - return NULL; + return nullptr; return vExtKeys[0]; }; - + int AddLookAhead(uint32_t nChain, uint32_t nKeys); - + int AddLookAheadInternal(uint32_t nKeys) { return AddLookAhead(nActiveExternal, nKeys); }; - + int AddLookAheadExternal(uint32_t nKeys) { return AddLookAhead(nActiveInternal, nKeys); }; - + int ExpandStealthChildKey(const CEKAStealthKey *aks, const ec_secret &sShared, CKey &kOut) const; int ExpandStealthChildPubKey(const CEKAStealthKey *aks, const ec_secret &sShared, CPubKey &pkOut) const; - + int WipeEncryption(); - + IMPLEMENT_SERIALIZE ( READWRITE(sLabel); READWRITE(idMaster); - + READWRITE(nActiveExternal); READWRITE(nActiveInternal); READWRITE(nActiveStealth); - + READWRITE(vExtKeyIDs); READWRITE(nHeightCheckedUncrypted); READWRITE(nFlags); @@ -455,38 +448,38 @@ class CExtKeyAccount READWRITE(nPackStealthKeys); READWRITE(mapValue); ); - - + + // TODO: Could store used keys in archived packs, which don't get loaded into memory AccKeyMap mapKeys; AccKeyMap mapLookAhead; - + AccKeySCMap mapStealthChildKeys; // keys derived from stealth addresses - + AccStealthKeyMap mapStealthKeys; AccStealthKeyMap mapLookAheadStealth; - - + + std::string sLabel; // account name CKeyID idMaster; - + uint32_t nActiveExternal; uint32_t nActiveInternal; uint32_t nActiveStealth; - - + + // Note: Stealth addresses consist of 2 secret keys, one of which (scan secret) must remain unencrypted while wallet locked // store a separate child key used only to derive secret keys // Stealth addresses must only ever be generated as hardened keys - + mutable CCriticalSection cs_account; - + // - 0th key is always the account key std::vector vExtKeys; std::vector vExtKeyIDs; - + int nHeightCheckedUncrypted; // last block checked while uncrypted - + uint32_t nFlags; uint32_t nPack; uint32_t nPackStealth; diff --git a/src/hash.cpp b/src/hash.cpp index c92d3e8405..88d14eb3d8 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -1,3 +1,11 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #include "hash.h" unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& vDataToHash) @@ -22,7 +30,7 @@ unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector& data) { uint32_t checksum = BitcoinChecksum(&data[0], data.size()); - + std::vector tmp(4); memcpy(&tmp[0], &checksum, 4); - + data.insert(data.end(), tmp.begin(), tmp.end()); }; @@ -125,9 +141,9 @@ bool VerifyChecksum(const std::vector& data) { if (data.size() < 4) return false; - + uint32_t checksum; memcpy(&checksum, &(*(data.end() - 4)), 4); - + return BitcoinChecksum((uint8_t*)&data[0], data.size()-4) == checksum; }; diff --git a/src/hash.h b/src/hash.h index eeb7581ff9..d0835bb909 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,7 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_HASH_H #define BITCOIN_HASH_H diff --git a/src/init.cpp b/src/init.cpp index bf21a60c64..951650ddeb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "txdb.h" #include "walletdb.h" @@ -11,30 +14,27 @@ #include "state.h" #include "sync.h" #include "util.h" -#include "ui_interface.h" - -#include "smessage.h" +#include "interface.h" #include "ringsig.h" #include "miner.h" +#include "util/fs.h" -#include -#include -#include -#include -#include +#include +#include #include #ifndef WIN32 #include #endif -namespace fs = boost::filesystem; +using namespace std; +using namespace boost; + +// Using modern std::filesystem via util/fs.h CWallet* pwalletMain; CClientUIInterface uiInterface; -static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; - ////////////////////////////////////////////////////////////////////////////// // // Shutdown @@ -65,17 +65,7 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; // shutdown thing. // -volatile bool fRequestShutdown = false; -//boost::atomic fRequestShutdown(false); - -void StartShutdown() -{ - fRequestShutdown = true; -} -bool ShutdownRequested() -{ - return fRequestShutdown; -} +// see shutdown.h/cpp ////////////////////////////////////////////////////////////////////////////// @@ -86,17 +76,19 @@ bool ShutdownRequested() bool Finalise() { LogPrintf("Finalise()\n"); - + + // Set fRequestShutdown to true, to make sure no matter how we landed here, ShutdownRequested() will reliable return true. + StartShutdown(); + StopRPCThreads(); ShutdownRPCMining(); - SecureMsgShutdown(); - + mempool.AddTransactionsUpdated(1); if (pwalletMain) bitdb.Flush(false); - + StopNode(); - + if (pwalletMain) { { @@ -106,37 +98,33 @@ bool Finalise() bitdb.Flush(true); UnregisterWallet(pwalletMain); delete pwalletMain; - pwalletMain = NULL; + pwalletMain = nullptr; }; - + finaliseRingSigs(); - + if (nNodeMode == NT_FULL) { - std::map::iterator it; - - for (it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) + for (auto& pair : mapBlockIndex) { - delete it->second; + delete pair.second; }; mapBlockIndex.clear(); if (fDebug) LogPrintf("mapBlockIndex cleared.\n"); } else { - std::map::iterator it; - - for (it = mapBlockThinIndex.begin(); it != mapBlockThinIndex.end(); ++it) + for (auto& pair : mapBlockThinIndex) { - delete it->second; + delete pair.second; }; mapBlockThinIndex.clear(); if (fDebug) LogPrintf("mapBlockThinIndex cleared.\n"); }; - + CTxDB().Close(); - + fs::remove(GetPidFile()); return true; } @@ -146,32 +134,74 @@ void Shutdown() static CCriticalSection cs_Shutdown; TRY_LOCK(cs_Shutdown, lockShutdown); if (!lockShutdown) return; - + Finalise(); - + LogPrintf("Shutdown complete.\n\n"); } -void HandleSIGTERM(int) +#ifndef WIN32 +// Note: this also handles SIGINT +void HandleSIGTERM() { - fRequestShutdown = true; + StartShutdown(); } -void HandleSIGHUP(int) +void HandleSIGHUP() { fReopenDebugLog = true; } +static sigset_t blockedSignals; + +int BlockSignals() +{ + sigemptyset(&blockedSignals); + sigaddset(&blockedSignals, SIGINT); + sigaddset(&blockedSignals, SIGTERM); + sigaddset(&blockedSignals, SIGHUP); + return pthread_sigmask(SIG_BLOCK, &blockedSignals, nullptr); +} + +void ThreadSignalHandler(void *nothing) +{ + RenameThread("signals"); + +// fprintf(stderr, "Waiting for signals\n"); + while (1) { + int sig, rc; + rc = sigwait(&blockedSignals, &sig); + if (rc != 0) { + fprintf(stderr, "Failed to wait for signals: %d\n", rc); + return; + } + switch (sig) { + case SIGINT: + case SIGTERM: + fprintf(stderr, "Shutting down on signal %d\n", sig); + HandleSIGTERM(); + return; + case SIGHUP: + fprintf(stderr, "Received SIGHUP, re-opening debug log\n"); + HandleSIGHUP(); + break; + default: + fprintf(stderr, "Unexpected signal %d\n", sig); + break; + } + } +} +#endif bool static InitError(const std::string &str) { - uiInterface.ThreadSafeMessageBox(str, _("ShadowCoin"), CClientUIInterface::BTN_OK | CClientUIInterface::MODAL); + uiInterface.ThreadSafeMessageBox(str, _("Alias"), CClientUIInterface::BTN_OK | CClientUIInterface::MODAL); return false; } bool static InitWarning(const std::string &str) { - uiInterface.ThreadSafeMessageBox(str, _("ShadowCoin"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); + uiInterface.ThreadSafeMessageBox(str, _("Alias"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); return true; } @@ -196,9 +226,9 @@ bool static Bind(const CService &addr, bool fError = true) std::string HelpMessage() { std::string strUsage = _("Options:") + "\n"; - strUsage += " -? " + _("This help message") + "\n"; - strUsage += " -conf= " + _("Specify configuration file (default: shadowcoin.conf)") + "\n"; - strUsage += " -pid= " + _("Specify pid file (default: shadowcoind.pid)") + "\n"; + strUsage += " -?|-h|-help " + _("This help message") + "\n"; + strUsage += " -conf= " + _("Specify configuration file (default: alias.conf)") + "\n"; + strUsage += " -pid= " + _("Specify pid file (default: alias.pid)") + "\n"; strUsage += " -datadir= " + _("Specify data directory") + "\n"; strUsage += " -wallet= " + _("Specify wallet file (within data directory)") + "\n"; strUsage += " -dbcache= " + _("Set database cache size in megabytes (default: 25)") + "\n"; @@ -207,8 +237,9 @@ std::string HelpMessage() strUsage += " -proxy= " + _("Connect through socks proxy") + "\n"; strUsage += " -socks= " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n"; strUsage += " -tor= " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"; + strUsage += " -onionv2 " + _("Use tor hidden services version 2 instead of version 3") + "\n"; strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n"; - strUsage += " -port= " + _("Listen for connections on (default: 51737 or testnet: 51997)") + "\n"; + strUsage += " -port= " + _("Listen for connections on (default: 37347 or testnet: 37111)") + "\n"; strUsage += " -maxconnections= " + _("Maintain at most connections to peers (default: 125)") + "\n"; strUsage += " -addnode= " + _("Add a node to connect to and attempt to keep the connection open") + "\n"; strUsage += " -connect= " + _("Connect only to the specified node(s)") + "\n"; @@ -219,8 +250,10 @@ std::string HelpMessage() strUsage += " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n"; strUsage += " -bind= " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n"; strUsage += " -dnsseed " + _("Find peers using DNS lookup (default: 1)") + "\n"; + strUsage += " -onionseed " + _("Find peers using .onion seeds (default: 1 unless -connect)") + "\n"; strUsage += " -staking " + _("Stake your coins to support network and gain reward (default: 1)") + "\n"; strUsage += " -minstakeinterval= " + _("Minimum time in seconds between successful stakes (default: 30)") + "\n"; + strUsage += " -stakingdonation= " + _("Percentage of staking rewards to donate to the developers (between 0 and 100 inclusive, default 5)") + "\n"; strUsage += " -minersleep= " + _("Milliseconds between stake attempts. Lowering this param will not result in more stakes. (default: 500)") + "\n"; strUsage += " -synctime " + _("Sync time with other nodes. Disable if time on your system is precise e.g. syncing with NTP (default: 1)") + "\n"; strUsage += " -banscore= " + _("Threshold for disconnecting misbehaving peers (default: 100)") + "\n"; @@ -259,15 +292,15 @@ std::string HelpMessage() strUsage += " -printtodebuglog " + _("Send trace/debug info to debug.log file") + "\n"; strUsage += " -rpcuser= " + _("Username for JSON-RPC connections") + "\n"; strUsage += " -rpcpassword= " + _("Password for JSON-RPC connections") + "\n"; - strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 51736 or testnet: 51996)") + "\n"; + strUsage += " -rpcport= " + _("Listen for JSON-RPC connections on (default: 36657 or testnet: 36757)") + "\n"; strUsage += " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address") + "\n"; - + if (!fHaveGUI) { strUsage += " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n"; strUsage += " -rpcwait " + _("Wait for RPC server to start") + "\n"; }; - + strUsage += " -blocknotify= " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n"; strUsage += " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n"; strUsage += " -confchange " + _("Require a confirmations for change (default: 0)") + "\n"; @@ -280,8 +313,9 @@ std::string HelpMessage() strUsage += " -checkblocks= " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n"; strUsage += " -checklevel= " + _("How thorough the block verification is (0-6, default: 1)") + "\n"; strUsage += " -loadblock= " + _("Imports blocks from external blk000?.dat file") + "\n"; - strUsage += " -maxorphanblocksmib= " + strprintf(_("Keep at most MiB of unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; + strUsage += " -maxorphanblocksmib= " + strprintf(_("Keep at most MiB of unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; strUsage += " -reindex " + _("Rebuild block chain index from current blk000?.dat files on startup") + "\n"; + strUsage += " -version " + _("Show version and exit") + "\n"; strUsage += "\n" + _("Thin options:") + "\n"; strUsage += " -thinmode " + _("Operate in less secure, less resource hungry 'thin' mode") + "\n"; @@ -303,11 +337,6 @@ std::string HelpMessage() strUsage += " -rpcsslprivatekeyfile= " + _("Server private key (default: server.pem)") + "\n"; strUsage += " -rpcsslciphers= " + _("Acceptable ciphers (default: TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH)") + "\n"; - strUsage += "\n" + _("Secure messaging options:") + "\n"; - strUsage += " -nosmsg " + _("Disable secure messaging.") + "\n"; - strUsage += " -debugsmsg " + _("Log extra debug messages.") + "\n"; - strUsage += " -smsgscanchain " + _("Scan the block chain for public key addresses on startup.") + "\n"; - return strUsage; } @@ -338,7 +367,7 @@ bool AppInit2(boost::thread_group& threadGroup) #ifdef _MSC_VER // Turn off Microsoft heap dump noise _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); + _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0)); #endif #if _MSC_VER >= 1400 // Disable confusing "helpful" text message on abort, Ctrl-C @@ -355,27 +384,20 @@ bool AppInit2(boost::thread_group& threadGroup) #endif typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD); PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy"); - if (setProcDEPPol != NULL) setProcDEPPol(PROCESS_DEP_ENABLE); + if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE); #endif #ifndef WIN32 umask(077); - // Clean shutdown on SIGTERM - struct sigaction sa; - sa.sa_handler = HandleSIGTERM; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - - // Reopen debug.log on SIGHUP - struct sigaction sa_hup; - sa_hup.sa_handler = HandleSIGHUP; - sigemptyset(&sa_hup.sa_mask); - sa_hup.sa_flags = 0; - sigaction(SIGHUP, &sa_hup, NULL); + // Start a thread to wait for SIGINT, SIGTERM and SIGHUP and handle them appropriately + NewThread(&ThreadSignalHandler, nullptr); #endif + if (GetBoolArg("-version")) { + fprintf(stdout, "%s", FormatFullVersion().c_str()); + return false; + } + if (!CheckDiskSpace()) return false; @@ -384,13 +406,14 @@ bool AppInit2(boost::thread_group& threadGroup) nNodeLifespan = GetArg("-addrlifespan", 7); nMinStakeInterval = GetArg("-minstakeinterval", 0); + nStakingDonation = GetArg("-stakingdonation", 0); nMinerSleep = GetArg("-minersleep", 500); fUseFastIndex = GetBoolArg("-fastindex", true); // Largest block you're willing to create. // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: - nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2); + nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE-1000); nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize)); // How much of the block should be dedicated to high-priority transactions, @@ -414,58 +437,25 @@ bool AppInit2(boost::thread_group& threadGroup) if (fDebug) LogPrintf("nMinerSleep %u\n", nMinerSleep); - nDerivationMethodIndex = 0; fTestNet = GetBoolArg("-testnet", false); if (!SelectParamsFromCommandLine()) return InitError("Invalid combination of -testnet and -regtest."); - + if (!fHaveGUI && GetBoolArg("-cli", false)) printf("Network: %s\n", Params().NetworkIDString().c_str()); - + if (GetBoolArg("-thinmode")) nNodeMode = NT_THIN; - - if (fTestNet) - { - SoftSetBoolArg("-irc", true); - }; - - if (mapArgs.count("-bind")) - { - // when specifying an explicit binding address, you want to listen on it - // even when -connect or -proxy is specified - SoftSetBoolArg("-listen", true); - }; if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0) { - // when only connecting to trusted nodes, do not seed via DNS, or listen by default - SoftSetBoolArg("-dnsseed", false); - SoftSetBoolArg("-listen", false); + // when only connecting to trusted nodes, do not seed via .onion, or listen by default + SoftSetBoolArg("-onionseed", false); } - if (mapArgs.count("-proxy")) - { - // to protect privacy, do not listen by default if a proxy server is specified - SoftSetBoolArg("-listen", false); - }; - - if (!GetBoolArg("-listen", true)) - { - // do not map ports or try to retrieve public IP when not listening (pointless) - SoftSetBoolArg("-upnp", false); - SoftSetBoolArg("-discover", false); - }; - - if (mapArgs.count("-externalip")) - { - // if an explicit public IP is specified, do not try to find others - SoftSetBoolArg("-discover", false); - }; - if (GetBoolArg("-salvagewallet")) { // Rewrite just private keys: rescan to find transactions @@ -474,36 +464,40 @@ bool AppInit2(boost::thread_group& threadGroup) if (fTestNet) { - nStakeMinAge = 1 * 60 * 60; // test net min age is 1 hour + int nTestnetScaleMod = 10; + nMinTxFee /= nTestnetScaleMod; + nMinRelayTxFee /= nTestnetScaleMod; + nStakeReward /= nTestnetScaleMod; + nAnonStakeReward /= nTestnetScaleMod; + nStakeMinAge = 15 * 60; // test net min age is 15 minutes nCoinbaseMaturity = 10; // test maturity is 10 blocks - nStakeMinConfirmations = 10; // test maturity is 10 blocks + nStakeCombineThreshold /= nTestnetScaleMod; + nStakeSplitThreshold /= nTestnetScaleMod; + nMaxAnonOutput /= nTestnetScaleMod; + nMaxAnonStakeOutput /= nTestnetScaleMod; }; // ********************************************************* Step 3: parameter-to-internal-flags - + fDebug = !mapMultiArgs["-debug"].empty(); // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector& categories = mapMultiArgs["-debug"]; if (GetBoolArg("-nodebug", false) || std::find(categories.begin(), categories.end(), std::string("0")) != categories.end()) fDebug = false; - + // -debug implies fDebug*, unless otherwise specified if (fDebug) { SoftSetBoolArg("-debugnet", true); - SoftSetBoolArg("-debugsmsg", true); SoftSetBoolArg("-debugchain", true); SoftSetBoolArg("-debugringsig", true); }; fDebugNet = GetBoolArg("-debugnet"); - fDebugSmsg = GetBoolArg("-debugsmsg"); fDebugChain = GetBoolArg("-debugchain"); fDebugRingSig = GetBoolArg("-debugringsig"); fDebugPoS = GetBoolArg("-debugpos"); - fNoSmsg = GetBoolArg("-nosmsg"); - // Check for -socks - as this is a privacy risk to continue, exit here if (mapArgs.count("-socks")) return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); @@ -550,9 +544,8 @@ bool AppInit2(boost::thread_group& threadGroup) // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // Sanity check if (!InitSanityCheck()) - return InitError(_("Initialization sanity check failed. ShadowCoin is shutting down.")); + return InitError(_("Initialization sanity check failed. Alias is shutting down.")); - std::string strDataDir = GetDataDir().string(); std::string strWalletFileName = GetArg("-wallet", "wallet.dat"); @@ -560,6 +553,9 @@ bool AppInit2(boost::thread_group& threadGroup) if (strWalletFileName != fs::basename(strWalletFileName) + fs::extension(strWalletFileName)) return InitError(strprintf(_("Wallet %s resides outside data directory %s."), strWalletFileName.c_str(), strDataDir.c_str())); + if (mapArgs.count("-bip44key") && fs::exists(GetDataDir() / strWalletFileName)) + return InitError(_("-bip44key is not allowed if wallet.dat already exists")); + // Make sure only a single Bitcoin process is using the data directory. fs::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. @@ -568,15 +564,19 @@ bool AppInit2(boost::thread_group& threadGroup) static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. ShadowCoin is probably already running."), strDataDir.c_str())); - + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Alias is probably already running."), strDataDir.c_str())); + if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); - LogPrintf("ShadowCoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); + LogPrintf("Alias version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); LogPrintf("Operating in %s mode.\n", GetNodeModeName(nNodeMode)); +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); +#else + LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION)); +#endif if (!fLogTimestamps) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); @@ -588,13 +588,11 @@ bool AppInit2(boost::thread_group& threadGroup) if (fDaemon) { - fprintf(stdout, "ShadowCoin server starting\n"); + fprintf(stdout, "Alias server starting\n"); fflush(stdout); }; - - int64_t nStart; - + int64_t nStart; /* ********************************************************* Step 4.5: adjust parameters for nNodeMode @@ -657,9 +655,6 @@ bool AppInit2(boost::thread_group& threadGroup) }; // -- thin and full - if (fNoSmsg) - nLocalServices &= ~(SMSG_RELAY); - if (initialiseRingSigs() != 0) return InitError("initialiseRingSigs() failed."); @@ -669,6 +664,7 @@ bool AppInit2(boost::thread_group& threadGroup) if (!bitdb.Open(GetDataDir())) { + LogPrintf("Failed to open data directory %s\n", strDataDir); std::string msg = strprintf(_("Error initializing database environment %s!" " To recover, BACKUP THAT DIRECTORY, then remove" " everything from it except for wallet.dat."), strDataDir.c_str()); @@ -691,7 +687,7 @@ bool AppInit2(boost::thread_group& threadGroup) " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), strDataDir.c_str()); - uiInterface.ThreadSafeMessageBox(msg, _("ShadowCoin"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); + uiInterface.ThreadSafeMessageBox(msg, _("Alias"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); }; if (r == CDBEnv::RECOVER_FAIL) @@ -704,96 +700,94 @@ bool AppInit2(boost::thread_group& threadGroup) nBloomFilterElements = GetArg("-bloomfilterelements", 1536); - if (mapArgs.count("-onlynet")) - { + // Tor implementation + + do { std::set nets; - BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) - { - enum Network net = ParseNetwork(snet); - if (net == NET_UNROUTABLE) - return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); - nets.insert(net); - }; - for (int n = 0; n < NET_MAX; n++) - { + nets.insert(NET_TOR); + + for (int n = 0; n < NET_MAX; n++) { enum Network net = (enum Network)n; if (!nets.count(net)) SetLimited(net); - }; - }; + } + } while (false); - CService addrProxy; - bool fProxy = false; - if (mapArgs.count("-proxy")) { - addrProxy = CService(mapArgs["-proxy"], 9050); - if (!addrProxy.IsValid()) - return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"])); - - SetProxy(NET_IPV4, addrProxy); - SetProxy(NET_IPV6, addrProxy); - SetNameProxy(addrProxy); - fProxy = true; - } + // Tor implementation + + unsigned short onion_port; + CService addrOnion; + if (fTestNet) + onion_port = 9090; + else + onion_port = 9089; + + if (mapArgs.count("-tor") && mapArgs["-tor"] != "0") { + addrOnion = CService(mapArgs["-tor"], onion_port); - // -tor can override normal proxy, -notor disables tor entirely - if (!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") - && (fProxy || mapArgs.count("-tor"))) - { - CService addrOnion; - if (!mapArgs.count("-tor")) - addrOnion = addrProxy; - else - addrOnion = CService(mapArgs["-tor"], 9050); if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"])); - SetProxy(NET_TOR, addrOnion); - SetReachable(NET_TOR); - } + return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"].c_str())); + } else { + addrOnion = CService("127.0.0.1", onion_port); +} + + SetProxy(NET_TOR, addrOnion); + SetReachable(NET_TOR); // see Step 2: parameter interactions for more information about these - fNoListen = !GetBoolArg("-listen", true); - fDiscover = GetBoolArg("-discover", true); fNameLookup = GetBoolArg("-dns", true); -#ifdef USE_UPNP - fUseUPnP = GetBoolArg("-upnp", USE_UPNP); -#endif bool fBound = false; - if (!fNoListen) - { - std::string strError; - if (mapArgs.count("-bind")) - { - BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) - { - CService addrBind; - if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) - return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str())); - fBound |= Bind(addrBind); - }; - } else - { - struct in_addr inaddr_any; - inaddr_any.s_addr = INADDR_ANY; - if (!IsLimited(NET_IPV6)) - fBound |= Bind(CService(in6addr_any, GetListenPort()), false); - if (!IsLimited(NET_IPV4)) - fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); - }; - if (!fBound) - return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); - }; - if (mapArgs.count("-externalip")) + // Tor implementation + std::string strError; + + do { - BOOST_FOREACH(std::string strAddr, mapMultiArgs["-externalip"]) - { + CService addrBind; + if (!Lookup("127.0.0.1", addrBind, GetListenPort(), false)) + return InitError(strprintf(_("Cannot resolve binding address: '%s'"), "127.0.0.1")); + + fBound |= Bind(addrBind); + } while (false); + + if (!fBound) + return InitError(_("Failed to listen on any port.")); + + if (!(mapArgs.count("-tor") && mapArgs["-tor"] != "0")) { + if (!NewThread(&StartTor, nullptr)) + return InitError(_("Error: could not start tor node")); + } + + if (mapArgs.count("-externalip")) { + for (const std::string& strAddr : mapMultiArgs["-externalip"]) { CService addrLocal(strAddr, GetListenPort(), fNameLookup); if (!addrLocal.IsValid()) return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str())); AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL); - }; - }; + } + } else + { + string automatic_onion; + fs::path hostname_path = GetDataDir() / "tor" / "onion" / "hostname"; + if (fs::exists(hostname_path) && ((GetBoolArg("-onionv2") && fs::file_size(hostname_path) != 23) || (!GetBoolArg("-onionv2") && fs::file_size(hostname_path) != 63))) + remove(hostname_path.string().c_str()); + + int attempts = 0; + while (1) { + if (fs::exists(hostname_path)) + break; + ++attempts; + boost::this_thread::sleep(boost::posix_time::seconds(2)); + if (attempts > 8) + return InitError(_("Timed out waiting for onion hostname.")); + LogPrintf("No onion hostname yet, will retry in 2 seconds... (%d/8)\n", attempts); + } + + ifstream file(hostname_path.string().c_str()); + file >> automatic_onion; + AddLocal(CService(automatic_onion, GetListenPort(), fNameLookup), LOCAL_MANUAL); + } if (mapArgs.count("-reservebalance")) // ppcoin: reserve balance amount { @@ -803,8 +797,8 @@ bool AppInit2(boost::thread_group& threadGroup) return false; }; }; - - BOOST_FOREACH(std::string strDest, mapMultiArgs["-seednode"]) + + for (const std::string& strDest : mapMultiArgs["-seednode"]) AddOneShot(strDest); // ********************************************************* Step 7: load blockchain @@ -828,7 +822,7 @@ bool AppInit2(boost::thread_group& threadGroup) uiInterface.InitMessage(_("Loading block index...")); LogPrintf("Loading block index...\n"); nStart = GetTimeMillis(); - + // -- wipe the txdb if a reindex is queued if (mapArgs.count("-reindex")) { @@ -836,11 +830,18 @@ bool AppInit2(boost::thread_group& threadGroup) CTxDB txdb("cr+"); txdb.RecreateDB(); }; - - switch (LoadBlockIndex()) + + switch (LoadBlockIndex(true, [] (const unsigned mode, const uint32_t& nBlock) -> void { + if (mode == 0) + uiInterface.InitMessage(strprintf(_("Loading block index... (%d)"), nBlock)); + else if (mode == 1) + uiInterface.InitMessage(strprintf(_("Calculating chain trust... (%d)"), nBlock)); + else + uiInterface.InitMessage(strprintf(_("Validating last %d block..."), nBlock)); + })) { case 1: - return InitError(_("Error loading blkindex.dat")); + return InitError(_("Error loading blk0001.dat")); case 2: if (nNodeMode == NT_FULL) { @@ -848,12 +849,14 @@ bool AppInit2(boost::thread_group& threadGroup) mapArgs["-reindex"] = 1; }; break; + case 3: + return InitError(_("Error loading blk0001.dat: Invalid chain detected, please resync or use bootstrap files.")); }; - + // as LoadBlockIndex can take several minutes, it's possible the user // requested to kill bitcoin-qt during the last operation. If so, exit. // As the program has not fully started yet, Shutdown() is possibly overkill. - if (fRequestShutdown) + if (ShutdownRequested()) { LogPrintf("Shutdown requested. Exiting.\n"); return false; @@ -871,12 +874,12 @@ bool AppInit2(boost::thread_group& threadGroup) { std::string strMatch = mapArgs["-printblock"]; int nFound = 0; - for (std::map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + for (auto& pair : mapBlockIndex) { - uint256 hash = (*mi).first; + uint256 hash = pair.first; if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) { - CBlockIndex* pindex = (*mi).second; + CBlockIndex* pindex = pair.second; CBlock block; block.ReadFromDisk(pindex); block.BuildMerkleTree(); @@ -895,9 +898,12 @@ bool AppInit2(boost::thread_group& threadGroup) uiInterface.InitMessage(_("Loading wallet...")); LogPrintf("Loading wallet...\n"); nStart = GetTimeMillis(); - + pwalletMain = new CWallet(strWalletFileName); - DBErrors nLoadWalletRet = pwalletMain->LoadWallet(); + int oltWalletVersion = 0; + DBErrors nLoadWalletRet = pwalletMain->LoadWallet(oltWalletVersion, [] (const uint32_t& nBlock) -> void { + uiInterface.InitMessage(strprintf(_("Loading wallet items... (%d)"), nBlock)); + }); if (nLoadWalletRet != DB_LOAD_OK) { @@ -909,15 +915,15 @@ bool AppInit2(boost::thread_group& threadGroup) { std::string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect.")); - uiInterface.ThreadSafeMessageBox(msg, _("ShadowCoin"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); + uiInterface.ThreadSafeMessageBox(msg, _("Alias"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); } else if (nLoadWalletRet == DB_TOO_NEW) { - strErrors << _("Error loading wallet.dat: Wallet requires newer version of ShadowCoin") << "\n"; + strErrors << _("Error loading wallet.dat: Wallet requires newer version of Alias") << "\n"; } else if (nLoadWalletRet == DB_NEED_REWRITE) { - strErrors << _("Wallet needed to be rewritten: restart ShadowCoin to complete") << "\n"; + strErrors << _("Wallet needed to be rewritten: restart Alias to complete") << "\n"; LogPrintf("%s", strErrors.str().c_str()); return InitError(strErrors.str()); } else @@ -925,22 +931,19 @@ bool AppInit2(boost::thread_group& threadGroup) strErrors << _("Error loading wallet.dat") << "\n"; }; }; - + // --- Prepare extended keys pwalletMain->ExtKeyLoadMaster(); pwalletMain->ExtKeyLoadAccounts(); pwalletMain->ExtKeyLoadAccountPacks(); - - - + LogPrintf("%s", strErrors.str().c_str()); LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - RegisterWallet(pwalletMain); CBlockIndex *pindexRescan = pindexBest; - if (GetBoolArg("-rescan")) + if (GetBoolArg("-rescan") || (oltWalletVersion > 0 && oltWalletVersion < 2020009)) // Wallets prior to V2.2 must be rescanned { pindexRescan = pindexGenesisBlock; } else @@ -953,45 +956,56 @@ bool AppInit2(boost::thread_group& threadGroup) if (pindexBest != pindexRescan && pindexBest && pindexRescan && pindexBest->nHeight > pindexRescan->nHeight) { - uiInterface.InitMessage(_("Rescanning...")); LogPrintf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight); nStart = GetTimeMillis(); - pwalletMain->ScanForWalletTransactions(pindexRescan, true); + + { + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->MarkDirty(); + pwalletMain->ScanForWalletTransactions(pindexRescan, true, [] (const int& nCurrentHeight, const int& nBestHeight, const int& foundOwned) -> bool { + uiInterface.InitMessage(strprintf("Rescanning... %d / %d (%d txns)", nCurrentHeight, nBestHeight, foundOwned)); + return true; + },100); + pwalletMain->ReacceptWalletTransactions(); + } + LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); }; - // ********************************************************* Step 9: import blocks - std::vector vImportFiles; + std::vector vImportFiles; if (mapArgs.count("-loadblock")) { - BOOST_FOREACH(std::string strFile, mapMultiArgs["-loadblock"]) + for (const std::string& strFile : mapMultiArgs["-loadblock"]) vImportFiles.push_back(strFile); }; - threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); - + threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles)); + if (mapArgs.count("-reindex")) { uiInterface.InitMessage(_("Reindexing from blk000?.dat files.")); - + fReindexing = true; int nFile = 1; - while (true) + while (true) { FILE* file = OpenBlockFile(false, nFile, 0, "rb"); if (!file) break; LogPrintf("Reindexing block file blk%04u.dat...\n", (unsigned int)nFile); - LoadExternalBlockFile(nFile, file); + LoadExternalBlockFile(nFile, file, [] (const uint32_t& nBlock) -> void { + if (nBlock % 10 == 0) + uiInterface.InitMessage(strprintf(_("Reindexing block... (%d)"), nBlock)); + }); nFile++; }; - + LogPrintf("Terminating: reindex completed.\n"); Finalise(); exit(0); }; - + // ********************************************************* Step 10: load peers uiInterface.InitMessage(_("Loading addresses...")); @@ -1001,17 +1015,16 @@ bool AppInit2(boost::thread_group& threadGroup) { CAddrDB adb; if (!adb.Read(addrman)) + { LogPrintf("Invalid or missing peers.dat; recreating\n"); + addrman.Clear(); + } } LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); - // ********************************************************* Step 10.1: startup secure messaging - - SecureMsgStart(fNoSmsg, GetBoolArg("-smsgscanchain")); - // ********************************************************* Step 11: start node if (!CheckDiskSpace()) @@ -1028,36 +1041,37 @@ bool AppInit2(boost::thread_group& threadGroup) LogPrintf("mapAddressBook.size() = %u\n", pwalletMain->mapAddressBook.size()); StartNode(threadGroup); - + if (fServer) StartRPCThreads(); // ********************************************************* Step 12: finished - + // Add wallet transactions that aren't already in a block to mapTransactions pwalletMain->ReacceptWalletTransactions(); - + // Run a thread to flush wallet periodically threadGroup.create_thread(boost::bind(&TraceThread, "wflush", &ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile))); - + InitRPCMining(); - + // Mine proof-of-stake blocks in the background - if (!GetBoolArg("-staking", true)) + fIsStakingEnabled = GetBoolArg("-staking", true); + if (!fIsStakingEnabled && !fHaveGUI) LogPrintf("Staking disabled\n"); else threadGroup.create_thread(boost::bind(&TraceThread, "miner", &ThreadStakeMiner, pwalletMain)); - + if (nNodeMode != NT_FULL) pwalletMain->InitBloomFilter(); - uiInterface.InitMessage(_("Done loading")); + uiInterface.InitMessage(_("Core started!")); LogPrintf("Done loading.\n"); if (!strErrors.str().empty()) return InitError(strErrors.str()); - + LogPrintf("Network: %s, port: %d\n", Params().NetworkIDString(), Params().GetDefaultPort()); - - return !fRequestShutdown; + + return !ShutdownRequested(); } diff --git a/src/init.h b/src/init.h index 780a5bb775..e30d41d4af 100644 --- a/src/init.h +++ b/src/init.h @@ -1,16 +1,20 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_INIT_H #define BITCOIN_INIT_H #include "wallet.h" +#include "shutdown.h" extern CWallet* pwalletMain; -void StartShutdown(); -bool ShutdownRequested(); void Shutdown(); +int BlockSignals(); bool AppInit2(boost::thread_group& threadGroup); std::string HelpMessage(); diff --git a/src/ui_interface.h b/src/interface.h similarity index 84% rename from src/ui_interface.h rename to src/interface.h index 2897138e32..08d4d0a54d 100644 --- a/src/ui_interface.h +++ b/src/interface.h @@ -1,13 +1,21 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_UI_INTERFACE_H #define BITCOIN_UI_INTERFACE_H +#ifndef Q_MOC_RUN #include #include +#endif #include @@ -25,6 +33,13 @@ enum ChangeType CT_DELETED }; +struct BlockChangedEvent { + int numBlocks; + int numBlocksOfPeers; + bool isInitialBlockDownload; + int64_t lastBlockTime; +}; + /** Signals for UI communication. */ class CClientUIInterface { @@ -84,9 +99,9 @@ class CClientUIInterface /** Translate a message to the native language of the user. */ boost::signals2::signal Translate; - + /** Block chain changed. */ - boost::signals2::signal NotifyBlocksChanged; + boost::signals2::signalNotifyBlocksChanged; /** Number of network connections changed. */ boost::signals2::signal NotifyNumConnectionsChanged; diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h new file mode 100644 index 0000000000..bbfd26eb0d --- /dev/null +++ b/src/interfaces/chain.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2018-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_INTERFACES_CHAIN_H +#define ALIAS_INTERFACES_CHAIN_H + +#include +#include +#include +#include +#include +#include + +class CBlock; +class CBlockIndex; +class CTransaction; +class COutPoint; +class CTxOut; +class uint256; + +namespace interfaces { + +class Handler; +class Wallet; + +//! Interface giving clients (wallet processes, maybe other tools) read-only access +//! to the chain state, chain notifications, and the ability to relay transactions. +class Chain { +public: + virtual ~Chain() = default; + + //! Get current chain height + virtual int getHeight() const = 0; + + //! Get block hash at height + virtual std::optional getBlockHash(int height) const = 0; + + //! Check if block is in main chain + virtual bool haveBlockOnDisk(int height) const = 0; + + //! Get locator for a given block + virtual std::vector getBlockLocator(const uint256& block_hash) const = 0; + + //! Check if transaction is in mempool + virtual bool isInMempool(const uint256& txid) const = 0; + + //! Check if transaction has confirmations + virtual bool hasConfirmedTx(const uint256& txid) const = 0; + + //! Relay a transaction + virtual void relayTransaction(const uint256& txid) = 0; + + //! Get estimated fee for target + virtual int64_t estimateFee(int target_blocks) const = 0; + + //! Check if chain is syncing + virtual bool isInitialBlockDownload() const = 0; + + //! Broadcast transaction + virtual bool broadcastTransaction(const CTransaction& tx, std::string& err_string, int64_t max_fee, bool relay) = 0; + + //! Get unspent output + virtual std::optional getUnspentOutput(const COutPoint& outpoint) const = 0; + + //! Return whether node has the block and optionally return block metadata + virtual bool findBlock(const uint256& hash, CBlock* block = nullptr, int* height = nullptr, int64_t* time = nullptr) const = 0; + + //! Notifications interface + class Notifications { + public: + virtual ~Notifications() = default; + virtual void transactionAddedToMempool(const CTransaction& tx) {} + virtual void transactionRemovedFromMempool(const CTransaction& tx) {} + virtual void blockConnected(const CBlock& block, int height) {} + virtual void blockDisconnected(const CBlock& block, int height) {} + virtual void updatedBlockTip() {} + virtual void chainStateFlushed(const uint256& best_block_hash) {} + }; + + //! Register handler for notifications + virtual std::unique_ptr handleNotifications(std::shared_ptr notifications) = 0; + + //! Wait for notifications + virtual void waitForNotificationsIfTipChanged(const uint256& old_tip) = 0; +}; + +//! Return implementation of Chain interface +std::unique_ptr MakeChain(); + +} // namespace interfaces + +#endif // ALIAS_INTERFACES_CHAIN_H diff --git a/src/interfaces/handler.h b/src/interfaces/handler.h new file mode 100644 index 0000000000..d45e200abf --- /dev/null +++ b/src/interfaces/handler.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2018-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_INTERFACES_HANDLER_H +#define ALIAS_INTERFACES_HANDLER_H + +#include +#include + +namespace interfaces { + +//! Generic interface for managing an event handler or callback function +//! registered with another interface. Has a single disconnect method to cancel +//! the registration and prevent any future notifications. +class Handler { +public: + virtual ~Handler() = default; + + //! Disconnect the handler + virtual void disconnect() = 0; +}; + +//! Return handler wrapping a cleanup function +std::unique_ptr MakeCleanupHandler(std::function cleanup); + +//! Simple handler implementation that calls cleanup function on disconnect +class CleanupHandler : public Handler { +public: + explicit CleanupHandler(std::function cleanup) : m_cleanup(std::move(cleanup)) {} + + ~CleanupHandler() override { + if (m_cleanup) { + m_cleanup(); + } + } + + void disconnect() override { + if (m_cleanup) { + m_cleanup(); + m_cleanup = nullptr; + } + } + +private: + std::function m_cleanup; +}; + +inline std::unique_ptr MakeCleanupHandler(std::function cleanup) { + return std::make_unique(std::move(cleanup)); +} + +} // namespace interfaces + +#endif // ALIAS_INTERFACES_HANDLER_H diff --git a/src/interfaces/node.h b/src/interfaces/node.h new file mode 100644 index 0000000000..b61d4ae812 --- /dev/null +++ b/src/interfaces/node.h @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2018-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_INTERFACES_NODE_H +#define ALIAS_INTERFACES_NODE_H + +#include +#include +#include +#include +#include + +class CNodeStats; +class proxyType; +class uint256; + +namespace interfaces { + +class Chain; +class Handler; +class Wallet; +class WalletLoader; + +//! Top-level interface for a node (aliascoind process) +class Node { +public: + virtual ~Node() = default; + + //! Init logging + virtual void initLogging() = 0; + + //! Init parameter interaction + virtual void initParameterInteraction() = 0; + + //! Get warnings + virtual std::string getWarnings() = 0; + + //! Get log flags + virtual uint32_t getLogCategories() = 0; + + //! Initialize app dependencies + virtual bool baseInitialize() = 0; + + //! Start node + virtual bool appInitMain() = 0; + + //! Stop node + virtual void appShutdown() = 0; + + //! Start shutdown + virtual void startShutdown() = 0; + + //! Return whether shutdown was requested + virtual bool shutdownRequested() = 0; + + //! Get network active state + virtual bool getNetworkActive() const = 0; + + //! Set network active state + virtual void setNetworkActive(bool active) = 0; + + //! Get number of connections + virtual size_t getNodeCount() const = 0; + + //! Get peer info + virtual bool getNodesStats(std::vector& stats) const = 0; + + //! Disconnect by node id + virtual bool disconnectByAddress(const std::string& address) = 0; + + //! Disconnect by node id + virtual bool disconnectById(int64_t id) = 0; + + //! Get number of blocks + virtual int getNumBlocks() const = 0; + + //! Get best block hash + virtual uint256 getBestBlockHash() const = 0; + + //! Get last block time + virtual int64_t getLastBlockTime() const = 0; + + //! Get verification progress + virtual double getVerificationProgress() const = 0; + + //! Is initial block download + virtual bool isInitialBlockDownload() const = 0; + + //! Get reindex status + virtual bool getReindex() const = 0; + + //! Get importing status + virtual bool getImporting() const = 0; + + //! Get network name + virtual std::string getNetworkName() const = 0; + + //! Get proxy + virtual bool getProxy(std::string& proxy_info) const = 0; + + //! Get mempool size + virtual size_t getMempoolSize() const = 0; + + //! Get mempool dynamic usage + virtual size_t getMempoolDynamicUsage() const = 0; + + //! Notifications interface for GUI + class Notifications { + public: + virtual ~Notifications() = default; + virtual void initMessage(const std::string& message) {} + virtual void showProgress(const std::string& title, int progress, bool resume_possible) {} + virtual void numConnectionsChanged(int num_connections) {} + virtual void numBlocksChanged(int num_blocks, int64_t block_time, double verification_progress) {} + virtual void alertNotify(const std::string& message) {} + virtual void bannedListChanged() {} + }; + + //! Register handler for notifications + virtual std::unique_ptr handleNotifications(std::shared_ptr notifications) = 0; + + //! Get wallet loader + virtual WalletLoader& walletLoader() = 0; + + //! Get chain interface + virtual Chain& chain() = 0; +}; + +//! Return implementation of Node interface +std::unique_ptr MakeNode(); + +} // namespace interfaces + +#endif // ALIAS_INTERFACES_NODE_H diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h new file mode 100644 index 0000000000..8df1fe727f --- /dev/null +++ b/src/interfaces/wallet.h @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2018-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_INTERFACES_WALLET_H +#define ALIAS_INTERFACES_WALLET_H + +#include +#include +#include +#include +#include +#include + +class CKey; +class CKeyID; +class CPubKey; +class CScript; +class CTransaction; +class COutPoint; +class CTxDestination; +class uint256; + +namespace interfaces { + +class Handler; + +//! Collection of wallet info for display +struct WalletInfo { + std::string name; + bool have_watch_only{false}; + bool is_encrypted{false}; + bool is_locked{true}; +}; + +//! Collection of wallet balance info +struct WalletBalance { + int64_t balance{0}; + int64_t unconfirmed_balance{0}; + int64_t immature_balance{0}; + int64_t stake{0}; + int64_t anon_balance{0}; + int64_t anon_unconfirmed_balance{0}; + bool have_watch_only{false}; + int64_t watch_only_balance{0}; + int64_t watch_only_unconfirmed_balance{0}; + int64_t watch_only_immature_balance{0}; +}; + +//! Wallet transaction output +struct WalletTxOut { + CScript script_pub_key; + int64_t value{0}; + int depth{0}; + bool is_spent{false}; + bool is_anon{false}; +}; + +//! Wallet transaction +struct WalletTx { + uint256 hash; + int64_t time{0}; + int64_t value{0}; + int64_t fee{0}; + int depth{0}; + bool is_coinbase{false}; + bool is_coinstake{false}; + bool is_anon{false}; + bool is_in_mempool{false}; + std::map additional_info; +}; + +//! Interface for accessing a wallet +class Wallet { +public: + virtual ~Wallet() = default; + + //! Encrypt wallet + virtual bool encryptWallet(const std::string& passphrase) = 0; + + //! Check if wallet is encrypted + virtual bool isEncrypted() const = 0; + + //! Lock wallet + virtual bool lock() = 0; + + //! Unlock wallet + virtual bool unlock(const std::string& passphrase, bool staking_only = false) = 0; + + //! Check if wallet is locked + virtual bool isLocked() const = 0; + + //! Change wallet passphrase + virtual bool changeWalletPassphrase(const std::string& old_passphrase, const std::string& new_passphrase) = 0; + + //! Get wallet name + virtual std::string getWalletName() const = 0; + + //! Get wallet balance info + virtual WalletBalance getBalance() const = 0; + + //! Get available balance + virtual int64_t getAvailableBalance() const = 0; + + //! Check if we have key + virtual bool haveKey(const CKeyID& key_id) const = 0; + + //! Get key + virtual bool getKey(const CKeyID& key_id, CKey& key) const = 0; + + //! Get pubkey + virtual bool getPubKey(const CKeyID& key_id, CPubKey& pub_key) const = 0; + + //! Get address for destination + virtual std::string getAddress(const CTxDestination& dest) const = 0; + + //! Get address book name + virtual std::string getAddressLabel(const CTxDestination& dest) const = 0; + + //! Get transaction + virtual bool getTransaction(const uint256& txid, WalletTx& wtx) const = 0; + + //! Get wallet transactions + virtual std::vector getWalletTxs() const = 0; + + //! Check if transaction is from this wallet + virtual bool isFromMe(const CTransaction& tx) const = 0; + + //! Check if output is mine + virtual bool isMine(const CScript& script) const = 0; + + //! Create transaction + virtual bool createTransaction( + const std::vector>& recipients, + int64_t& fee, + std::string& fail_reason, + CTransaction& tx) = 0; + + //! Commit transaction + virtual bool commitTransaction(const CTransaction& tx, std::string& reject_reason) = 0; + + //! Notifications interface + class Notifications { + public: + virtual ~Notifications() = default; + virtual void walletLockStatusChanged(bool locked) {} + virtual void walletEncryptionStatusChanged() {} + virtual void balanceChanged() {} + virtual void transactionChanged() {} + virtual void addressBookChanged() {} + virtual void showProgress(const std::string& title, int progress) {} + }; + + //! Register handler for notifications + virtual std::unique_ptr handleNotifications(std::shared_ptr notifications) = 0; +}; + +//! Wallet loader interface +class WalletLoader { +public: + virtual ~WalletLoader() = default; + + //! Get wallet names + virtual std::vector listWallets() const = 0; + + //! Load wallet + virtual std::unique_ptr loadWallet(const std::string& name, std::string& error, std::string& warning) = 0; + + //! Create wallet + virtual std::unique_ptr createWallet(const std::string& name, std::string& error, std::string& warning) = 0; + + //! Get wallet + virtual std::unique_ptr getWallet(const std::string& name) const = 0; +}; + +//! Return implementation of Wallet interface +std::unique_ptr MakeWallet(const std::string& name); + +//! Return implementation of WalletLoader interface +std::unique_ptr MakeWalletLoader(); + +} // namespace interfaces + +#endif // ALIAS_INTERFACES_WALLET_H diff --git a/src/json/CMakeLists.txt b/src/json/CMakeLists.txt new file mode 100644 index 0000000000..beca67b4b0 --- /dev/null +++ b/src/json/CMakeLists.txt @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(aliaswallet_lib + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_error_position.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_reader.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_reader_template.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_stream_reader.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_utils.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_value.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_writer.h + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_writer_template.h + + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_reader.cpp + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_value.cpp + ${CMAKE_CURRENT_LIST_DIR}/json_spirit_writer.cpp + ) diff --git a/src/json/json_spirit.h b/src/json/json_spirit.h index ac1879d5b3..3c80b90a33 100644 --- a/src/json/json_spirit.h +++ b/src/json/json_spirit.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT -#define JSON_SPIRIT - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT +#define JSON_SPIRIT + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif diff --git a/src/json/json_spirit_error_position.h b/src/json/json_spirit_error_position.h index 17208507df..66ec0c2ad1 100644 --- a/src/json/json_spirit_error_position.h +++ b/src/json/json_spirit_error_position.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_ERROR_POSITION -#define JSON_SPIRIT_ERROR_POSITION - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_ERROR_POSITION +#define JSON_SPIRIT_ERROR_POSITION + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -15,7 +16,7 @@ namespace json_spirit { // An Error_position exception is thrown by the "read_or_throw" functions below on finding an error. - // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" + // Note the "read_or_throw" functions are around 3 times slower than the standard functions "read" // functions that return a bool. // struct Error_position @@ -47,7 +48,7 @@ namespace json_spirit return ( reason_ == lhs.reason_ ) && ( line_ == lhs.line_ ) && - ( column_ == lhs.column_ ); + ( column_ == lhs.column_ ); } } diff --git a/src/json/json_spirit_reader.cpp b/src/json/json_spirit_reader.cpp index aa4f637226..5a3dcd3790 100644 --- a/src/json/json_spirit_reader.cpp +++ b/src/json/json_spirit_reader.cpp @@ -1,5 +1,6 @@ -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 diff --git a/src/json/json_spirit_reader.h b/src/json/json_spirit_reader.h index 96494a9789..67744f3650 100644 --- a/src/json/json_spirit_reader.h +++ b/src/json/json_spirit_reader.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_READER -#define JSON_SPIRIT_READER - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_READER +#define JSON_SPIRIT_READER + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -22,7 +23,7 @@ namespace json_spirit bool read( std::istream& is, Value& value ); bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); - void read_or_throw( const std::string& s, Value& value ); + void read_or_throw( const std::string& s, Value& value ); void read_or_throw( std::istream& is, Value& value ); void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value ); @@ -30,7 +31,7 @@ namespace json_spirit bool read( const std::wstring& s, wValue& value ); bool read( std::wistream& is, wValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); + bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value ); void read_or_throw( const std::wstring& s, wValue& value ); void read_or_throw( std::wistream& is, wValue& value ); @@ -42,7 +43,7 @@ namespace json_spirit bool read( std::istream& is, mValue& value ); bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); - void read_or_throw( const std::string& s, mValue& value ); + void read_or_throw( const std::string& s, mValue& value ); void read_or_throw( std::istream& is, mValue& value ); void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value ); @@ -50,7 +51,7 @@ namespace json_spirit bool read( const std::wstring& s, wmValue& value ); bool read( std::wistream& is, wmValue& value ); - bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); + bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value ); void read_or_throw( const std::wstring& s, wmValue& value ); void read_or_throw( std::wistream& is, wmValue& value ); diff --git a/src/json/json_spirit_reader_template.h b/src/json/json_spirit_reader_template.h index 46f5892f62..add7ad2c45 100644 --- a/src/json/json_spirit_reader_template.h +++ b/src/json/json_spirit_reader_template.h @@ -1,17 +1,23 @@ +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT + +// json spirit version 4.03 + #ifndef JSON_SPIRIT_READER_TEMPLATE #define JSON_SPIRIT_READER_TEMPLATE -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt - -// json spirit version 4.03 +#ifdef __APPLE__ +#define BOOST_HAS_THREADS +#endif #include "json_spirit_value.h" #include "json_spirit_error_position.h" //#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread -#include +#ifndef Q_MOC_RUN +#include #include #include @@ -30,6 +36,7 @@ #include #define spirit_namespace boost::spirit #endif +#endif namespace json_spirit { @@ -65,7 +72,7 @@ namespace json_spirit const Char_type c2( *( ++begin ) ); return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 ); - } + } template< class Char_type, class Iter_type > Char_type unicode_str_to_char( Iter_type& begin ) @@ -75,19 +82,19 @@ namespace json_spirit const Char_type c3( *( ++begin ) ); const Char_type c4( *( ++begin ) ); - return ( hex_to_num( c1 ) << 12 ) + - ( hex_to_num( c2 ) << 8 ) + - ( hex_to_num( c3 ) << 4 ) + + return ( hex_to_num( c1 ) << 12 ) + + ( hex_to_num( c2 ) << 8 ) + + ( hex_to_num( c3 ) << 4 ) + hex_to_num( c4 ); } template< class String_type > - void append_esc_char_and_incr_iter( String_type& s, - typename String_type::const_iterator& begin, + void append_esc_char_and_incr_iter( String_type& s, + typename String_type::const_iterator& begin, typename String_type::const_iterator end ) { typedef typename String_type::value_type Char_type; - + const Char_type c2( *begin ); switch( c2 ) @@ -100,19 +107,19 @@ namespace json_spirit case '\\': s += '\\'; break; case '/': s += '/'; break; case '"': s += '"'; break; - case 'x': + case 'x': { if( end - begin >= 3 ) // expecting "xHH..." { - s += hex_str_to_char< Char_type >( begin ); + s += hex_str_to_char< Char_type >( begin ); } break; } - case 'u': + case 'u': { if( end - begin >= 5 ) // expecting "uHHHH..." { - s += unicode_str_to_char< Char_type >( begin ); + s += unicode_str_to_char< Char_type >( begin ); } break; } @@ -120,7 +127,7 @@ namespace json_spirit } template< class String_type > - String_type substitute_esc_chars( typename String_type::const_iterator begin, + String_type substitute_esc_chars( typename String_type::const_iterator begin, typename String_type::const_iterator end ) { typedef typename String_type::const_iterator Iter_type; @@ -128,7 +135,7 @@ namespace json_spirit if( end - begin < 2 ) return String_type( begin, end ); String_type result; - + result.reserve( end - begin ); const Iter_type end_minus_1( end - 1 ); @@ -143,7 +150,7 @@ namespace json_spirit result.append( substr_start, i ); ++i; // skip the '\' - + append_esc_char_and_incr_iter( result, i, end ); substr_start = i + 1; @@ -156,7 +163,7 @@ namespace json_spirit } template< class String_type > - String_type get_str_( typename String_type::const_iterator begin, + String_type get_str_( typename String_type::const_iterator begin, typename String_type::const_iterator end ) { assert( end - begin >= 2 ); @@ -178,7 +185,7 @@ namespace json_spirit { return get_str_< std::wstring >( begin, end ); } - + template< class String_type, class Iter_type > String_type get_str( Iter_type begin, Iter_type end ) { @@ -193,7 +200,7 @@ namespace json_spirit // NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator // template< class Value_type, class Iter_type > - class Semantic_actions + class Semantic_actions { public: @@ -226,7 +233,7 @@ namespace json_spirit void begin_array( Char_type c ) { assert( c == '[' ); - + begin_compound< Array_type >(); } @@ -287,7 +294,7 @@ namespace json_spirit private: - Semantic_actions& operator=( const Semantic_actions& ); + Semantic_actions& operator=( const Semantic_actions& ); // to prevent "assignment operator could not be generated" warning Value_type* add_first( const Value_type& value ) @@ -321,9 +328,9 @@ namespace json_spirit if( current_p_ != &value_ ) { current_p_ = stack_.back(); - + stack_.pop_back(); - } + } } Value_type* add_to_current( const Value_type& value ) @@ -336,9 +343,9 @@ namespace json_spirit { current_p_->get_array().push_back( value ); - return ¤t_p_->get_array().back(); + return ¤t_p_->get_array().back(); } - + assert( current_p_->type() == obj_type ); return &Config_type::add( current_p_->get_obj(), name_, value ); @@ -364,7 +371,7 @@ namespace json_spirit throw reason; } - // the spirit grammer + // the spirit grammer // template< class Value_type, class Iter_type > class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > > @@ -419,7 +426,7 @@ namespace json_spirit typedef typename Value_type::String_type::value_type Char_type; - // first we convert the semantic action class methods to functors with the + // first we convert the semantic action class methods to functors with the // parameter signature expected by spirit typedef boost::function< void( Char_type ) > Char_action; @@ -428,18 +435,18 @@ namespace json_spirit typedef boost::function< void( int64_t ) > Int_action; typedef boost::function< void( uint64_t ) > Uint64_action; - Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) ); - Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) ); - Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) ); - Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) ); - Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) ); - Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) ); - Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) ); - Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) ); - Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) ); - Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) ); - Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) ); - Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) ); + Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, boost::placeholders::_1 ) ); + Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, boost::placeholders::_1 ) ); + Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, boost::placeholders::_1 ) ); + Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, boost::placeholders::_1 ) ); + Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, boost::placeholders::_1, boost::placeholders::_2 ) ); + Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, boost::placeholders::_1, boost::placeholders::_2 ) ); + Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, boost::placeholders::_1, boost::placeholders::_2 ) ); + Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, boost::placeholders::_1, boost::placeholders::_2 ) ); + Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, boost::placeholders::_1, boost::placeholders::_2 ) ); + Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, boost::placeholders::_1 ) ); + Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, boost::placeholders::_1 ) ); + Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, boost::placeholders::_1 ) ); // actual grammer @@ -448,16 +455,16 @@ namespace json_spirit ; value_ - = string_[ new_str ] - | number_ - | object_ - | array_ - | str_p( "true" ) [ new_true ] - | str_p( "false" )[ new_false ] + = string_[ new_str ] + | number_ + | object_ + | array_ + | str_p( "true" ) [ new_true ] + | str_p( "false" )[ new_false ] | str_p( "null" ) [ new_null ] ; - object_ + object_ = ch_p('{')[ begin_obj ] >> !members_ >> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] ) @@ -483,20 +490,20 @@ namespace json_spirit = value_ >> *( ',' >> value_ ) ; - string_ + string_ = lexeme_d // this causes white space inside a string to be retained [ confix_p - ( - '"', + ( + '"', *lex_escape_ch_p, '"' - ) + ) ] ; number_ - = strict_real_p[ new_real ] + = strict_real_p[ new_real ] | int64_p [ new_int ] | uint64_p [ new_uint64 ] ; @@ -518,10 +525,10 @@ namespace json_spirit Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value ) { Semantic_actions< Value_type, Iter_type > semantic_actions( value ); - - const spirit_namespace::parse_info< Iter_type > info = - spirit_namespace::parse( begin, end, - Json_grammer< Value_type, Iter_type >( semantic_actions ), + + const spirit_namespace::parse_info< Iter_type > info = + spirit_namespace::parse( begin, end, + Json_grammer< Value_type, Iter_type >( semantic_actions ), spirit_namespace::space_p ); if( !info.hit ) @@ -540,7 +547,7 @@ namespace json_spirit const Posn_iter_t posn_begin( begin, end ); const Posn_iter_t posn_end( end, end ); - + read_range_or_throw( posn_begin, posn_end, value ); } diff --git a/src/json/json_spirit_stream_reader.h b/src/json/json_spirit_stream_reader.h index 7e59c9adc2..5e380e677f 100644 --- a/src/json/json_spirit_stream_reader.h +++ b/src/json/json_spirit_stream_reader.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_READ_STREAM -#define JSON_SPIRIT_READ_STREAM - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_READ_STREAM +#define JSON_SPIRIT_READ_STREAM + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -15,7 +16,7 @@ namespace json_spirit { // these classes allows you to read multiple top level contiguous values from a stream, - // the normal stream read functions have a bug that prevent multiple top level values + // the normal stream read functions have a bug that prevent multiple top level values // from being read unless they are separated by spaces template< class Istream_type, class Value_type > diff --git a/src/json/json_spirit_utils.h b/src/json/json_spirit_utils.h index 553e3b96a4..5cab512b15 100644 --- a/src/json/json_spirit_utils.h +++ b/src/json/json_spirit_utils.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_UTILS -#define JSON_SPIRIT_UTILS - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_UTILS +#define JSON_SPIRIT_UTILS + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -14,7 +15,7 @@ #include namespace json_spirit -{ +{ template< class Obj_t, class Map_t > void obj_to_map( const Obj_t& obj, Map_t& mp_obj ) { diff --git a/src/json/json_spirit_value.cpp b/src/json/json_spirit_value.cpp index 44d2f06a01..5ee716d20e 100644 --- a/src/json/json_spirit_value.cpp +++ b/src/json/json_spirit_value.cpp @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT + /* Copyright (c) 2007 John W Wilkinson This source code can be used for any purpose as long as diff --git a/src/json/json_spirit_value.h b/src/json/json_spirit_value.h index 13cc89210c..f71fa5839b 100644 --- a/src/json/json_spirit_value.h +++ b/src/json/json_spirit_value.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_VALUE -#define JSON_SPIRIT_VALUE - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_VALUE +#define JSON_SPIRIT_VALUE + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -13,13 +14,17 @@ #include #include #include +#undef NDEBUG #include #include #include #include -#include -#include -#include + +#ifndef Q_MOC_RUN +#include +#include +#include +#endif namespace json_spirit { @@ -39,7 +44,7 @@ namespace json_spirit typedef typename String_type::const_pointer Const_str_ptr; // eg const char* Value_impl(); // creates null value - Value_impl( Const_str_ptr value ); + Value_impl( Const_str_ptr value ); Value_impl( const String_type& value ); Value_impl( const Object& value ); Value_impl( const Array& value ); @@ -81,8 +86,8 @@ namespace json_spirit void check_type( const Value_type vtype ) const; - typedef boost::variant< String_type, - boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, + typedef boost::variant< String_type, + boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >, bool, int64_t, double > Variant; Value_type type_; @@ -121,12 +126,12 @@ namespace json_spirit return obj.back().value_; } - + static String_type get_name( const Pair_type& pair ) { return pair.name_; } - + static Value_type get_value( const Pair_type& pair ) { return pair.value_; @@ -169,12 +174,12 @@ namespace json_spirit { return obj[ name ] = value; } - + static String_type get_name( const Pair_type& pair ) { return pair.first; } - + static Value_type get_value( const Pair_type& pair ) { return pair.second; @@ -314,7 +319,7 @@ namespace json_spirit if( type() != lhs.type() ) return false; - return v_ == lhs.v_; + return v_ == lhs.v_; } template< class Config > @@ -338,7 +343,7 @@ namespace json_spirit template< class Config > void Value_impl< Config >::check_type( const Value_type vtype ) const { - if( type() != vtype ) + if( type() != vtype ) { std::ostringstream os; @@ -364,7 +369,7 @@ namespace json_spirit return *boost::get< Object >( &v_ ); } - + template< class Config > const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const { @@ -372,7 +377,7 @@ namespace json_spirit return *boost::get< Array >( &v_ ); } - + template< class Config > bool Value_impl< Config >::get_bool() const { @@ -380,7 +385,7 @@ namespace json_spirit return boost::get< bool >( v_ ); } - + template< class Config > int Value_impl< Config >::get_int() const { @@ -388,7 +393,7 @@ namespace json_spirit return static_cast< int >( get_int64() ); } - + template< class Config > int64_t Value_impl< Config >::get_int64() const { @@ -396,7 +401,7 @@ namespace json_spirit return boost::get< int64_t >( v_ ); } - + template< class Config > uint64_t Value_impl< Config >::get_uint64() const { @@ -474,49 +479,49 @@ namespace json_spirit { }; - template< class Value > + template< class Value > int get_value( const Value& value, Type_to_type< int > ) { return value.get_int(); } - - template< class Value > + + template< class Value > int64_t get_value( const Value& value, Type_to_type< int64_t > ) { return value.get_int64(); } - - template< class Value > + + template< class Value > uint64_t get_value( const Value& value, Type_to_type< uint64_t > ) { return value.get_uint64(); } - - template< class Value > + + template< class Value > double get_value( const Value& value, Type_to_type< double > ) { return value.get_real(); } - - template< class Value > + + template< class Value > typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > ) { return value.get_str(); } - - template< class Value > + + template< class Value > typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > ) { return value.get_array(); } - - template< class Value > + + template< class Value > typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > ) { return value.get_obj(); } - - template< class Value > + + template< class Value > bool get_value( const Value& value, Type_to_type< bool > ) { return value.get_bool(); @@ -524,7 +529,7 @@ namespace json_spirit } template< class Config > - template< typename T > + template< typename T > T Value_impl< Config >::get_value() const { return internal_::get_value( *this, internal_::Type_to_type< T >() ); diff --git a/src/json/json_spirit_writer.cpp b/src/json/json_spirit_writer.cpp index d24a632cf3..0f10cd8c0f 100644 --- a/src/json/json_spirit_writer.cpp +++ b/src/json/json_spirit_writer.cpp @@ -1,5 +1,6 @@ -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 diff --git a/src/json/json_spirit_writer.h b/src/json/json_spirit_writer.h index 52e14068e7..8b1825bf40 100644 --- a/src/json/json_spirit_writer.h +++ b/src/json/json_spirit_writer.h @@ -1,11 +1,12 @@ -#ifndef JSON_SPIRIT_WRITER -#define JSON_SPIRIT_WRITER - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_WRITER +#define JSON_SPIRIT_WRITER + #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma once #endif @@ -15,7 +16,7 @@ namespace json_spirit { - // functions to convert JSON Values to text, + // functions to convert JSON Values to text, // the "formatted" versions add whitespace to format the output nicely void write ( const Value& value, std::ostream& os ); diff --git a/src/json/json_spirit_writer_template.h b/src/json/json_spirit_writer_template.h index 28c49ddc64..d7273ec886 100644 --- a/src/json/json_spirit_writer_template.h +++ b/src/json/json_spirit_writer_template.h @@ -1,13 +1,15 @@ -#ifndef JSON_SPIRIT_WRITER_TEMPLATE -#define JSON_SPIRIT_WRITER_TEMPLATE - -// Copyright John W. Wilkinson 2007 - 2009. -// Distributed under the MIT License, see accompanying file LICENSE.txt +// SPDX-FileCopyrightText: © 2007 John W. Wilkinson +// +// SPDX-License-Identifier: MIT // json spirit version 4.03 +#ifndef JSON_SPIRIT_WRITER_TEMPLATE +#define JSON_SPIRIT_WRITER_TEMPLATE + #include "json_spirit_value.h" +#undef NDEBUG #include #include #include @@ -28,8 +30,6 @@ namespace json_spirit template< class String_type > String_type non_printable_to_string( unsigned int c ) { - typedef typename String_type::value_type Char_type; - String_type result( 6, '\\' ); result[1] = 'u'; @@ -146,8 +146,8 @@ namespace json_spirit void output( const Obj_member_type& member ) { - output( Config_type::get_name( member ) ); space(); - os_ << ':'; space(); + output( Config_type::get_name( member ) ); space(); + os_ << ':'; space(); output( Config_type::get_value( member ) ); } @@ -179,7 +179,7 @@ namespace json_spirit os_ << start_char; new_line(); ++indentation_level_; - + for( typename T::const_iterator i = t.begin(); i != t.end(); ++i ) { indent(); output( *i ); @@ -198,13 +198,13 @@ namespace json_spirit indent(); os_ << end_char; } - + void indent() { if( !pretty_ ) return; for( int i = 0; i < indentation_level_; ++i ) - { + { os_ << " "; } } diff --git a/src/kernel.cpp b/src/kernel.cpp index 4ea98ff0ff..c58c316256 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2012-2013 The PPCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 PPCoin Developers +// +// SPDX-License-Identifier: MIT #include @@ -36,13 +39,13 @@ static bool GetLastStakeModifierThin(const CBlockThinIndex* pindex, uint64_t& nS { if (!pindex) return error("GetLastStakeModifierThin: null pindex"); - + while (pindex && pindex->pprev && !pindex->GeneratedStakeModifier()) pindex = pindex->pprev; - + if (!pindex->GeneratedStakeModifier()) return error("GetLastStakeModifierThin: no generation at genesis block"); - + nStakeModifier = pindex->nStakeModifier; nModifierTime = pindex->GetBlockTime(); return true; @@ -72,19 +75,19 @@ static bool SelectBlockFromCandidates(std::vector >& { bool fSelected = false; uint256 hashBest = 0; - *pindexSelected = (const CBlockIndex*) 0; - BOOST_FOREACH(const PAIRTYPE(int64_t, uint256)& item, vSortedByTimestamp) + *pindexSelected = nullptr; + for (const auto& item : vSortedByTimestamp) { if (!mapBlockIndex.count(item.second)) return error("SelectBlockFromCandidates: failed to find block index for candidate block %s", item.second.ToString().c_str()); - + const CBlockIndex* pindex = mapBlockIndex[item.second]; if (fSelected && pindex->GetBlockTime() > nSelectionIntervalStop) break; - + if (mapSelectedBlocks.count(pindex->GetBlockHash()) > 0) continue; - + // compute the selection hash by hashing its proof-hash and the // previous proof-of-stake modifier CDataStream ss(SER_GETHASH, 0); @@ -107,10 +110,10 @@ static bool SelectBlockFromCandidates(std::vector >& *pindexSelected = (const CBlockIndex*) pindex; } } - + if (fDebugPoS) LogPrintf("SelectBlockFromCandidates: selection hash=%s\n", hashBest.ToString().c_str()); - + return fSelected; } @@ -119,21 +122,21 @@ static bool SelectBlockFromCandidatesThin(std::vectorGetBlockTime() > nSelectionIntervalStop) break; - + if (mapSelectedBlocks.count(pindex->GetBlockHash()) > 0) continue; - + // compute the selection hash by hashing its proof-hash and the // previous proof-of-stake modifier CDataStream ss(SER_GETHASH, 0); @@ -144,7 +147,7 @@ static bool SelectBlockFromCandidatesThin(std::vectorIsProofOfStake()) hashSelection >>= 32; - + if (fSelected && hashSelection < hashBest) { hashBest = hashSelection; @@ -157,10 +160,10 @@ static bool SelectBlockFromCandidatesThin(std::vector= pindexPrev->GetBlockTime() / nModifierInterval) return true; // Sort candidate blocks by timestamp std::vector > vSortedByTimestamp; - vSortedByTimestamp.reserve(64 * nModifierInterval / GetTargetSpacing(pindexPrev->nHeight)); + vSortedByTimestamp.reserve(64 * nModifierInterval / GetTargetSpacing(pindexPrev->nHeight, pindexPrev->GetBlockTime())); int64_t nSelectionInterval = GetStakeModifierSelectionInterval(); int64_t nSelectionIntervalStart = (pindexPrev->GetBlockTime() / nModifierInterval) * nModifierInterval - nSelectionInterval; const CBlockIndex* pindex = pindexPrev; @@ -217,7 +220,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod uint64_t nStakeModifierNew = 0; int64_t nSelectionIntervalStop = nSelectionIntervalStart; std::map mapSelectedBlocks; - + for (int nRound=0; nRoundnHeight - nHeightFirstCandidate, 1, "="); pindex = pindex->pprev; } - - BOOST_FOREACH(const PAIRTYPE(uint256, const CBlockIndex*)& item, mapSelectedBlocks) - // 'S' indicates selected proof-of-stake blocks - // 'W' indicates selected proof-of-work blocks + + for (const auto& item : mapSelectedBlocks) { + // 'S' indicates selected proof-of-stake blocks, 'W' indicates selected proof-of-work blocks strSelectionMap.replace(item.second->nHeight - nHeightFirstCandidate, 1, item.second->IsProofOfStake()? "S" : "W"); - + } + LogPrintf("ComputeNextStakeModifier: selection height [%d, %d] map %s\n", nHeightFirstCandidate, pindexPrev->nHeight, strSelectionMap.c_str()); } else if (fDebugPoS) @@ -272,24 +275,24 @@ bool ComputeNextStakeModifierThin(const CBlockThinIndex* pindexPrev, uint64_t& n fGeneratedStakeModifier = true; return true; // genesis block's modifier is 0 }; - + // First find current stake modifier and its generation block time // if it's not old enough, return the same stake modifier int64_t nModifierTime = 0; if (!GetLastStakeModifierThin(pindexPrev, nStakeModifier, nModifierTime)) return error("ComputeNextStakeModifier: unable to get last modifier"); - + if (fDebug) { LogPrintf("ComputeNextStakeModifierThin: prev modifier=0x%016x time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str()); }; - + if (nModifierTime / nModifierInterval >= pindexPrev->GetBlockTime() / nModifierInterval) return true; // Sort candidate blocks by timestamp std::vector > vSortedByTimestamp; - vSortedByTimestamp.reserve(64 * nModifierInterval / GetTargetSpacing(pindexPrev->nHeight)); + vSortedByTimestamp.reserve(64 * nModifierInterval / GetTargetSpacing(pindexPrev->nHeight, pindexPrev->GetBlockTime())); int64_t nSelectionInterval = GetStakeModifierSelectionInterval(); int64_t nSelectionIntervalStart = (pindexPrev->GetBlockTime() / nModifierInterval) * nModifierInterval - nSelectionInterval; const CBlockThinIndex* pindex = pindexPrev; @@ -298,7 +301,7 @@ bool ComputeNextStakeModifierThin(const CBlockThinIndex* pindexPrev, uint64_t& n vSortedByTimestamp.push_back(std::make_pair(pindex->GetBlockTime(), pindex->GetBlockHash())); pindex = pindex->pprev; }; - + int nHeightFirstCandidate = pindex ? (pindex->nHeight + 1) : 0; reverse(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); sort(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); @@ -307,7 +310,7 @@ bool ComputeNextStakeModifierThin(const CBlockThinIndex* pindexPrev, uint64_t& n uint64_t nStakeModifierNew = 0; int64_t nSelectionIntervalStop = nSelectionIntervalStart; std::map mapSelectedBlocks; - + for (int nRound=0; nRoundnHeight - nHeightFirstCandidate, 1, "="); pindex = pindex->pprev; }; - - BOOST_FOREACH(const PAIRTYPE(uint256, const CBlockThinIndex*)& item, mapSelectedBlocks) + + for (const auto& item : mapSelectedBlocks) { // 'S' indicates selected proof-of-stake blocks // 'W' indicates selected proof-of-work blocks strSelectionMap.replace(item.second->nHeight - nHeightFirstCandidate, 1, item.second->IsProofOfStake()? "S" : "W"); }; - + LogPrintf("ComputeNextStakeModifierThin: selection height [%d, %d] map %s\n", nHeightFirstCandidate, pindexPrev->nHeight, strSelectionMap.c_str()); } else if (fDebugPoS) @@ -398,7 +401,7 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifi else return false; } - + pindex = pindex->pnext; if (pindex->GeneratedStakeModifier()) { @@ -406,7 +409,7 @@ static bool GetKernelStakeModifier(uint256 hashBlockFrom, uint64_t& nStakeModifi nStakeModifierTime = pindex->GetBlockTime(); } } - + nStakeModifier = pindex->nStakeModifier; return true; } @@ -430,7 +433,7 @@ static bool GetKernelStakeModifierThinIt(CBlockThinIndex* pindex, int64_t nFound return false; }; }; - + pindex = pindex->pnext; if (pindex->GeneratedStakeModifier()) { @@ -438,7 +441,7 @@ static bool GetKernelStakeModifierThinIt(CBlockThinIndex* pindex, int64_t nFound nStakeModifierTime = pindex->GetBlockTime(); }; }; - + nStakeModifier = pindex->nStakeModifier; return true; }; @@ -446,27 +449,27 @@ static bool GetKernelStakeModifierThinIt(CBlockThinIndex* pindex, int64_t nFound static bool GetKernelStakeModifierThin(uint256 hashBlockFrom, uint64_t& nStakeModifier, int& nStakeModifierHeight, int64_t& nStakeModifierTime, bool fPrintProofOfStake) { nStakeModifier = 0; - + int64_t nFoundTime; int64_t nStakeModifierSelectionInterval = GetStakeModifierSelectionInterval(); - + std::map::iterator mi = mapBlockThinIndex.find(hashBlockFrom); if (mi == mapBlockThinIndex.end()) { if (fThinFullIndex || !pindexRear) return error("GetKernelStakeModifierThin() : block not indexed"); - + CTxDB txdb("r"); CDiskBlockThinIndex diskindex; if (!txdb.ReadBlockThinIndex(hashBlockFrom, diskindex) || diskindex.hashNext == 0) return error("GetKernelStakeModifierThin() : block not in db %s", hashBlockFrom.ToString().c_str()); - + nStakeModifierHeight = diskindex.nHeight; nStakeModifierTime = (int64_t)diskindex.nTime; nFoundTime = (int64_t)diskindex.nTime; - + // TODO, check mapBlockThinIndex while (nStakeModifierTime < nFoundTime + nStakeModifierSelectionInterval) { @@ -483,24 +486,24 @@ static bool GetKernelStakeModifierThin(uint256 hashBlockFrom, uint64_t& nStakeMo return false; }; }; - - + + if ((int64_t)diskindex.nTime > pindexRear->GetBlockTime()) { // -- back into the index window mi = mapBlockThinIndex.find(diskindex.hashNext); - + if (mi != mapBlockThinIndex.end()) { CBlockThinIndex* pindex = mi->second; return GetKernelStakeModifierThinIt(pindex, nFoundTime, nStakeModifierSelectionInterval, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake); }; }; - + if (!txdb.ReadBlockThinIndex(diskindex.hashNext, diskindex) || diskindex.hashNext == 0) return error("GetKernelStakeModifierThin() : block not indexed %s", diskindex.hashNext.ToString().c_str()); - + //pindex = pindex->pnext; if (diskindex.GeneratedStakeModifier()) { @@ -508,16 +511,16 @@ static bool GetKernelStakeModifierThin(uint256 hashBlockFrom, uint64_t& nStakeMo nStakeModifierTime = (int64_t)diskindex.nTime; }; }; - + nStakeModifier = diskindex.nStakeModifier; return true; }; - + CBlockThinIndex* pindexFrom = mi->second; nStakeModifierHeight = pindexFrom->nHeight; nStakeModifierTime = pindexFrom->GetBlockTime(); nFoundTime = pindexFrom->GetBlockTime(); - + CBlockThinIndex* pindex = pindexFrom; return GetKernelStakeModifierThinIt(pindex, nFoundTime, nStakeModifierSelectionInterval, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake); } @@ -537,7 +540,7 @@ static bool GetKernelStakeModifierThin(uint256 hashBlockFrom, uint64_t& nStakeMo // future proof-of-stake at the time of the coin's confirmation // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage -// txPrev.offset: offset of txPrev inside block, to reduce the chance of +// txPrev.offset: offset of txPrev inside block, to reduce the chance of // nodes generating coinstake at the same time // txPrev.nTime: reduce the chance of nodes generating coinstake at the same // time @@ -551,12 +554,12 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc { if (nTimeTx < txPrev.nTime) // Transaction timestamp violation return error("CheckStakeKernelHash() : nTime violation"); - + unsigned int nTimeBlockFrom = blockFrom.GetBlockTime(); - + if (nTimeBlockFrom + nStakeMinAge > nTimeTx) // Min age requirement return error("CheckStakeKernelHash() : min age violation"); - + CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); @@ -570,7 +573,7 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc uint64_t nStakeModifier = 0; int nStakeModifierHeight = 0; int64_t nStakeModifierTime = 0; - + if (nNodeMode == NT_FULL) { if (!GetKernelStakeModifier(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake)) @@ -580,12 +583,12 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc if (!GetKernelStakeModifierThin(hashBlockFrom, nStakeModifier, nStakeModifierHeight, nStakeModifierTime, fPrintProofOfStake)) return false; }; - + ss << nStakeModifier; - + ss << nTimeBlockFrom << nTxPrevOffset << txPrev.nTime << prevout.n << nTimeTx; hashProofOfStake = Hash(ss.begin(), ss.end()); - + if (fPrintProofOfStake) { int nHeight = 0; @@ -594,7 +597,7 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc else if (fThinFullIndex) // otherwise index may not be in the window nHeight = mapBlockThinIndex[hashBlockFrom]->nHeight; - + LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from height=%d timestamp=%s\n", nStakeModifier, nStakeModifierHeight, DateTimeStrFormat(nStakeModifierTime).c_str(), @@ -604,24 +607,24 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc nStakeModifier, nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx, hashProofOfStake.ToString().c_str()); - + CBigNum nTry = CBigNum(hashProofOfStake); CBigNum nTar = bnCoinDayWeight * bnTargetPerCoinDay; LogPrintf("try %s\n target %s\n", nTry.ToString().c_str(), nTar.ToString().c_str()); }; - - + + // Now check if proof-of-stake hash meets target protocol if (CBigNum(hashProofOfStake) > bnCoinDayWeight * bnTargetPerCoinDay) return false; - + if (fDebug && !fPrintProofOfStake) { //int nHeight = nNodeMode == NT_FULL ? mapBlockIndex[hashBlockFrom]->nHeight : mapBlockThinIndex[hashBlockFrom]->nHeight; int nHeight = nNodeMode == NT_FULL ? mapBlockIndex[hashBlockFrom]->nHeight : fThinFullIndex ? mapBlockThinIndex[hashBlockFrom]->nHeight : 0; - + LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from height=%d timestamp=%s\n", - nStakeModifier, nStakeModifierHeight, + nStakeModifier, nStakeModifierHeight, DateTimeStrFormat(nStakeModifierTime), nHeight, DateTimeStrFormat(blockFrom.GetBlockTime())); @@ -630,12 +633,12 @@ static inline bool CheckStakeKernelHashV1(unsigned int nBits, const CBlock& bloc nTimeBlockFrom, nTxPrevOffset, txPrev.nTime, prevout.n, nTimeTx, hashProofOfStake.ToString()); } - + return true; } -// ShadowCoin kernel protocol +// Spectrecoin kernel protocol // coinstake must meet hash target according to the protocol: // kernel (input 0) must meet the formula // hash(nStakeModifier + txPrev.block.nTime + txPrev.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight @@ -661,9 +664,6 @@ static inline bool CheckStakeKernelHashV2(CStakeModifier* pStakeMod, unsigned in if (nTimeTx < txPrev.nTime) // Transaction timestamp violation return error("CheckStakeKernelHash() : nTime violation"); - if (nTimeBlockFrom + nStakeMinAge > nTimeTx) // Min age requirement - return error("CheckStakeKernelHash() : min age violation"); - // Base target CBigNum bnTarget; bnTarget.SetCompact(nBits); @@ -683,36 +683,27 @@ static inline bool CheckStakeKernelHashV2(CStakeModifier* pStakeMod, unsigned in hashProofOfStake = Hash(ss.begin(), ss.end()); - if (fPrintProofOfStake) - { - LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n", - pStakeMod->nModifier, pStakeMod->nHeight, - DateTimeStrFormat(pStakeMod->nTime), - DateTimeStrFormat(nTimeBlockFrom)); - LogPrintf("CheckStakeKernelHash() : check modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s target=%s\n", - pStakeMod->nModifier, - nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx, - hashProofOfStake.ToString(), - bnTarget.ToString()); - } // Now check if proof-of-stake hash meets target protocol - if (CBigNum(hashProofOfStake) > bnTarget) - return false; + bool foundHash = CBigNum(hashProofOfStake) < bnTarget; - if (fDebug && !fPrintProofOfStake) + if (fPrintProofOfStake || (foundHash && fDebug)) { - LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n", - pStakeMod->nModifier, pStakeMod->nHeight, - DateTimeStrFormat(pStakeMod->nTime), - DateTimeStrFormat(nTimeBlockFrom)); - LogPrintf("CheckStakeKernelHash() : pass modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n", - pStakeMod->nModifier, - nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx, - hashProofOfStake.ToString()); + if (Params().IsProtocolV3(pStakeMod->nHeight)) + LogPrintf("CheckStakeKernelHash() : PoSv3 check=%b with modifierV2=%s at height=%d timestamp=%s, nTimeTxPrev=%u nPrevout=%u nTimeTx=%u, hashProof=%s target=%s\n", + foundHash, + pStakeMod->bnModifierV2.ToString(), pStakeMod->nHeight, DateTimeStrFormat(pStakeMod->nTime), + txPrev.nTime, prevout.n, nTimeTx, + hashProofOfStake.ToString(), bnTarget.ToString()); + else + LogPrintf("CheckStakeKernelHash() : PoSv2 check=%b with modifier=0x%016x at height=%d timestamp=%s, nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u, hashProof=%s target=%s\n", + foundHash, + pStakeMod->nModifier, pStakeMod->nHeight, DateTimeStrFormat(pStakeMod->nTime), + nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx, + hashProofOfStake.ToString(), bnTarget.ToString()); } - return true; + return foundHash; } @@ -727,18 +718,36 @@ bool CheckStakeKernelHash(int nPrevHeight, CStakeModifier* pStakeMod, unsigned i // Check kernel hash target and coinstake signature bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake) { + if (tx.nVersion == ANON_TXN_VERSION) + return CheckAnonProofOfStake(pindexPrev, tx, nBits, hashProofOfStake, targetProofOfStake); + if (!tx.IsCoinStake()) return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString()); // Kernel (input 0) must match the stake hash target per coin age (nBits) const CTxIn& txin = tx.vin[0]; - // First try finding the previous transaction in database + // First try finding the previous transaction in database and check that output is not spent CTxDB txdb("r"); CTransaction txPrev; CTxIndex txindex; if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex)) return tx.DoS(1, error("CheckProofOfStake() : INFO: read txPrev failed")); // previous transaction not in main chain, may occur during initial download + if (!txindex.vSpent[txin.prevout.n].IsNull()) + { + CBlock block; + if (block.ReadFromDisk(txindex.vSpent[txin.prevout.n].nFile, txindex.vSpent[txin.prevout.n].nBlockPos, false)) + { + std::map::iterator mi = mapBlockIndex.find(block.GetHash()); + if (fDebug) + LogPrintf("CheckProofOfStake() : block at height %d spends txPrev staked at height %d\n", mi->second->nHeight, pindexPrev->nHeight + 1); + if (mi != mapBlockIndex.end() && mi->second->nHeight < pindexPrev->nHeight + 1) // only consider spends in blocks BEFORE current block + return tx.DoS(100, error("CheckProofOfStake() : INFO: txPrev already used at %s height %d", txindex.vSpent[txin.prevout.n].ToString(), mi->second->nHeight)); + } + else { + LogPrintf("CheckProofOfStake(): Warning - Could not read block which spends txPrev at %s -> ignore spend", txindex.vSpent[txin.prevout.n].ToString()); + } + } // Verify signature if (!VerifySignature(txPrev, tx, 0, SCRIPT_VERIFY_NONE, 0)) @@ -752,15 +761,11 @@ bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned if (Params().IsProtocolV3(pindexPrev->nHeight)) { int nDepth; - if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, nStakeMinConfirmations - 1, nDepth)) + if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetStakeMinConfirmations(tx.nTime) - 1, nDepth)) return tx.DoS(100, error("CheckProofOfStake() : tried to stake at depth %d", nDepth + 1)); } - else - { - unsigned int nTimeBlockFrom = block.GetBlockTime(); - if (nTimeBlockFrom + nStakeMinAge > tx.nTime) - return error("CheckProofOfStake() : min age violation"); - } + else if (block.GetBlockTime() + nStakeMinAge > tx.nTime) + return error("CheckProofOfStake() : min age violation"); CStakeModifier stakeMod(pindexPrev->nStakeModifier, pindexPrev->bnStakeModifierV2, pindexPrev->nHeight, pindexPrev->nTime); if (!CheckStakeKernelHash(pindexPrev->nHeight, &stakeMod, nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, txin.prevout, tx.nTime, hashProofOfStake, targetProofOfStake, fDebugPoS)) @@ -782,32 +787,160 @@ bool CheckCoinStakeTimestamp(int nHeight, int64_t nTimeBlock, int64_t nTimeTx) bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, int64_t nTime, const COutPoint& prevout, int64_t* pBlockTime) { uint256 hashProofOfStake, targetProofOfStake; - + CTxDB txdb("r"); CTransaction txPrev; CTxIndex txindex; if (!txPrev.ReadFromDisk(txdb, prevout, txindex)) return false; - + // Read block header CBlock block; if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false)) return false; - if (Params().IsProtocolV3(nTime)) + if (Params().IsProtocolV3(pindexPrev->nHeight+1)) { int nDepth; - if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, nStakeMinConfirmations - 1, nDepth)) + if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetStakeMinConfirmations(nTime) - 1, nDepth)) return false; } - else - if (block.GetBlockTime() + nStakeMinAge > nTime) - return false; // only count coins meeting min age requirement + else if (block.GetBlockTime() + nStakeMinAge > nTime) + return false; // only count coins meeting min age requirement if (pBlockTime) *pBlockTime = block.GetBlockTime(); - + // - workaround for thin mode CStakeModifier stakeMod(pindexPrev->nStakeModifier, pindexPrev->bnStakeModifierV2, pindexPrev->nHeight, pindexPrev->nTime); return CheckStakeKernelHash(pindexPrev->nHeight, &stakeMod, nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, txPrev, prevout, nTime, hashProofOfStake, targetProofOfStake, fDebugPoS); } + + +/** + * ----------------------------------------------------------- + * Stealth Staking + * ----------------------------------------------------------- + * + * An anon staking transaction is valid, if + * - transaction is PoSv3 conform + * - a valid rigsignature of MIN_RING_SIZE exists in vin[0] + * - keyImage is unspent (checked in CheckAnonInputs()) + * - all ring signature anon outputs meet minDepth maturity requirement (checked in CheckAnonInputs()) + * - the kernel hash calculated is below target + * + * Spectrecoin anon kernel protocol + * -------------------------------- + * coinstake kernel (input 0) must meet hash target according to the formula: + * + * hash(nStakeModifier + keyImage + nTime) < bnTarget * nWeight + * + * this ensures that the chance of getting a coinstake is proportional to the amount of coins one owns. + * + * The reason this hash is chosen is the following: + * nStakeModifier: scrambles computation to make it very difficult to precompute future proof-of-stake. + * nStakeModifier is either the UTXO hash or keyImage used for the last staking transaction + * plus the previous block's stake modifier + * keyImage: the keyImage of the ATXO used for staking is unique regardles the mixins, + * makes sure an ATXO can only be used once for generating a kernel hash + * nTime: current timestamp (granularity set to 16 seconds) + * + * Note: + * block/tx hash should not be used here as they can be generated in vast + * quantities so as to generate blocks faster, degrading the system back into + * a proof-of-work situation. + */ +bool CheckAnonProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake) +{ + if (!tx.IsAnonCoinStake()) + return error("CheckAnonProofOfStake() : called on non-anon-coinstake %s", tx.GetHash().ToString()); + + if (!Params().IsProtocolV3(pindexPrev->nHeight+1)) + return error("CheckAnonProofOfStake() : not allowed for PoSv2 for coinstake %s", tx.GetHash().ToString()); + + if (!Params().IsForkV3(tx.nTime)) + return error("CheckAnonProofOfStake() : called before V3 fork time for coinstake %s", tx.GetHash().ToString()); + + if (!tx.vin[0].IsAnonInput()) + return error("CheckAnonProofOfStake() : vin[0] is no anon input for coinstake %s", tx.GetHash().ToString()); + + if (!tx.vout[1].IsAnonOutput()) + return error("CheckAnonProofOfStake() : vout[1] is no anon output for coinstake %s", tx.GetHash().ToString()); + + CTxDB txdb("r"); + + // Kernel (input 0) must match the stake hash target per coin age (nBits) + const CTxIn& txin = tx.vin[0]; + ec_point vchImage; + txin.ExtractKeyImage(vchImage); + + // ringsig AB + int64_t nCoinValue = -1; + int nRingSize = txin.ExtractRingSize(); + if (nRingSize != MIN_RING_SIZE) + return tx.DoS(100, error("CheckAnonProofOfStake() : INFO: Ringsize not %d for coinstake tx %s", MIN_RING_SIZE, tx.GetHash().ToString().c_str())); + + { + LOCK(cs_main); + CKeyImageSpent spentKeyImage; + bool fInMemPool; + if (GetKeyImage(&txdb, vchImage, spentKeyImage, fInMemPool) && // keyImage already spent + spentKeyImage.nBlockHeight < (pindexPrev->nHeight + 1) && // only consider spends in blocks BEFORE current block + !(spentKeyImage.txnHash == tx.GetHash() && spentKeyImage.inputNo == 0) && // this can happen for transactions created by the local node + TxnHashInSystem(&txdb, spentKeyImage.txnHash)) // keyimage is in db, but invalid as does not point to a known transaction, could be an old mempool keyimag + return tx.DoS(100, error("CheckAnonProofOfStake() : INFO: Coinstake tx %s has already spent keyImage %s", tx.GetHash().ToString().c_str(), HexStr(vchImage).c_str())); + + if (!tx.CheckAnonInputAB(txdb, txin, 0, MIN_RING_SIZE, vchImage, nCoinValue)) + return tx.DoS(100, error("CheckAnonProofOfStake() : INFO: CheckAnonInputAB failed on coinstake tx %s", tx.GetHash().ToString().c_str())); + } + + CStakeModifier stakeMod(pindexPrev->nStakeModifier, pindexPrev->bnStakeModifierV2, pindexPrev->nHeight, pindexPrev->nTime); + if (!CheckAnonStakeKernelHash(&stakeMod, nBits, nCoinValue, vchImage, tx.nTime, hashProofOfStake, targetProofOfStake, fDebugPoS)) + return tx.DoS(1, error("CheckAnonProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString().c_str(), hashProofOfStake.ToString().c_str())); // may occur during initial download or if behind on block chain sync + + return true; +} +// Note: this method does not validate that the keyImage is valid & unspent and that anon output is mature +bool CheckAnonStakeKernelHash(CStakeModifier* pStakeMod, const unsigned int& nBits, const int64_t& anonValue, const ec_point &anonKeyImage, const unsigned int& nTimeTx, uint256& hashProofOfStake, uint256& targetProofOfStake, const bool fPrintProofOfStake) +{ + // Base target + CBigNum bnTarget; + bnTarget.SetCompact(nBits); + + // Weighted target + CBigNum bnWeight = CBigNum(anonValue); + bnTarget *= bnWeight; + + targetProofOfStake = bnTarget.getuint256(); + + CDataStream ss(SER_GETHASH, 0); + ss << pStakeMod->bnModifierV2; + ss << anonKeyImage << nTimeTx; + + hashProofOfStake = Hash(ss.begin(), ss.end()); + + // Now check if proof-of-stake hash meets target protocol + bool foundHash = CBigNum(hashProofOfStake) < bnTarget; + + if (fPrintProofOfStake || (foundHash && fDebug)) + { + LogPrintf("CheckAnonStakeKernelHash() : PoSv3 check=%b with modifier=%s at height=%d timestamp=%s, anonKeyImage=%s nTimeTx=%u, hashProof=%s target=%s\n", + foundHash, + pStakeMod->bnModifierV2.ToString(), + pStakeMod->nHeight, + DateTimeStrFormat(pStakeMod->nTime), + HexStr(anonKeyImage), nTimeTx, + hashProofOfStake.ToString(), + bnTarget.ToString()); + } + return foundHash; +} + + +bool CheckAnonKernel(const CBlockIndex* pindexPrev, const unsigned int& nBits, const int64_t& anonValue, const ec_point& anonKeyImage, const unsigned int& nTime) +{ + uint256 hashProofOfStake, targetProofOfStake; + + CStakeModifier stakeMod(pindexPrev->nStakeModifier, pindexPrev->bnStakeModifierV2, pindexPrev->nHeight, pindexPrev->nTime); + return CheckAnonStakeKernelHash(&stakeMod, nBits, anonValue, anonKeyImage, nTime, hashProofOfStake, targetProofOfStake, fDebugPoS); +} diff --git a/src/kernel.h b/src/kernel.h index b8a4bb41da..e927fca23b 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -1,6 +1,10 @@ -// Copyright (c) 2012-2013 The PPCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 PPCoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef PPCOIN_KERNEL_H #define PPCOIN_KERNEL_H @@ -34,13 +38,26 @@ bool CheckProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned // Check whether the coinstake timestamp meets protocol bool CheckCoinStakeTimestamp(int nHeight, int64_t nTimeBlock, int64_t nTimeTx); -// Get time weight using supplied timestamps +// Get time weight using supplied timestamps int64_t GetWeight(int64_t nIntervalBeginning, int64_t nIntervalEnd); // TODO: posv2 remove // Wrapper around CheckStakeKernelHash() // Also checks existence of kernel input and min age // Convenient for searching a kernel -bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, int64_t nTime, const COutPoint& prevout, int64_t* pBlockTime = NULL); +bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, int64_t nTime, const COutPoint& prevout, int64_t* pBlockTime = nullptr); + + +// -- Stealth Staking +// Check whether stake kernel meets hash target and ATXO maturity +// Sets hashProofOfStake on success return +bool CheckAnonProofOfStake(CBlockIndex* pindexPrev, const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake); + +// Check whether stake kernel meets hash target +// Sets hashProofOfStake on success return +bool CheckAnonStakeKernelHash(CStakeModifier* pStakeMod, const unsigned int& nBits, const int64_t& anonValue, const ec_point &anonKeyImage, const unsigned int& nTimeTx, uint256& hashProofOfStake, uint256& targetProofOfStake, const bool fPrintProofOfStake); +// Wrapper around CheckAnonStakeKernelHash() +// Convenient for searching a anon kernel +bool CheckAnonKernel(const CBlockIndex* pindexPrev, const unsigned int& nBits, const int64_t& anonValue, const ec_point& anonKeyImage, const unsigned int& nTime); #endif // PPCOIN_KERNEL_H diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp new file mode 100644 index 0000000000..d800aa1504 --- /dev/null +++ b/src/kernel/chainparams.cpp @@ -0,0 +1,532 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// Copyright (c) 2009-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include // For COIN, CENT, COIN_YEAR_REWARD, GENESIS_BLOCK_TIME +#include // For CBigNum +#include +#include +#include +#include +#include +#include +#include // For CScript +#include +#include +// ChainTypeToString is implemented in util/chaintype.cpp +#include +#include // For ARRAYLEN, GetTime, GetRand, ParseHex, etc. +#include // For CService, CAddress +#include // For CBlockIndex, nStakeReward, nAnonStakeReward + +#include +#include +#include +#include +#include + +// External references to stake rewards (set in state.cpp) +extern int64_t nStakeReward; +extern int64_t nAnonStakeReward; +extern bool fDebug; +extern bool fTestNet; + +// Forward declarations +static void convertSeeds(std::vector &vSeedsOut, const unsigned int *data, unsigned int count, int port); + +// Helper function for uint256 from hex string (compatibility) +inline uint256 uint256S(const char* str) { + return uint256(str); +} +inline uint256 uint256S(const std::string& str) { + return uint256(str); +} + +// Convert the pnSeeds array into usable address objects. +static void convertSeeds(std::vector &vSeedsOut, const unsigned int *data, unsigned int count, int port) +{ + const int64_t nOneWeek = 7*24*60*60; + for (unsigned int k = 0; k < count; ++k) + { + struct in_addr ip; + unsigned int i = data[k], t; + + // Convert to big endian + t = (i & 0x000000ff) << 24u + | (i & 0x0000ff00) << 8u + | (i & 0x00ff0000) >> 8u + | (i & 0xff000000) >> 24u; + + memcpy(&ip, &t, sizeof(ip)); + + CAddress addr(CService(ip, port)); + addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; + vSeedsOut.push_back(addr); + } +} + +// Alias-specific reward functions +int64_t CChainParams::GetProofOfWorkReward(int nHeight, int64_t nFees) const +{ + int64_t nSubsidy = 0; + + if(nHeight == 1) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 2000000 : 20000000) * COIN; + + else if(nHeight <= nLastPOWBlock) + nSubsidy = 0; + + if (fDebug && GetBoolArg("-printcreation")) + LogPrintf("GetProofOfWorkReward() : create=%s nSubsidy=%d\n", FormatMoney(nSubsidy).c_str(), nSubsidy); + + return nSubsidy; +} + +int64_t CChainParams::GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) const +{ + int64_t nSubsidy; + + if (IsForkV4SupplyIncrease(pindexPrev)) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 300000 : 3000000) * COIN; + else if (IsProtocolV3(pindexPrev->nHeight)) + nSubsidy = IsForkV3(pindexPrev->GetBlockTime()) ? + nStakeReward : + (pindexPrev->nMoneySupply / COIN) * COIN_YEAR_REWARD / (365 * 24 * (60 * 60 / 64)); + else + nSubsidy = nCoinAge * COIN_YEAR_REWARD * 33 / (365 * 33 + 8); + + if (fDebug && GetBoolArg("-printcreation")) + { + if (IsProtocolV3(pindexPrev->nHeight)) + LogPrintf("GetProofOfStakeReward(): create=%s\n", FormatMoney(nSubsidy).c_str()); + else + LogPrintf("GetProofOfStakeReward(): create=%s nCoinAge=%d\n", FormatMoney(nSubsidy).c_str(), nCoinAge); + } + + return nSubsidy + nFees; +} + +int64_t CChainParams::GetProofOfAnonStakeReward(const CBlockIndex* pindexPrev, int64_t nFees) const +{ + int64_t nSubsidy = nAnonStakeReward; + if (IsForkV4SupplyIncrease(pindexPrev)) + nSubsidy = (NetworkID() == CChainParams::TESTNET ? 300000 : 3000000) * COIN; + + if (fDebug && GetBoolArg("-printcreation")) + LogPrintf("GetProofOfAnonStakeReward(): create=%s\n", FormatMoney(nSubsidy).c_str()); + + return nSubsidy + nFees; +} + +bool CChainParams::IsForkV4SupplyIncrease(const CBlockIndex* pindexPrev) const +{ + return pindexPrev->GetBlockTime() >= nForkV4Time && pindexPrev->pprev->GetBlockTime() < nForkV4Time; +} + +// Create Alias genesis block +static CBlock CreateAliasGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits) +{ + const char* pszTimestamp = "https://www.cryptocoinsnews.com/encrypted-services-exec-bitcoins-price-history-follows-gartners-hype-cycle/"; + CTransaction txNew; + txNew.nTime = GENESIS_BLOCK_TIME; + txNew.vin.resize(1); + txNew.vout.resize(1); + txNew.vin[0].scriptSig = CScript() << 0 << CBigNum(42) << std::vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); + txNew.vout[0].SetEmpty(); + + CBlock genesis; + genesis.vtx.push_back(txNew); + genesis.hashPrevBlock = 0; + genesis.hashMerkleRoot = genesis.BuildMerkleTree(); + genesis.nVersion = 1; + genesis.nTime = GENESIS_BLOCK_TIME; + genesis.nBits = nBits; + genesis.nNonce = nNonce; + + return genesis; +} + +/** + * Main network + */ +class CMainParams : public CChainParams { +public: + CMainParams() + : m_chain_type(ChainType::MAIN) + , strNetworkID("main") + , strDataDir("") + { + + // Message start + pchMessageStart[0] = 0xb5; + pchMessageStart[1] = 0x22; + pchMessageStart[2] = 0x5c; + pchMessageStart[3] = 0xd3; + + vAlertPubKey = ParseHex("04f7bbad03208ea942e292080854d422d046d457949ea70ad3306438fc8357343dccaa73e52291ebe07de85c6701d88d87af2d29c2e3b024fb0ad53f045a6d3ad6"); + + nDefaultPort = 37347; + nRPCPort = 36657; + nBIP44ID = 0x800000d5; + + // PoS parameters + nLastPOWBlock = 17000; + nFirstPosv2Block = 17001; + nFirstPosv3Block = 17010; + + // Proof limits + bnProofOfWorkLimit = CBigNum(~uint256(0) >> 20); + bnProofOfStakeLimit = CBigNum(~uint256(0) >> 20); + bnProofOfStakeLimitV2 = CBigNum(~uint256(0) >> 48); + + nStakeMinConfirmationsLegacy = 288; + nStakeMinConfirmations = 450; // block time 96 seconds * 450 = 12 hours + + // Consensus parameters + consensus.hashGenesisBlock = uint256(); + consensus.nSubsidyHalvingInterval = 210000; + consensus.BIP34Height = 0; + consensus.BIP65Height = 0; + consensus.BIP66Height = 0; + consensus.CSVHeight = 1; + consensus.SegwitHeight = 0; + consensus.MinBIP9WarningHeight = 0; + consensus.powLimit = uint256S("0000000000000fffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetSpacing = 96; // Alias: 96 seconds + consensus.nPowTargetTimespan = 24 * 60 * 60; // 24 hours (moving average) + consensus.fPowAllowMinDifficultyBlocks = false; + consensus.fPowNoRetargeting = false; + consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016 + consensus.nMinerConfirmationWindow = 2016; + + // Alias-specific consensus (stored in consensus params) + consensus.m_alias_mode = true; + consensus.nForkV2Time = 1534888800; // MAINNET V2 chain fork + consensus.nForkV3Time = 1558123200; // MAINNET V3 chain fork + consensus.nForkV4Time = 1569614400; // MAINNET V4 chain fork + consensus.nLastPOWBlock = 17000; + consensus.nFirstPosv2Block = 17001; + consensus.nFirstPosv3Block = 17010; + consensus.m_min_ringsize = 10; + consensus.m_max_ringsize = 10; + consensus.m_max_anon_inputs = 32; + consensus.m_max_anon_output = 1000 * COIN; + consensus.nMinRCTOutputDepth = 12; + + // Genesis block + genesis = CreateAliasGenesisBlock(GENESIS_BLOCK_TIME, 715015, bnProofOfWorkLimit.GetCompact()); + hashGenesisBlock = genesis.GetHash(); + consensus.hashGenesisBlock = hashGenesisBlock; + + assert(hashGenesisBlock == uint256("0x000001fd6111f0d71d90b7d8c827c6028dbc867f6c527d90794a0d22f68fecd4")); + assert(genesis.hashMerkleRoot == uint256("0x48d79d88cdf7d5c84dbb2ffb4fcaab253cebe040a4e7b46cdd507fbb93623e3f")); + + // Base58 prefixes + base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 63); + base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 136); + base58Prefixes[SECRET_KEY] = std::vector(1, 179); + base58Prefixes[STEALTH_ADDRESS] = std::vector(1, 40); + base58Prefixes[EXT_PUBLIC_KEY] = {0x2C, 0x51, 0x3B, 0xD7}; + base58Prefixes[EXT_SECRET_KEY] = {0x2C, 0x51, 0xC1, 0x5A}; + base58Prefixes[EXT_KEY_HASH] = std::vector(1, 137); + base58Prefixes[EXT_ACC_HASH] = std::vector(1, 83); + base58Prefixes[EXT_PUBLIC_KEY_BTC] = {0x04, 0x88, 0xB2, 0x1E}; + base58Prefixes[EXT_SECRET_KEY_BTC] = {0x04, 0x88, 0xAD, 0xE4}; + + // DNS seeds + vSeeds.push_back(CDNSSeedData("node1.spectreproject.io", "node1.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node2.spectreproject.io", "node2.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node3.spectreproject.io", "node3.spectreproject.io")); + vSeeds.push_back(CDNSSeedData("node4.spectreproject.io", "node4.spectreproject.io")); + + convertSeeds(vFixedSeeds, pnSeed, ARRAYLEN(pnSeed), nDefaultPort); + + // Fork times + nForkV2Time = 1534888800; // MAINNET V2 chain fork (GMT: Tuesday, 21. August 2018 22.00) + nForkV3Time = 1558123200; // MAINNET V3 chain fork (GMT: Friday, 17. May 2019 20:00:00) + nForkV4Time = 1569614400; // MAINNET V4 chain fork (GMT: Friday, 27. September 2019 20:00:00) + + devContributionAddress = "SdrdWNtjD7V6BSt3EyQZKCnZDkeE28cZhr"; + supplyIncreaseAddress = "SSGCEMb6xESgmuGXkx7yozGDxhVSXzBP3a"; + + // Modern Bitcoin Core parameters + nPruneAfterHeight = 100000; + m_assumed_blockchain_size = 4; + m_assumed_chain_state_size = 3; + fDefaultConsistencyChecks = false; + m_is_mockable_chain = false; + + checkpointData = { + { + // Add checkpoints as needed + } + }; + + chainTxData = ChainTxData{ + 0, // nTime + 0, // nTxCount + 0.0 // dTxRate + }; + } + + Network NetworkID() const override { return CChainParams::MAIN; } +}; + +/** + * Testnet + */ +class CTestNetParams : public CChainParams { +public: + CTestNetParams() + : m_chain_type(ChainType::TESTNET) + , strNetworkID("test") + , strDataDir("testnet") + { + + // Message start + pchMessageStart[0] = 0xa3; + pchMessageStart[1] = 0x2c; + pchMessageStart[2] = 0x44; + pchMessageStart[3] = 0xb4; + + vAlertPubKey = ParseHex("04e564bc9bf28e6d395cd89c4d2bdb235c3873f59b1330d2e6a30c6fa85d8a8637693ae367ce39c2fe0f4e8e3c7c3a34feb82305388f19030aa4fcd4955abeb810"); + + nDefaultPort = 37111; + nRPCPort = 36757; + nBIP44ID = 0x80000001; + + // PoS parameters + nLastPOWBlock = 20; + nFirstPosv2Block = 20; + nFirstPosv3Block = 500; + + // Proof limits + bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); + bnProofOfStakeLimit = CBigNum(~uint256(0) >> 20); + bnProofOfStakeLimitV2 = CBigNum(~uint256(0) >> 46); + + nStakeMinConfirmationsLegacy = 28; + nStakeMinConfirmations = 30; + + // Consensus parameters + consensus.hashGenesisBlock = uint256(); + consensus.nSubsidyHalvingInterval = 210000; + consensus.BIP34Height = 0; + consensus.BIP65Height = 0; + consensus.BIP66Height = 0; + consensus.CSVHeight = 1; + consensus.SegwitHeight = 0; + consensus.MinBIP9WarningHeight = 0; + consensus.powLimit = uint256S("0000000000000fffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.nPowTargetSpacing = 96; + consensus.nPowTargetTimespan = 24 * 60 * 60; + consensus.fPowAllowMinDifficultyBlocks = true; + consensus.fPowNoRetargeting = false; + consensus.nRuleChangeActivationThreshold = 1512; + consensus.nMinerConfirmationWindow = 2016; + + // Alias-specific consensus (stored in consensus params) + consensus.m_alias_mode = true; + consensus.nForkV2Time = 1532466000; // TESTNET V2 chain fork + consensus.nForkV3Time = 1546470000; // TESTNET V3 chain fork + consensus.nForkV4Time = 1567972800; // TESTNET V4 chain fork + consensus.nLastPOWBlock = 20; + consensus.nFirstPosv2Block = 20; + consensus.nFirstPosv3Block = 500; + consensus.m_min_ringsize = 10; + consensus.m_max_ringsize = 10; + consensus.m_max_anon_inputs = 32; + consensus.m_max_anon_output = 1000 * COIN; + consensus.nMinRCTOutputDepth = 12; + + // Genesis block + genesis = CreateAliasGenesisBlock(GENESIS_BLOCK_TIME, 20, bnProofOfWorkLimit.GetCompact()); + hashGenesisBlock = genesis.GetHash(); + consensus.hashGenesisBlock = hashGenesisBlock; + + assert(hashGenesisBlock == uint256("0x0a3e03a153b1713ebc1f03fefa5d013bba4d2677ae189fcb727396b98043d95c")); + + // Base58 prefixes + base58Prefixes[PUBKEY_ADDRESS] = std::vector(1, 127); + base58Prefixes[SCRIPT_ADDRESS] = std::vector(1, 196); + base58Prefixes[SECRET_KEY] = std::vector(1, 255); + base58Prefixes[STEALTH_ADDRESS] = std::vector(1, 40); + base58Prefixes[EXT_PUBLIC_KEY] = {0x76, 0xC0, 0xFD, 0xFB}; + base58Prefixes[EXT_SECRET_KEY] = {0x76, 0xC1, 0x07, 0x7A}; + base58Prefixes[EXT_KEY_HASH] = std::vector(1, 75); + base58Prefixes[EXT_ACC_HASH] = std::vector(1, 23); + base58Prefixes[EXT_PUBLIC_KEY_BTC] = {0x04, 0x35, 0x87, 0xCF}; + base58Prefixes[EXT_SECRET_KEY_BTC] = {0x04, 0x35, 0x83, 0x94}; + + convertSeeds(vFixedSeeds, pnTestnetSeed, ARRAYLEN(pnTestnetSeed), nDefaultPort); + + // Fork times + nForkV2Time = 1532466000; // TESTNET V2 chain fork + nForkV3Time = 1546470000; // TESTNET V3 chain fork + nForkV4Time = 1567972800; // TESTNET V4 chain fork + + devContributionAddress = "tSJoPZoXumJyDmGKYo9Y7SZkJvymESFYkD"; + supplyIncreaseAddress = devContributionAddress; + + // Modern Bitcoin Core parameters + nPruneAfterHeight = 1000; + m_assumed_blockchain_size = 1; + m_assumed_chain_state_size = 1; + fDefaultConsistencyChecks = false; + m_is_mockable_chain = true; + + checkpointData = { + { + // Add checkpoints as needed + } + }; + + chainTxData = ChainTxData{ + 0, // nTime + 0, // nTxCount + 0.0 // dTxRate + }; + } + + Network NetworkID() const override { return CChainParams::TESTNET; } +}; + +/** + * Regression test + */ +class CRegTestParams : public CTestNetParams { +public: + CRegTestParams() + : m_chain_type(ChainType::REGTEST) + , strNetworkID("regtest") + , strDataDir("regtest") + { + + nFirstPosv2Block = -1; + nFirstPosv3Block = -1; + + pchMessageStart[0] = 0x05; + pchMessageStart[1] = 0xc5; + pchMessageStart[2] = 0x04; + pchMessageStart[3] = 0x3a; + + bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1); + genesis = CreateAliasGenesisBlock(1479594600, 2, bnProofOfWorkLimit.GetCompact()); + hashGenesisBlock = genesis.GetHash(); + consensus.hashGenesisBlock = hashGenesisBlock; + + nDefaultPort = 18444; + consensus.fPowNoRetargeting = true; + consensus.fPowAllowMinDifficultyBlocks = true; + + assert(hashGenesisBlock == uint256("0x562dba63b74b056329585b9779306f3d3caf447b5df40fb088cebbfb31fd5d5d")); + + vSeeds.clear(); + fDefaultConsistencyChecks = true; + m_is_mockable_chain = true; + } + + bool RequireRPCPassword() const override { return false; } + Network NetworkID() const override { return CChainParams::REGTEST; } +}; + +// Global instances +static std::unique_ptr globalChainParams; + +static CMainParams mainParams; +static CTestNetParams testNetParams; +static CRegTestParams regTestParams; + +const CChainParams &Params() { + assert(globalChainParams); + return *globalChainParams; +} + +const CChainParams &TestNetParams() { + return testNetParams; +} + +const CChainParams &MainNetParams() { + return mainParams; +} + +void SelectParams(CChainParams::Network network) +{ + switch (network) + { + case CChainParams::MAIN: + globalChainParams = std::make_unique(); + break; + case CChainParams::TESTNET: + globalChainParams = std::make_unique(); + break; + case CChainParams::REGTEST: + globalChainParams = std::make_unique(); + break; + default: + assert(false && "Unimplemented network"); + return; + } +} + +bool SelectParamsFromCommandLine() +{ + bool fRegTest = GetBoolArg("-regtest", false); + bool fTestNet = GetBoolArg("-testnet", false); + + if (fTestNet && fRegTest) + { + return false; + } + + if (fRegTest) + { + SelectParams(CChainParams::REGTEST); + } else if (fTestNet) + { + SelectParams(CChainParams::TESTNET); + } else + { + SelectParams(CChainParams::MAIN); + } + + return true; +} + +std::unique_ptr CChainParams::Main() +{ + return std::make_unique(); +} + +std::unique_ptr CChainParams::TestNet() +{ + return std::make_unique(); +} + +std::unique_ptr CChainParams::RegTest() +{ + return std::make_unique(); +} + +std::optional GetNetworkForMagic(const MessageStartChars& pchMessageStart) +{ + if (pchMessageStart[0] == 0xb5 && pchMessageStart[1] == 0x22 && + pchMessageStart[2] == 0x5c && pchMessageStart[3] == 0xd3) { + return ChainType::MAIN; + } else if (pchMessageStart[0] == 0xa3 && pchMessageStart[1] == 0x2c && + pchMessageStart[2] == 0x44 && pchMessageStart[3] == 0xb4) { + return ChainType::TESTNET; + } else if (pchMessageStart[0] == 0x05 && pchMessageStart[1] == 0xc5 && + pchMessageStart[2] == 0x04 && pchMessageStart[3] == 0x3a) { + return ChainType::REGTEST; + } + return std::nullopt; +} + diff --git a/src/kernel/chainparams.h b/src/kernel/chainparams.h new file mode 100644 index 0000000000..6e5d273866 --- /dev/null +++ b/src/kernel/chainparams.h @@ -0,0 +1,228 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_CHAINPARAMS_H +#define BITCOIN_KERNEL_CHAINPARAMS_H + +#include +#include +#include // Alias uses CBlock from core.h +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class CBlockIndex; +class CAddress; + +struct CDNSSeedData { + std::string name, host; + CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} +}; + +typedef std::map MapCheckpoints; + +struct CCheckpointData { + MapCheckpoints mapCheckpoints; + + int GetHeight() const { + const auto& final_checkpoint = mapCheckpoints.rbegin(); + return final_checkpoint->first /* height */; + } +}; + +struct AssumeutxoHash : public BaseHash { + explicit AssumeutxoHash(const uint256& hash) : BaseHash(hash) {} +}; + +struct AssumeutxoData { + int height; + AssumeutxoHash hash_serialized; + unsigned int nChainTx; + uint256 blockhash; +}; + +struct ChainTxData { + int64_t nTime; + int64_t nTxCount; + double dTxRate; +}; + +/** + * CChainParams defines various tweakable parameters of a given instance of the + * Alias blockchain system. Modern structure with Alias-specific extensions. + */ +class CChainParams +{ +public: + enum Network { + MAIN, + TESTNET, + REGTEST, + MAX_NETWORK_TYPES + }; + + enum Base58Type { + PUBKEY_ADDRESS, + SCRIPT_ADDRESS, + SECRET_KEY, + STEALTH_ADDRESS, + EXT_PUBLIC_KEY, + EXT_SECRET_KEY, + EXT_KEY_HASH, + EXT_ACC_HASH, + EXT_PUBLIC_KEY_BTC, + EXT_SECRET_KEY_BTC, + MAX_BASE58_TYPES + }; + + const Consensus::Params& GetConsensus() const { return consensus; } + const MessageStartChars& MessageStart() const { return pchMessageStart; } + uint16_t GetDefaultPort() const { return nDefaultPort; } + + const CBlock& GenesisBlock() const { return genesis; } + bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } + bool IsTestChain() const { return m_chain_type != ChainType::MAIN; } + bool IsMockableChain() const { return m_is_mockable_chain; } + uint64_t PruneAfterHeight() const { return nPruneAfterHeight; } + uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; } + uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; } + bool MineBlocksOnDemand() const { return consensus.fPowNoRetargeting; } + std::string GetChainTypeString() const { return ChainTypeToString(m_chain_type); } + ChainType GetChainType() const { return m_chain_type; } + const std::vector& DNSSeeds() const { return vSeeds; } + const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } + const std::vector& FixedSeeds() const { return vFixedSeeds; } + const CCheckpointData& Checkpoints() const { return checkpointData; } + const ChainTxData& TxData() const { return chainTxData; } + + // Alias-specific methods (preserved from old structure) + const uint256& HashGenesisBlock() const { return hashGenesisBlock; } + const std::vector& AlertKey() const { return vAlertPubKey; } + int RPCPort() const { return nRPCPort; } + int BIP44ID() const { return nBIP44ID; } + int LastPOWBlock() const { return nLastPOWBlock; } + std::string NetworkIDString() const { return strNetworkID; } + const std::string& DataDir() const { return strDataDir; } + + // Alias PoS methods + bool IsProtocolV2(int nHeight) const { return nHeight > nFirstPosv2Block; } + bool IsProtocolV3(int nHeight) const { return nHeight > nFirstPosv3Block; } + + // Alias fork detection + bool IsForkV2(int64_t nTime) const { return nTime > nForkV2Time; } + bool IsForkV3(int64_t nTime) const { return nTime > nForkV3Time; } + bool IsForkV4(int64_t nTime) const { return nTime >= nForkV4Time; } + bool IsForkV4SupplyIncrease(const CBlockIndex* pindexPrev) const; + int GetForkId(int64_t nTime) const { + return (nTime >= nForkV4Time) ? 4 : (nTime > nForkV3Time) ? 3 : (nTime > nForkV2Time) ? 2 : 0; + } + + // Alias stake confirmation methods + int GetStakeMinConfirmations(int64_t nTime) const { + return IsForkV3(nTime) ? nStakeMinConfirmations : nStakeMinConfirmationsLegacy; + } + int GetAnonStakeMinConfirmations() const { return nStakeMinConfirmations; } + + // Alias reward methods + int64_t GetProofOfWorkReward(int nHeight, int64_t nFees) const; + int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) const; + int64_t GetProofOfAnonStakeReward(const CBlockIndex* pindexPrev, int64_t nFees) const; + + // Alias development fund addresses + const std::string GetDevContributionAddress() const { return devContributionAddress; } + const std::string GetSupplyIncreaseAddress() const { return supplyIncreaseAddress; } + + // Alias proof limits (using CBigNum for compatibility) + const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const CBigNum& ProofOfStakeLimit(int nHeight) const { + return IsProtocolV2(nHeight) ? bnProofOfStakeLimitV2 : bnProofOfStakeLimit; + } + const CBigNum BnProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const CBigNum BnProofOfStakeLimit() const { return bnProofOfStakeLimit; } + + // Network selection + virtual Network NetworkID() const = 0; + virtual bool RequireRPCPassword() const { return true; } + + static std::unique_ptr RegTest(); + static std::unique_ptr Main(); + static std::unique_ptr TestNet(); + +protected: + CChainParams() {} + + Consensus::Params consensus; + MessageStartChars pchMessageStart; + uint16_t nDefaultPort; + uint64_t nPruneAfterHeight; + uint64_t m_assumed_blockchain_size; + uint64_t m_assumed_chain_state_size; + std::vector vSeeds; + std::vector base58Prefixes[MAX_BASE58_TYPES]; + ChainType m_chain_type; + CBlock genesis; + std::vector vFixedSeeds; // Alias uses CAddress + bool fDefaultConsistencyChecks; + bool m_is_mockable_chain; + CCheckpointData checkpointData; + std::vector m_assumeutxo_data; + ChainTxData chainTxData; + + // Alias-specific members + uint256 hashGenesisBlock; + std::vector vAlertPubKey; + std::string strNetworkID; + int nRPCPort; + int nBIP44ID; + std::string strDataDir; + + // Alias PoS parameters + int nLastPOWBlock; + int nFirstPosv2Block; + int nFirstPosv3Block; + CBigNum bnProofOfWorkLimit; + CBigNum bnProofOfStakeLimit; + CBigNum bnProofOfStakeLimitV2; + int nStakeMinConfirmationsLegacy; + int nStakeMinConfirmations; + + // Alias fork times + int64_t nForkV2Time; + int64_t nForkV3Time; + int64_t nForkV4Time; + + // Alias development addresses + std::string devContributionAddress; + std::string supplyIncreaseAddress; + + // Alias stake rewards (externally set, referenced in reward functions) + // These are set in state.cpp and referenced via extern +}; + +// Global functions for backward compatibility +const CChainParams &Params(); +const CChainParams &TestNetParams(); +const CChainParams &MainNetParams(); +void SelectParams(CChainParams::Network network); +bool SelectParamsFromCommandLine(); + +std::optional GetNetworkForMagic(const MessageStartChars& pchMessageStart); + +#endif // BITCOIN_KERNEL_CHAINPARAMS_H + diff --git a/src/kernel/context.cpp b/src/kernel/context.cpp new file mode 100644 index 0000000000..5ea71bf935 --- /dev/null +++ b/src/kernel/context.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include // For LogPrintf +#include // May not exist in old codebase, will add if needed +#include // May not exist in old codebase, will add if needed + +#include + +namespace kernel { +Context::Context() +{ + // TODO: Implement SHA256AutoDetect and RandomInit when crypto/random modules are migrated + // For now, this is a placeholder that allows compilation + // std::string sha256_algo = SHA256AutoDetect(); + // LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); + // RandomInit(); + LogPrintf("Kernel context initialized\n"); +} +} // namespace kernel + diff --git a/src/kernel/context.h b/src/kernel/context.h new file mode 100644 index 0000000000..66cd2d602b --- /dev/null +++ b/src/kernel/context.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_CONTEXT_H +#define BITCOIN_KERNEL_CONTEXT_H + +namespace kernel { +//! Context struct holding the kernel library's logically global state, and +//! passed to external libbitcoin_kernel functions which need access to this +//! state. The kernel library API is a work in progress, so state organization +//! and member list will evolve over time. +//! +//! State stored directly in this struct should be simple. More complex state +//! should be stored to std::unique_ptr members pointing to opaque types. +struct Context { + Context(); +}; +} // namespace kernel + +#endif // BITCOIN_KERNEL_CONTEXT_H + diff --git a/src/kernel/messagestartchars.h b/src/kernel/messagestartchars.h new file mode 100644 index 0000000000..b6a081092f --- /dev/null +++ b/src/kernel/messagestartchars.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_KERNEL_MESSAGESTARTCHARS_H +#define BITCOIN_KERNEL_MESSAGESTARTCHARS_H + +#include +#include + +using MessageStartChars = std::array; + +#endif // BITCOIN_KERNEL_MESSAGESTARTCHARS_H + diff --git a/src/key.cpp b/src/key.cpp index ab6b8276c1..4a008cb936 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "key.h" #include "eckey.h" @@ -50,7 +53,14 @@ const unsigned char vchMaxModHalfOrder[32] = { 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 }; -const unsigned char vchZero[0] = {}; + +#ifdef _MSC_VER +#define vchZeroSize 1 +#else +#define vchZeroSize 0 +#endif + +const unsigned char vchZero[vchZeroSize] = {}; @@ -270,7 +280,7 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild assert(begin() + 32 == end()); BIP32Hash(cc, nChild, 0, begin(), out); }; - + memcpy(ccChild, out+32, 32); bool ret = TweakSecret((unsigned char*)keyChild.begin(), begin(), out); UnlockObject(out); @@ -401,7 +411,7 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { out.nDepth = nDepth + 1; CKeyID id = pubkey.GetID(); - + memcpy(&out.vchFingerprint[0], &id, 4); out.nChild = nChild; return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode); @@ -476,7 +486,7 @@ bool CExtKeyPair::Derive(CExtPubKey &out, unsigned int nChild) const }; if (!key.IsValid()) return false; - + out.nDepth = nDepth + 1; CKeyID id = pubkey.GetID(); memcpy(&out.vchFingerprint[0], &id, 4); @@ -484,7 +494,7 @@ bool CExtKeyPair::Derive(CExtPubKey &out, unsigned int nChild) const CKey tkey; if (!key.Derive(tkey, out.vchChainCode, nChild, vchChainCode)) return false; - + out.pubkey = tkey.GetPubKey(true); return true; }; @@ -493,7 +503,7 @@ bool CExtKeyPair::Derive(CKey &out, unsigned int nChild) const { if (!key.IsValid()) return false; - + unsigned char temp[32]; return key.Derive(out, temp, nChild, vchChainCode); }; @@ -507,7 +517,7 @@ bool CExtKeyPair::Derive(CPubKey &out, unsigned int nChild) const }; if (!key.IsValid()) return false; - + CKey tkey; if (!key.Derive(tkey, temp, nChild, vchChainCode)) return false; @@ -571,7 +581,7 @@ int CExtKeyPair::SetKeyCode(const unsigned char *pkey, const unsigned char *pcod bool ECC_InitSanityCheck() { EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1); - if(pkey == NULL) + if(pkey == nullptr) return false; EC_KEY_free(pkey); diff --git a/src/key.h b/src/key.h index 294f734c49..3d97ef1384 100644 --- a/src/key.h +++ b/src/key.h @@ -1,7 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_KEY_H #define BITCOIN_KEY_H @@ -76,7 +80,7 @@ class CPubKey { CPubKey(const std::vector &vch) { Set(vch.begin(), vch.end()); } - + CPubKey(const unsigned char* p, const int len) { if (len <= 65) @@ -150,7 +154,7 @@ class CPubKey { bool IsCompressed() const { return size() == 33; } - + bool SetZero() { memset(&vch[0], 0, 65); @@ -173,7 +177,7 @@ class CPubKey { // Derive BIP32 child pubkey. bool Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const; - + }; @@ -238,15 +242,15 @@ class CKey { fValid = false; } } - + void Clear() { memset(vch, 0, sizeof(vch)); fCompressed = true; fValid = false; }; - - + + void Set(const unsigned char *p, bool fCompressedIn) { if (Check(p)) { @@ -297,13 +301,13 @@ class CKey { // Derive BIP32 child key. bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const; - + /** * Verify thoroughly whether a private key and a public key match. * This is done using a different mechanism than just regenerating it. */ bool VerifyPubKey(const CPubKey& vchPubKey) const; - + // Load private key and check that public key matches. bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck); @@ -314,13 +318,13 @@ class CKey { { return 33; } - + template void Serialize(Stream &s, int nType, int nVersion) const { s.write((char*)vch, 32); s.write((char*)&fValid, 1); } - + template void Unserialize(Stream &s, int nType, int nVersion) { fCompressed = true; @@ -340,9 +344,9 @@ struct CExtPubKey { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.pubkey == b.pubkey; } - + bool IsValid() const { return pubkey.IsValid(); } - + CKeyID GetID() const { return pubkey.GetID(); } @@ -350,30 +354,30 @@ struct CExtPubKey { void Encode(unsigned char code[74]) const; void Decode(const unsigned char code[74]); bool Derive(CExtPubKey &out, unsigned int nChild) const; - - + + unsigned int GetSerializeSize(int nType, int nVersion) const { return 41 + pubkey.GetSerializeSize(nType, nVersion); } - + template void Serialize(Stream &s, int nType, int nVersion) const { s.write((char*)&nDepth, 1); s.write((char*)vchFingerprint, 4); s.write((char*)&nChild, 4); s.write((char*)vchChainCode, 32); - + pubkey.Serialize(s, nType, nVersion); } - + template void Unserialize(Stream &s, int nType, int nVersion) { s.read((char*)&nDepth, 1); s.read((char*)vchFingerprint, 4); s.read((char*)&nChild, 4); s.read((char*)vchChainCode, 32); - + pubkey.Unserialize(s, nType, nVersion); } }; @@ -389,7 +393,7 @@ struct CExtKey { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.key == b.key; } - + bool IsValid() const { return key.IsValid(); } void Encode(unsigned char code[74]) const; @@ -398,32 +402,32 @@ struct CExtKey { CExtPubKey Neutered() const; void SetMaster(const unsigned char *seed, unsigned int nSeedLen); int SetKeyCode(const unsigned char *pkey, const unsigned char *pcode); - + unsigned int GetSerializeSize(int nType, int nVersion) const { return 42 + (key.IsValid() ? 32 : 0); } - + template void Serialize(Stream &s, int nType, int nVersion) const { s.write((char*)&nDepth, 1); s.write((char*)vchFingerprint, 4); s.write((char*)&nChild, 4); s.write((char*)vchChainCode, 32); - + char fValid = key.IsValid(); s.write((char*)&fValid, 1); if (fValid) s.write((char*)key.begin(), 32); } - + template void Unserialize(Stream &s, int nType, int nVersion) { s.read((char*)&nDepth, 1); s.read((char*)vchFingerprint, 4); s.read((char*)&nChild, 4); s.read((char*)vchChainCode, 32); - + char tmp[33]; s.read((char*)tmp, 1); // key.IsValid() if (tmp[0]) @@ -444,7 +448,7 @@ class CExtKeyPair unsigned char vchChainCode[32]; CKey key; CPubKey pubkey; - + CExtKeyPair() {}; CExtKeyPair(CExtKey &vk) { @@ -455,8 +459,8 @@ class CExtKeyPair key = vk.key; pubkey = key.GetPubKey(); }; - - + + CExtKey GetExtKey() const { CExtKey vk; @@ -467,69 +471,69 @@ class CExtKeyPair vk.key = key; return vk; }; - + CKeyID GetID() const { return pubkey.GetID(); } - - + + bool operator <(const CExtKeyPair& y) const { return pubkey < y.pubkey; }; - + friend bool operator==(const CExtKeyPair &a, const CExtKeyPair &b) { return a.nDepth == b.nDepth && memcmp(&a.vchFingerprint[0], &b.vchFingerprint[0], 4) == 0 && a.nChild == b.nChild && memcmp(&a.vchChainCode[0], &b.vchChainCode[0], 32) == 0 && a.key == b.key && a.pubkey == b.pubkey ; } - + bool IsValidV() const { return key.IsValid(); } bool IsValidP() const { return pubkey.IsValid(); } void EncodeV(unsigned char code[74]) const; void DecodeV(const unsigned char code[74]); - + void EncodeP(unsigned char code[74]) const; void DecodeP(const unsigned char code[74]); - + bool Derive(CExtKey &out, unsigned int nChild) const; bool Derive(CExtPubKey &out, unsigned int nChild) const; bool Derive(CKey &out, unsigned int nChild) const; bool Derive(CPubKey &out, unsigned int nChild) const; - + CExtPubKey GetExtPubKey() const; CExtKeyPair Neutered() const; void SetMaster(const unsigned char *seed, unsigned int nSeedLen); int SetKeyCode(const unsigned char *pkey, const unsigned char *pcode); - + unsigned int GetSerializeSize(int nType, int nVersion) const { return 42 + (key.IsValid() ? 32 : 0) + pubkey.GetSerializeSize(nType, nVersion); } - + template void Serialize(Stream &s, int nType, int nVersion) const { s.write((char*)&nDepth, 1); s.write((char*)vchFingerprint, 4); s.write((char*)&nChild, 4); s.write((char*)vchChainCode, 32); - + char fValid = key.IsValid(); s.write((char*)&fValid, 1); if (fValid) s.write((char*)key.begin(), 32); - + pubkey.Serialize(s, nType, nVersion); } - + template void Unserialize(Stream &s, int nType, int nVersion) { s.read((char*)&nDepth, 1); s.read((char*)vchFingerprint, 4); s.read((char*)&nChild, 4); s.read((char*)vchChainCode, 32); - + char tmp[33]; s.read((char*)tmp, 1); // key.IsValid() if (tmp[0]) diff --git a/src/keystore.cpp b/src/keystore.cpp index 8fea421989..98773fa758 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "keystore.h" #include "script.h" diff --git a/src/keystore.h b/src/keystore.h index 57955dd647..0aa8925e6f 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -1,13 +1,20 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_KEYSTORE_H #define BITCOIN_KEYSTORE_H #include "key.h" #include "sync.h" + +#ifndef Q_MOC_RUN #include +#endif class CScript; class CScriptID; @@ -48,8 +55,8 @@ class CBasicKeyStore : public CKeyStore ScriptMap mapScripts; public: - bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); - bool HaveKey(const CKeyID &address) const + bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override; + bool HaveKey(const CKeyID &address) const override { bool result; { @@ -58,7 +65,7 @@ class CBasicKeyStore : public CKeyStore } return result; } - void GetKeys(std::set &setAddress) const + void GetKeys(std::set &setAddress) const override { setAddress.clear(); { @@ -71,7 +78,7 @@ class CBasicKeyStore : public CKeyStore } } } - bool GetKey(const CKeyID &address, CKey &keyOut) const + bool GetKey(const CKeyID &address, CKey &keyOut) const override { { LOCK(cs_KeyStore); @@ -84,9 +91,9 @@ class CBasicKeyStore : public CKeyStore } return false; } - virtual bool AddCScript(const CScript& redeemScript); - virtual bool HaveCScript(const CScriptID &hash) const; - virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; + bool AddCScript(const CScript& redeemScript) override; + bool HaveCScript(const CScriptID &hash) const override; + bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const override; }; typedef std::map > > CryptedKeyMap; diff --git a/src/leveldb/.gitignore b/src/leveldb/.gitignore deleted file mode 100644 index 71d87a4eeb..0000000000 --- a/src/leveldb/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -build_config.mk -*.a -*.o -*.dylib* -*.so -*.so.* -*_test -db_bench -leveldbutil -Release -Debug -Benchmark -vs2010.* diff --git a/src/leveldb/AUTHORS b/src/leveldb/AUTHORS deleted file mode 100644 index 2439d7a452..0000000000 --- a/src/leveldb/AUTHORS +++ /dev/null @@ -1,12 +0,0 @@ -# Names should be added to this file like so: -# Name or Organization - -Google Inc. - -# Initial version authors: -Jeffrey Dean -Sanjay Ghemawat - -# Partial list of contributors: -Kevin Regan -Johan Bilien diff --git a/src/leveldb/CONTRIBUTING.md b/src/leveldb/CONTRIBUTING.md deleted file mode 100644 index cd600ff46b..0000000000 --- a/src/leveldb/CONTRIBUTING.md +++ /dev/null @@ -1,36 +0,0 @@ -# Contributing - -We'd love to accept your code patches! However, before we can take them, we -have to jump a couple of legal hurdles. - -## Contributor License Agreements - -Please fill out either the individual or corporate Contributor License -Agreement as appropriate. - -* If you are an individual writing original source code and you're sure you -own the intellectual property, then sign an [individual CLA](https://developers.google.com/open-source/cla/individual). -* If you work for a company that wants to allow you to contribute your work, -then sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). - -Follow either of the two links above to access the appropriate CLA and -instructions for how to sign and return it. - -## Submitting a Patch - -1. Sign the contributors license agreement above. -2. Decide which code you want to submit. A submission should be a set of changes -that addresses one issue in the [issue tracker](https://github.com/google/leveldb/issues). -Please don't mix more than one logical change per submission, because it makes -the history hard to follow. If you want to make a change -(e.g. add a sample or feature) that doesn't have a corresponding issue in the -issue tracker, please create one. -3. **Submitting**: When you are ready to submit, send us a Pull Request. Be -sure to include the issue number you fixed and the name you used to sign -the CLA. - -## Writing Code ## - -If your contribution contains code, please make sure that it follows -[the style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml). -Otherwise we will have to ask you to make changes, and that's no fun for anyone. diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile deleted file mode 100644 index 2bd2cadcdd..0000000000 --- a/src/leveldb/Makefile +++ /dev/null @@ -1,227 +0,0 @@ -# Copyright (c) 2011 The LevelDB Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. See the AUTHORS file for names of contributors. - -#----------------------------------------------- -# Uncomment exactly one of the lines labelled (A), (B), and (C) below -# to switch between compilation modes. - -# (A) Production use (optimized mode) -OPT ?= -O2 -DNDEBUG -# (B) Debug mode, w/ full line-level debugging symbols -# OPT ?= -g2 -# (C) Profiling mode: opt, but w/debugging symbols -# OPT ?= -O2 -g2 -DNDEBUG -#----------------------------------------------- - -# detect what platform we're building on -$(shell CC="$(CC)" CXX="$(CXX)" TARGET_OS="$(TARGET_OS)" \ - ./build_detect_platform build_config.mk ./) -# this file is generated by the previous line to set build flags and sources -include build_config.mk - -CFLAGS += -I. -I./include $(PLATFORM_CCFLAGS) $(OPT) -CXXFLAGS += -I. -I./include $(PLATFORM_CXXFLAGS) $(OPT) - -LDFLAGS += $(PLATFORM_LDFLAGS) -LIBS += $(PLATFORM_LIBS) - -LIBOBJECTS = $(SOURCES:.cc=.o) -MEMENVOBJECTS = $(MEMENV_SOURCES:.cc=.o) - -TESTUTIL = ./util/testutil.o -TESTHARNESS = ./util/testharness.o $(TESTUTIL) - -# Note: iOS should probably be using libtool, not ar. -ifeq ($(PLATFORM), IOS) -AR=xcrun ar -endif - -TESTS = \ - arena_test \ - autocompact_test \ - bloom_test \ - c_test \ - cache_test \ - coding_test \ - corruption_test \ - crc32c_test \ - db_test \ - dbformat_test \ - env_test \ - filename_test \ - filter_block_test \ - hash_test \ - issue178_test \ - issue200_test \ - log_test \ - memenv_test \ - skiplist_test \ - table_test \ - version_edit_test \ - version_set_test \ - write_batch_test - -PROGRAMS = db_bench leveldbutil $(TESTS) -BENCHMARKS = db_bench_sqlite3 db_bench_tree_db - -LIBRARY = libleveldb.a -MEMENVLIBRARY = libmemenv.a - -default: all - -# Should we build shared libraries? -ifneq ($(PLATFORM_SHARED_EXT),) - -ifneq ($(PLATFORM_SHARED_VERSIONED),true) -SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) -SHARED2 = $(SHARED1) -SHARED3 = $(SHARED1) -SHARED = $(SHARED1) -else -# Update db.h if you change these. -SHARED_MAJOR = 1 -SHARED_MINOR = 18 -SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT) -SHARED2 = $(SHARED1).$(SHARED_MAJOR) -SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR) -SHARED = $(SHARED1) $(SHARED2) $(SHARED3) -$(SHARED1): $(SHARED3) - ln -fs $(SHARED3) $(SHARED1) -$(SHARED2): $(SHARED3) - ln -fs $(SHARED3) $(SHARED2) -endif - -$(SHARED3): - $(CXX) $(LDFLAGS) $(PLATFORM_SHARED_LDFLAGS)$(SHARED2) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(SOURCES) -o $(SHARED3) $(LIBS) - -endif # PLATFORM_SHARED_EXT - -all: $(SHARED) $(LIBRARY) - -check: all $(PROGRAMS) $(TESTS) - for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done - -clean: - -rm -f $(PROGRAMS) $(BENCHMARKS) $(LIBRARY) $(SHARED) $(MEMENVLIBRARY) */*.o */*/*.o ios-x86/*/*.o ios-arm/*/*.o build_config.mk - -rm -rf ios-x86/* ios-arm/* - -$(LIBRARY): $(LIBOBJECTS) - rm -f $@ - $(AR) -rs $@ $(LIBOBJECTS) - -db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) - $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS) - -db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) - $(CXX) $(LDFLAGS) doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lsqlite3 $(LIBS) - -db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) - $(CXX) $(LDFLAGS) doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@ -lkyotocabinet $(LIBS) - -leveldbutil: db/leveldb_main.o $(LIBOBJECTS) - $(CXX) $(LDFLAGS) db/leveldb_main.o $(LIBOBJECTS) -o $@ $(LIBS) - -arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -autocompact_test: db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/autocompact_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -bloom_test: util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/bloom_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -hash_test: util/hash_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) util/hash_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -issue178_test: issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -issue200_test: issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) - $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) - -$(MEMENVLIBRARY) : $(MEMENVOBJECTS) - rm -f $@ - $(AR) -rs $@ $(MEMENVOBJECTS) - -memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) - $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS) - -ifeq ($(PLATFORM), IOS) -# For iOS, create universal object files to be used on both the simulator and -# a device. -PLATFORMSROOT=/Applications/Xcode.app/Contents/Developer/Platforms -SIMULATORROOT=$(PLATFORMSROOT)/iPhoneSimulator.platform/Developer -DEVICEROOT=$(PLATFORMSROOT)/iPhoneOS.platform/Developer -IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBundleShortVersionString) -IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 - -.cc.o: - mkdir -p ios-x86/$(dir $@) - xcrun -sdk iphonesimulator $(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ - mkdir -p ios-arm/$(dir $@) - xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ - xcrun lipo ios-x86/$@ ios-arm/$@ -create -output $@ - -.c.o: - mkdir -p ios-x86/$(dir $@) - xcrun -sdk iphonesimulator $(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -arch x86_64 -c $< -o ios-x86/$@ - mkdir -p ios-arm/$(dir $@) - xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk $(IOSARCH) -c $< -o ios-arm/$@ - xcrun lipo ios-x86/$@ ios-arm/$@ -create -output $@ - -else -.cc.o: - $(CXX) $(CXXFLAGS) -c $< -o $@ - -.c.o: - $(CC) $(CFLAGS) -c $< -o $@ -endif diff --git a/src/leveldb/NEWS b/src/leveldb/NEWS deleted file mode 100644 index 3fd99242d7..0000000000 --- a/src/leveldb/NEWS +++ /dev/null @@ -1,17 +0,0 @@ -Release 1.2 2011-05-16 ----------------------- - -Fixes for larger databases (tested up to one billion 100-byte entries, -i.e., ~100GB). - -(1) Place hard limit on number of level-0 files. This fixes errors -of the form "too many open files". - -(2) Fixed memtable management. Before the fix, a heavy write burst -could cause unbounded memory usage. - -A fix for a logging bug where the reader would incorrectly complain -about corruption. - -Allow public access to WriteBatch contents so that users can easily -wrap a DB. diff --git a/src/leveldb/README b/src/leveldb/README deleted file mode 100644 index 3618adeeed..0000000000 --- a/src/leveldb/README +++ /dev/null @@ -1,51 +0,0 @@ -leveldb: A key-value store -Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) - -The code under this directory implements a system for maintaining a -persistent key/value store. - -See doc/index.html for more explanation. -See doc/impl.html for a brief overview of the implementation. - -The public interface is in include/*.h. Callers should not include or -rely on the details of any other header files in this package. Those -internal APIs may be changed without warning. - -Guide to header files: - -include/db.h - Main interface to the DB: Start here - -include/options.h - Control over the behavior of an entire database, and also - control over the behavior of individual reads and writes. - -include/comparator.h - Abstraction for user-specified comparison function. If you want - just bytewise comparison of keys, you can use the default comparator, - but clients can write their own comparator implementations if they - want custom ordering (e.g. to handle different character - encodings, etc.) - -include/iterator.h - Interface for iterating over data. You can get an iterator - from a DB object. - -include/write_batch.h - Interface for atomically applying multiple updates to a database. - -include/slice.h - A simple module for maintaining a pointer and a length into some - other byte array. - -include/status.h - Status is returned from many of the public interfaces and is used - to report success and various kinds of errors. - -include/env.h - Abstraction of the OS environment. A posix implementation of - this interface is in util/env_posix.cc - -include/table.h -include/table_builder.h - Lower-level modules that most clients probably won't use directly diff --git a/src/leveldb/README.md b/src/leveldb/README.md deleted file mode 100644 index 480affb5ca..0000000000 --- a/src/leveldb/README.md +++ /dev/null @@ -1,138 +0,0 @@ -**LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.** - -Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) - -# Features - * Keys and values are arbitrary byte arrays. - * Data is stored sorted by key. - * Callers can provide a custom comparison function to override the sort order. - * The basic operations are `Put(key,value)`, `Get(key)`, `Delete(key)`. - * Multiple changes can be made in one atomic batch. - * Users can create a transient snapshot to get a consistent view of data. - * Forward and backward iteration is supported over the data. - * Data is automatically compressed using the [Snappy compression library](http://code.google.com/p/snappy). - * External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions. - * [Detailed documentation](http://htmlpreview.github.io/?https://github.com/google/leveldb/blob/master/doc/index.html) about how to use the library is included with the source code. - - -# Limitations - * This is not a SQL database. It does not have a relational data model, it does not support SQL queries, and it has no support for indexes. - * Only a single process (possibly multi-threaded) can access a particular database at a time. - * There is no client-server support builtin to the library. An application that needs such support will have to wrap their own server around the library. - -# Performance - -Here is a performance report (with explanations) from the run of the -included db_bench program. The results are somewhat noisy, but should -be enough to get a ballpark performance estimate. - -## Setup - -We use a database with a million entries. Each entry has a 16 byte -key, and a 100 byte value. Values used by the benchmark compress to -about half their original size. - - LevelDB: version 1.1 - Date: Sun May 1 12:11:26 2011 - CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz - CPUCache: 4096 KB - Keys: 16 bytes each - Values: 100 bytes each (50 bytes after compression) - Entries: 1000000 - Raw Size: 110.6 MB (estimated) - File Size: 62.9 MB (estimated) - -## Write performance - -The "fill" benchmarks create a brand new database, in either -sequential, or random order. The "fillsync" benchmark flushes data -from the operating system to the disk after every operation; the other -write operations leave the data sitting in the operating system buffer -cache for a while. The "overwrite" benchmark does random writes that -update existing keys in the database. - - fillseq : 1.765 micros/op; 62.7 MB/s - fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops) - fillrandom : 2.460 micros/op; 45.0 MB/s - overwrite : 2.380 micros/op; 46.5 MB/s - -Each "op" above corresponds to a write of a single key/value pair. -I.e., a random write benchmark goes at approximately 400,000 writes per second. - -Each "fillsync" operation costs much less (0.3 millisecond) -than a disk seek (typically 10 milliseconds). We suspect that this is -because the hard disk itself is buffering the update in its memory and -responding before the data has been written to the platter. This may -or may not be safe based on whether or not the hard disk has enough -power to save its memory in the event of a power failure. - -## Read performance - -We list the performance of reading sequentially in both the forward -and reverse direction, and also the performance of a random lookup. -Note that the database created by the benchmark is quite small. -Therefore the report characterizes the performance of leveldb when the -working set fits in memory. The cost of reading a piece of data that -is not present in the operating system buffer cache will be dominated -by the one or two disk seeks needed to fetch the data from disk. -Write performance will be mostly unaffected by whether or not the -working set fits in memory. - - readrandom : 16.677 micros/op; (approximately 60,000 reads per second) - readseq : 0.476 micros/op; 232.3 MB/s - readreverse : 0.724 micros/op; 152.9 MB/s - -LevelDB compacts its underlying storage data in the background to -improve read performance. The results listed above were done -immediately after a lot of random writes. The results after -compactions (which are usually triggered automatically) are better. - - readrandom : 11.602 micros/op; (approximately 85,000 reads per second) - readseq : 0.423 micros/op; 261.8 MB/s - readreverse : 0.663 micros/op; 166.9 MB/s - -Some of the high cost of reads comes from repeated decompression of blocks -read from disk. If we supply enough cache to the leveldb so it can hold the -uncompressed blocks in memory, the read performance improves again: - - readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) - readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) - -## Repository contents - -See doc/index.html for more explanation. See doc/impl.html for a brief overview of the implementation. - -The public interface is in include/*.h. Callers should not include or -rely on the details of any other header files in this package. Those -internal APIs may be changed without warning. - -Guide to header files: - -* **include/db.h**: Main interface to the DB: Start here - -* **include/options.h**: Control over the behavior of an entire database, -and also control over the behavior of individual reads and writes. - -* **include/comparator.h**: Abstraction for user-specified comparison function. -If you want just bytewise comparison of keys, you can use the default -comparator, but clients can write their own comparator implementations if they -want custom ordering (e.g. to handle different character encodings, etc.) - -* **include/iterator.h**: Interface for iterating over data. You can get -an iterator from a DB object. - -* **include/write_batch.h**: Interface for atomically applying multiple -updates to a database. - -* **include/slice.h**: A simple module for maintaining a pointer and a -length into some other byte array. - -* **include/status.h**: Status is returned from many of the public interfaces -and is used to report success and various kinds of errors. - -* **include/env.h**: -Abstraction of the OS environment. A posix implementation of this interface is -in util/env_posix.cc - -* **include/table.h, include/table_builder.h**: Lower-level modules that most -clients probably won't use directly diff --git a/src/leveldb/TODO b/src/leveldb/TODO deleted file mode 100644 index e603c07137..0000000000 --- a/src/leveldb/TODO +++ /dev/null @@ -1,14 +0,0 @@ -ss -- Stats - -db -- Maybe implement DB::BulkDeleteForRange(start_key, end_key) - that would blow away files whose ranges are entirely contained - within [start_key..end_key]? For Chrome, deletion of obsolete - object stores, etc. can be done in the background anyway, so - probably not that important. -- There have been requests for MultiGet. - -After a range is completely deleted, what gets rid of the -corresponding files if we do no future changes to that range. Make -the conditions for triggering compactions fire in more situations? diff --git a/src/leveldb/WINDOWS.md b/src/leveldb/WINDOWS.md deleted file mode 100644 index 5b76c2448f..0000000000 --- a/src/leveldb/WINDOWS.md +++ /dev/null @@ -1,39 +0,0 @@ -# Building LevelDB On Windows - -## Prereqs - -Install the [Windows Software Development Kit version 7.1](http://www.microsoft.com/downloads/dlx/en-us/listdetailsview.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b). - -Download and extract the [Snappy source distribution](http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz) - -1. Open the "Windows SDK 7.1 Command Prompt" : - Start Menu -> "Microsoft Windows SDK v7.1" > "Windows SDK 7.1 Command Prompt" -2. Change the directory to the leveldb project - -## Building the Static lib - -* 32 bit Version - - setenv /x86 - msbuild.exe /p:Configuration=Release /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5 - -* 64 bit Version - - setenv /x64 - msbuild.exe /p:Configuration=Release /p:Platform=x64 /p:Snappy=..\snappy-1.0.5 - - -## Building and Running the Benchmark app - -* 32 bit Version - - setenv /x86 - msbuild.exe /p:Configuration=Benchmark /p:Platform=Win32 /p:Snappy=..\snappy-1.0.5 - Benchmark\leveldb.exe - -* 64 bit Version - - setenv /x64 - msbuild.exe /p:Configuration=Benchmark /p:Platform=x64 /p:Snappy=..\snappy-1.0.5 - x64\Benchmark\leveldb.exe - diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform deleted file mode 100755 index a1101c1bda..0000000000 --- a/src/leveldb/build_detect_platform +++ /dev/null @@ -1,231 +0,0 @@ -#!/bin/sh -# -# Detects OS we're compiling on and outputs a file specified by the first -# argument, which in turn gets read while processing Makefile. -# -# The output will set the following variables: -# CC C Compiler path -# CXX C++ Compiler path -# PLATFORM_LDFLAGS Linker flags -# PLATFORM_LIBS Libraries flags -# PLATFORM_SHARED_EXT Extension for shared libraries -# PLATFORM_SHARED_LDFLAGS Flags for building shared library -# This flag is embedded just before the name -# of the shared library without intervening spaces -# PLATFORM_SHARED_CFLAGS Flags for compiling objects for shared library -# PLATFORM_CCFLAGS C compiler flags -# PLATFORM_CXXFLAGS C++ compiler flags. Will contain: -# PLATFORM_SHARED_VERSIONED Set to 'true' if platform supports versioned -# shared libraries, empty otherwise. -# -# The PLATFORM_CCFLAGS and PLATFORM_CXXFLAGS might include the following: -# -# -DLEVELDB_ATOMIC_PRESENT if is present -# -DLEVELDB_PLATFORM_POSIX for Posix-based platforms -# -DSNAPPY if the Snappy library is present -# - -OUTPUT=$1 -PREFIX=$2 -if test -z "$OUTPUT" || test -z "$PREFIX"; then - echo "usage: $0 " >&2 - exit 1 -fi - -# Delete existing output, if it exists -rm -f $OUTPUT -touch $OUTPUT - -if test -z "$CC"; then - CC=cc -fi - -if test -z "$CXX"; then - CXX=g++ -fi - -if test -z "$TMPDIR"; then - TMPDIR=/tmp -fi - -# Detect OS -if test -z "$TARGET_OS"; then - TARGET_OS=`uname -s` -fi - -COMMON_FLAGS= -CROSS_COMPILE= -PLATFORM_CCFLAGS= -PLATFORM_CXXFLAGS= -PLATFORM_LDFLAGS= -PLATFORM_LIBS= -PLATFORM_SHARED_EXT="so" -PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl," -PLATFORM_SHARED_CFLAGS="-fPIC" -PLATFORM_SHARED_VERSIONED=true - -MEMCMP_FLAG= -if [ "$CXX" = "g++" ]; then - # Use libc's memcmp instead of GCC's memcmp. This results in ~40% - # performance improvement on readrandom under gcc 4.4.3 on Linux/x86. - MEMCMP_FLAG="-fno-builtin-memcmp" -fi - -case "$TARGET_OS" in - CYGWIN_*) - PLATFORM=OS_LINUX - COMMON_FLAGS="$MEMCMP_FLAG -lpthread -DOS_LINUX -DCYGWIN" - PLATFORM_LDFLAGS="-lpthread" - PORT_FILE=port/port_posix.cc - ;; - Darwin) - PLATFORM=OS_MACOSX - COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX" - PLATFORM_SHARED_EXT=dylib - [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` - PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name $INSTALL_PATH/" - PORT_FILE=port/port_posix.cc - ;; - Linux) - PLATFORM=OS_LINUX - COMMON_FLAGS="$MEMCMP_FLAG -pthread -DOS_LINUX" - PLATFORM_LDFLAGS="-pthread" - PORT_FILE=port/port_posix.cc - ;; - SunOS) - PLATFORM=OS_SOLARIS - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_SOLARIS" - PLATFORM_LIBS="-lpthread -lrt" - PORT_FILE=port/port_posix.cc - ;; - FreeBSD) - PLATFORM=OS_FREEBSD - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_FREEBSD" - PLATFORM_LIBS="-lpthread" - PORT_FILE=port/port_posix.cc - ;; - GNU/kFreeBSD) - PLATFORM=OS_KFREEBSD - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD" - PLATFORM_LIBS="-lpthread" - PORT_FILE=port/port_posix.cc - ;; - NetBSD) - PLATFORM=OS_NETBSD - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD" - PLATFORM_LIBS="-lpthread -lgcc_s" - PORT_FILE=port/port_posix.cc - ;; - OpenBSD) - PLATFORM=OS_OPENBSD - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_OPENBSD" - PLATFORM_LDFLAGS="-pthread" - PORT_FILE=port/port_posix.cc - ;; - DragonFly) - PLATFORM=OS_DRAGONFLYBSD - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_DRAGONFLYBSD" - PLATFORM_LIBS="-lpthread" - PORT_FILE=port/port_posix.cc - ;; - OS_ANDROID_CROSSCOMPILE) - PLATFORM=OS_ANDROID - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX" - PLATFORM_LDFLAGS="" # All pthread features are in the Android C library - PORT_FILE=port/port_posix.cc - CROSS_COMPILE=true - ;; - HP-UX) - PLATFORM=OS_HPUX - COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_HPUX" - PLATFORM_LDFLAGS="-pthread" - PORT_FILE=port/port_posix.cc - # man ld: +h internal_name - PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl," - ;; - IOS) - PLATFORM=IOS - COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX" - [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` - PORT_FILE=port/port_posix.cc - PLATFORM_SHARED_EXT= - PLATFORM_SHARED_LDFLAGS= - PLATFORM_SHARED_CFLAGS= - PLATFORM_SHARED_VERSIONED= - ;; - OS_WINDOWS_CROSSCOMPILE | NATIVE_WINDOWS) - PLATFORM=OS_WINDOWS - COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1" - PLATFORM_SOURCES="util/env_win.cc" - PLATFORM_LIBS="-lshlwapi" - PORT_FILE=port/port_win.cc - CROSS_COMPILE=true - ;; - *) - echo "Unknown platform!" >&2 - exit 1 -esac - -# We want to make a list of all cc files within util, db, table, and helpers -# except for the test and benchmark files. By default, find will output a list -# of all files matching either rule, so we need to append -print to make the -# prune take effect. -DIRS="$PREFIX/db $PREFIX/util $PREFIX/table" - -set -f # temporarily disable globbing so that our patterns aren't expanded -PRUNE_TEST="-name *test*.cc -prune" -PRUNE_BENCH="-name *_bench.cc -prune" -PRUNE_TOOL="-name leveldb_main.cc -prune" -PORTABLE_FILES=`find $DIRS $PRUNE_TEST -o $PRUNE_BENCH -o $PRUNE_TOOL -o -name '*.cc' -print | sort | sed "s,^$PREFIX/,," | tr "\n" " "` - -set +f # re-enable globbing - -# The sources consist of the portable files, plus the platform-specific port -# file. -echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT -echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT - -if [ "$CROSS_COMPILE" = "true" ]; then - # Cross-compiling; do not try any compilation tests. - true -else - CXXOUTPUT="${TMPDIR}/leveldb_build_detect_platform-cxx.$$" - - # If -std=c++0x works, use as fallback for when memory barriers - # are not available. - $CXX $CXXFLAGS -std=c++0x -x c++ - -o $CXXOUTPUT 2>/dev/null < - int main() {} -EOF - if [ "$?" = 0 ]; then - COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX -DLEVELDB_ATOMIC_PRESENT" - PLATFORM_CXXFLAGS="-std=c++0x" - else - COMMON_FLAGS="$COMMON_FLAGS -DLEVELDB_PLATFORM_POSIX" - fi - - # Test whether tcmalloc is available - $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -ltcmalloc 2>/dev/null </dev/null -fi - -PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS" -PLATFORM_CXXFLAGS="$PLATFORM_CXXFLAGS $COMMON_FLAGS" - -echo "CC=$CC" >> $OUTPUT -echo "CXX=$CXX" >> $OUTPUT -echo "PLATFORM=$PLATFORM" >> $OUTPUT -echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT -echo "PLATFORM_LIBS=$PLATFORM_LIBS" >> $OUTPUT -echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT -echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT -echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT -echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT -echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT -echo "PLATFORM_SHARED_VERSIONED=$PLATFORM_SHARED_VERSIONED" >> $OUTPUT diff --git a/src/leveldb/db/autocompact_test.cc b/src/leveldb/db/autocompact_test.cc deleted file mode 100644 index d20a2362c3..0000000000 --- a/src/leveldb/db/autocompact_test.cc +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/db.h" -#include "db/db_impl.h" -#include "leveldb/cache.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -class AutoCompactTest { - public: - std::string dbname_; - Cache* tiny_cache_; - Options options_; - DB* db_; - - AutoCompactTest() { - dbname_ = test::TmpDir() + "/autocompact_test"; - tiny_cache_ = NewLRUCache(100); - options_.block_cache = tiny_cache_; - DestroyDB(dbname_, options_); - options_.create_if_missing = true; - options_.compression = kNoCompression; - ASSERT_OK(DB::Open(options_, dbname_, &db_)); - } - - ~AutoCompactTest() { - delete db_; - DestroyDB(dbname_, Options()); - delete tiny_cache_; - } - - std::string Key(int i) { - char buf[100]; - snprintf(buf, sizeof(buf), "key%06d", i); - return std::string(buf); - } - - uint64_t Size(const Slice& start, const Slice& limit) { - Range r(start, limit); - uint64_t size; - db_->GetApproximateSizes(&r, 1, &size); - return size; - } - - void DoReads(int n); -}; - -static const int kValueSize = 200 * 1024; -static const int kTotalSize = 100 * 1024 * 1024; -static const int kCount = kTotalSize / kValueSize; - -// Read through the first n keys repeatedly and check that they get -// compacted (verified by checking the size of the key space). -void AutoCompactTest::DoReads(int n) { - std::string value(kValueSize, 'x'); - DBImpl* dbi = reinterpret_cast(db_); - - // Fill database - for (int i = 0; i < kCount; i++) { - ASSERT_OK(db_->Put(WriteOptions(), Key(i), value)); - } - ASSERT_OK(dbi->TEST_CompactMemTable()); - - // Delete everything - for (int i = 0; i < kCount; i++) { - ASSERT_OK(db_->Delete(WriteOptions(), Key(i))); - } - ASSERT_OK(dbi->TEST_CompactMemTable()); - - // Get initial measurement of the space we will be reading. - const int64_t initial_size = Size(Key(0), Key(n)); - const int64_t initial_other_size = Size(Key(n), Key(kCount)); - - // Read until size drops significantly. - std::string limit_key = Key(n); - for (int read = 0; true; read++) { - ASSERT_LT(read, 100) << "Taking too long to compact"; - Iterator* iter = db_->NewIterator(ReadOptions()); - for (iter->SeekToFirst(); - iter->Valid() && iter->key().ToString() < limit_key; - iter->Next()) { - // Drop data - } - delete iter; - // Wait a little bit to allow any triggered compactions to complete. - Env::Default()->SleepForMicroseconds(1000000); - uint64_t size = Size(Key(0), Key(n)); - fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n", - read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0); - if (size <= initial_size/10) { - break; - } - } - - // Verify that the size of the key space not touched by the reads - // is pretty much unchanged. - const int64_t final_other_size = Size(Key(n), Key(kCount)); - ASSERT_LE(final_other_size, initial_other_size + 1048576); - ASSERT_GE(final_other_size, initial_other_size/5 - 1048576); -} - -TEST(AutoCompactTest, ReadAll) { - DoReads(kCount); -} - -TEST(AutoCompactTest, ReadHalf) { - DoReads(kCount/2); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/builder.cc b/src/leveldb/db/builder.cc deleted file mode 100644 index f419882197..0000000000 --- a/src/leveldb/db/builder.cc +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/builder.h" - -#include "db/filename.h" -#include "db/dbformat.h" -#include "db/table_cache.h" -#include "db/version_edit.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "leveldb/iterator.h" - -namespace leveldb { - -Status BuildTable(const std::string& dbname, - Env* env, - const Options& options, - TableCache* table_cache, - Iterator* iter, - FileMetaData* meta) { - Status s; - meta->file_size = 0; - iter->SeekToFirst(); - - std::string fname = TableFileName(dbname, meta->number); - if (iter->Valid()) { - WritableFile* file; - s = env->NewWritableFile(fname, &file); - if (!s.ok()) { - return s; - } - - TableBuilder* builder = new TableBuilder(options, file); - meta->smallest.DecodeFrom(iter->key()); - for (; iter->Valid(); iter->Next()) { - Slice key = iter->key(); - meta->largest.DecodeFrom(key); - builder->Add(key, iter->value()); - } - - // Finish and check for builder errors - if (s.ok()) { - s = builder->Finish(); - if (s.ok()) { - meta->file_size = builder->FileSize(); - assert(meta->file_size > 0); - } - } else { - builder->Abandon(); - } - delete builder; - - // Finish and check for file errors - if (s.ok()) { - s = file->Sync(); - } - if (s.ok()) { - s = file->Close(); - } - delete file; - file = NULL; - - if (s.ok()) { - // Verify that the table is usable - Iterator* it = table_cache->NewIterator(ReadOptions(), - meta->number, - meta->file_size); - s = it->status(); - delete it; - } - } - - // Check for input iterator errors - if (!iter->status().ok()) { - s = iter->status(); - } - - if (s.ok() && meta->file_size > 0) { - // Keep it - } else { - env->DeleteFile(fname); - } - return s; -} - -} // namespace leveldb diff --git a/src/leveldb/db/builder.h b/src/leveldb/db/builder.h deleted file mode 100644 index 62431fcf44..0000000000 --- a/src/leveldb/db/builder.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ -#define STORAGE_LEVELDB_DB_BUILDER_H_ - -#include "leveldb/status.h" - -namespace leveldb { - -struct Options; -struct FileMetaData; - -class Env; -class Iterator; -class TableCache; -class VersionEdit; - -// Build a Table file from the contents of *iter. The generated file -// will be named according to meta->number. On success, the rest of -// *meta will be filled with metadata about the generated table. -// If no data is present in *iter, meta->file_size will be set to -// zero, and no Table file will be produced. -extern Status BuildTable(const std::string& dbname, - Env* env, - const Options& options, - TableCache* table_cache, - Iterator* iter, - FileMetaData* meta); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/src/leveldb/db/c.cc b/src/leveldb/db/c.cc deleted file mode 100644 index 08ff0ad90a..0000000000 --- a/src/leveldb/db/c.cc +++ /dev/null @@ -1,595 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/c.h" - -#include -#include -#include "leveldb/cache.h" -#include "leveldb/comparator.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "leveldb/filter_policy.h" -#include "leveldb/iterator.h" -#include "leveldb/options.h" -#include "leveldb/status.h" -#include "leveldb/write_batch.h" - -using leveldb::Cache; -using leveldb::Comparator; -using leveldb::CompressionType; -using leveldb::DB; -using leveldb::Env; -using leveldb::FileLock; -using leveldb::FilterPolicy; -using leveldb::Iterator; -using leveldb::kMajorVersion; -using leveldb::kMinorVersion; -using leveldb::Logger; -using leveldb::NewBloomFilterPolicy; -using leveldb::NewLRUCache; -using leveldb::Options; -using leveldb::RandomAccessFile; -using leveldb::Range; -using leveldb::ReadOptions; -using leveldb::SequentialFile; -using leveldb::Slice; -using leveldb::Snapshot; -using leveldb::Status; -using leveldb::WritableFile; -using leveldb::WriteBatch; -using leveldb::WriteOptions; - -extern "C" { - -struct leveldb_t { DB* rep; }; -struct leveldb_iterator_t { Iterator* rep; }; -struct leveldb_writebatch_t { WriteBatch rep; }; -struct leveldb_snapshot_t { const Snapshot* rep; }; -struct leveldb_readoptions_t { ReadOptions rep; }; -struct leveldb_writeoptions_t { WriteOptions rep; }; -struct leveldb_options_t { Options rep; }; -struct leveldb_cache_t { Cache* rep; }; -struct leveldb_seqfile_t { SequentialFile* rep; }; -struct leveldb_randomfile_t { RandomAccessFile* rep; }; -struct leveldb_writablefile_t { WritableFile* rep; }; -struct leveldb_logger_t { Logger* rep; }; -struct leveldb_filelock_t { FileLock* rep; }; - -struct leveldb_comparator_t : public Comparator { - void* state_; - void (*destructor_)(void*); - int (*compare_)( - void*, - const char* a, size_t alen, - const char* b, size_t blen); - const char* (*name_)(void*); - - virtual ~leveldb_comparator_t() { - (*destructor_)(state_); - } - - virtual int Compare(const Slice& a, const Slice& b) const { - return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); - } - - virtual const char* Name() const { - return (*name_)(state_); - } - - // No-ops since the C binding does not support key shortening methods. - virtual void FindShortestSeparator(std::string*, const Slice&) const { } - virtual void FindShortSuccessor(std::string* key) const { } -}; - -struct leveldb_filterpolicy_t : public FilterPolicy { - void* state_; - void (*destructor_)(void*); - const char* (*name_)(void*); - char* (*create_)( - void*, - const char* const* key_array, const size_t* key_length_array, - int num_keys, - size_t* filter_length); - unsigned char (*key_match_)( - void*, - const char* key, size_t length, - const char* filter, size_t filter_length); - - virtual ~leveldb_filterpolicy_t() { - (*destructor_)(state_); - } - - virtual const char* Name() const { - return (*name_)(state_); - } - - virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { - std::vector key_pointers(n); - std::vector key_sizes(n); - for (int i = 0; i < n; i++) { - key_pointers[i] = keys[i].data(); - key_sizes[i] = keys[i].size(); - } - size_t len; - char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); - dst->append(filter, len); - free(filter); - } - - virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { - return (*key_match_)(state_, key.data(), key.size(), - filter.data(), filter.size()); - } -}; - -struct leveldb_env_t { - Env* rep; - bool is_default; -}; - -static bool SaveError(char** errptr, const Status& s) { - assert(errptr != NULL); - if (s.ok()) { - return false; - } else if (*errptr == NULL) { - *errptr = strdup(s.ToString().c_str()); - } else { - // TODO(sanjay): Merge with existing error? - free(*errptr); - *errptr = strdup(s.ToString().c_str()); - } - return true; -} - -static char* CopyString(const std::string& str) { - char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); - memcpy(result, str.data(), sizeof(char) * str.size()); - return result; -} - -leveldb_t* leveldb_open( - const leveldb_options_t* options, - const char* name, - char** errptr) { - DB* db; - if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { - return NULL; - } - leveldb_t* result = new leveldb_t; - result->rep = db; - return result; -} - -void leveldb_close(leveldb_t* db) { - delete db->rep; - delete db; -} - -void leveldb_put( - leveldb_t* db, - const leveldb_writeoptions_t* options, - const char* key, size_t keylen, - const char* val, size_t vallen, - char** errptr) { - SaveError(errptr, - db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); -} - -void leveldb_delete( - leveldb_t* db, - const leveldb_writeoptions_t* options, - const char* key, size_t keylen, - char** errptr) { - SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); -} - - -void leveldb_write( - leveldb_t* db, - const leveldb_writeoptions_t* options, - leveldb_writebatch_t* batch, - char** errptr) { - SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); -} - -char* leveldb_get( - leveldb_t* db, - const leveldb_readoptions_t* options, - const char* key, size_t keylen, - size_t* vallen, - char** errptr) { - char* result = NULL; - std::string tmp; - Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); - if (s.ok()) { - *vallen = tmp.size(); - result = CopyString(tmp); - } else { - *vallen = 0; - if (!s.IsNotFound()) { - SaveError(errptr, s); - } - } - return result; -} - -leveldb_iterator_t* leveldb_create_iterator( - leveldb_t* db, - const leveldb_readoptions_t* options) { - leveldb_iterator_t* result = new leveldb_iterator_t; - result->rep = db->rep->NewIterator(options->rep); - return result; -} - -const leveldb_snapshot_t* leveldb_create_snapshot( - leveldb_t* db) { - leveldb_snapshot_t* result = new leveldb_snapshot_t; - result->rep = db->rep->GetSnapshot(); - return result; -} - -void leveldb_release_snapshot( - leveldb_t* db, - const leveldb_snapshot_t* snapshot) { - db->rep->ReleaseSnapshot(snapshot->rep); - delete snapshot; -} - -char* leveldb_property_value( - leveldb_t* db, - const char* propname) { - std::string tmp; - if (db->rep->GetProperty(Slice(propname), &tmp)) { - // We use strdup() since we expect human readable output. - return strdup(tmp.c_str()); - } else { - return NULL; - } -} - -void leveldb_approximate_sizes( - leveldb_t* db, - int num_ranges, - const char* const* range_start_key, const size_t* range_start_key_len, - const char* const* range_limit_key, const size_t* range_limit_key_len, - uint64_t* sizes) { - Range* ranges = new Range[num_ranges]; - for (int i = 0; i < num_ranges; i++) { - ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); - ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); - } - db->rep->GetApproximateSizes(ranges, num_ranges, sizes); - delete[] ranges; -} - -void leveldb_compact_range( - leveldb_t* db, - const char* start_key, size_t start_key_len, - const char* limit_key, size_t limit_key_len) { - Slice a, b; - db->rep->CompactRange( - // Pass NULL Slice if corresponding "const char*" is NULL - (start_key ? (a = Slice(start_key, start_key_len), &a) : NULL), - (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : NULL)); -} - -void leveldb_destroy_db( - const leveldb_options_t* options, - const char* name, - char** errptr) { - SaveError(errptr, DestroyDB(name, options->rep)); -} - -void leveldb_repair_db( - const leveldb_options_t* options, - const char* name, - char** errptr) { - SaveError(errptr, RepairDB(name, options->rep)); -} - -void leveldb_iter_destroy(leveldb_iterator_t* iter) { - delete iter->rep; - delete iter; -} - -unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { - return iter->rep->Valid(); -} - -void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { - iter->rep->SeekToFirst(); -} - -void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { - iter->rep->SeekToLast(); -} - -void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { - iter->rep->Seek(Slice(k, klen)); -} - -void leveldb_iter_next(leveldb_iterator_t* iter) { - iter->rep->Next(); -} - -void leveldb_iter_prev(leveldb_iterator_t* iter) { - iter->rep->Prev(); -} - -const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { - Slice s = iter->rep->key(); - *klen = s.size(); - return s.data(); -} - -const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { - Slice s = iter->rep->value(); - *vlen = s.size(); - return s.data(); -} - -void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { - SaveError(errptr, iter->rep->status()); -} - -leveldb_writebatch_t* leveldb_writebatch_create() { - return new leveldb_writebatch_t; -} - -void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { - delete b; -} - -void leveldb_writebatch_clear(leveldb_writebatch_t* b) { - b->rep.Clear(); -} - -void leveldb_writebatch_put( - leveldb_writebatch_t* b, - const char* key, size_t klen, - const char* val, size_t vlen) { - b->rep.Put(Slice(key, klen), Slice(val, vlen)); -} - -void leveldb_writebatch_delete( - leveldb_writebatch_t* b, - const char* key, size_t klen) { - b->rep.Delete(Slice(key, klen)); -} - -void leveldb_writebatch_iterate( - leveldb_writebatch_t* b, - void* state, - void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), - void (*deleted)(void*, const char* k, size_t klen)) { - class H : public WriteBatch::Handler { - public: - void* state_; - void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); - void (*deleted_)(void*, const char* k, size_t klen); - virtual void Put(const Slice& key, const Slice& value) { - (*put_)(state_, key.data(), key.size(), value.data(), value.size()); - } - virtual void Delete(const Slice& key) { - (*deleted_)(state_, key.data(), key.size()); - } - }; - H handler; - handler.state_ = state; - handler.put_ = put; - handler.deleted_ = deleted; - b->rep.Iterate(&handler); -} - -leveldb_options_t* leveldb_options_create() { - return new leveldb_options_t; -} - -void leveldb_options_destroy(leveldb_options_t* options) { - delete options; -} - -void leveldb_options_set_comparator( - leveldb_options_t* opt, - leveldb_comparator_t* cmp) { - opt->rep.comparator = cmp; -} - -void leveldb_options_set_filter_policy( - leveldb_options_t* opt, - leveldb_filterpolicy_t* policy) { - opt->rep.filter_policy = policy; -} - -void leveldb_options_set_create_if_missing( - leveldb_options_t* opt, unsigned char v) { - opt->rep.create_if_missing = v; -} - -void leveldb_options_set_error_if_exists( - leveldb_options_t* opt, unsigned char v) { - opt->rep.error_if_exists = v; -} - -void leveldb_options_set_paranoid_checks( - leveldb_options_t* opt, unsigned char v) { - opt->rep.paranoid_checks = v; -} - -void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { - opt->rep.env = (env ? env->rep : NULL); -} - -void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { - opt->rep.info_log = (l ? l->rep : NULL); -} - -void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { - opt->rep.write_buffer_size = s; -} - -void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { - opt->rep.max_open_files = n; -} - -void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { - opt->rep.block_cache = c->rep; -} - -void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { - opt->rep.block_size = s; -} - -void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { - opt->rep.block_restart_interval = n; -} - -void leveldb_options_set_compression(leveldb_options_t* opt, int t) { - opt->rep.compression = static_cast(t); -} - -leveldb_comparator_t* leveldb_comparator_create( - void* state, - void (*destructor)(void*), - int (*compare)( - void*, - const char* a, size_t alen, - const char* b, size_t blen), - const char* (*name)(void*)) { - leveldb_comparator_t* result = new leveldb_comparator_t; - result->state_ = state; - result->destructor_ = destructor; - result->compare_ = compare; - result->name_ = name; - return result; -} - -void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { - delete cmp; -} - -leveldb_filterpolicy_t* leveldb_filterpolicy_create( - void* state, - void (*destructor)(void*), - char* (*create_filter)( - void*, - const char* const* key_array, const size_t* key_length_array, - int num_keys, - size_t* filter_length), - unsigned char (*key_may_match)( - void*, - const char* key, size_t length, - const char* filter, size_t filter_length), - const char* (*name)(void*)) { - leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; - result->state_ = state; - result->destructor_ = destructor; - result->create_ = create_filter; - result->key_match_ = key_may_match; - result->name_ = name; - return result; -} - -void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { - delete filter; -} - -leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { - // Make a leveldb_filterpolicy_t, but override all of its methods so - // they delegate to a NewBloomFilterPolicy() instead of user - // supplied C functions. - struct Wrapper : public leveldb_filterpolicy_t { - const FilterPolicy* rep_; - ~Wrapper() { delete rep_; } - const char* Name() const { return rep_->Name(); } - void CreateFilter(const Slice* keys, int n, std::string* dst) const { - return rep_->CreateFilter(keys, n, dst); - } - bool KeyMayMatch(const Slice& key, const Slice& filter) const { - return rep_->KeyMayMatch(key, filter); - } - static void DoNothing(void*) { } - }; - Wrapper* wrapper = new Wrapper; - wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); - wrapper->state_ = NULL; - wrapper->destructor_ = &Wrapper::DoNothing; - return wrapper; -} - -leveldb_readoptions_t* leveldb_readoptions_create() { - return new leveldb_readoptions_t; -} - -void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { - delete opt; -} - -void leveldb_readoptions_set_verify_checksums( - leveldb_readoptions_t* opt, - unsigned char v) { - opt->rep.verify_checksums = v; -} - -void leveldb_readoptions_set_fill_cache( - leveldb_readoptions_t* opt, unsigned char v) { - opt->rep.fill_cache = v; -} - -void leveldb_readoptions_set_snapshot( - leveldb_readoptions_t* opt, - const leveldb_snapshot_t* snap) { - opt->rep.snapshot = (snap ? snap->rep : NULL); -} - -leveldb_writeoptions_t* leveldb_writeoptions_create() { - return new leveldb_writeoptions_t; -} - -void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { - delete opt; -} - -void leveldb_writeoptions_set_sync( - leveldb_writeoptions_t* opt, unsigned char v) { - opt->rep.sync = v; -} - -leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { - leveldb_cache_t* c = new leveldb_cache_t; - c->rep = NewLRUCache(capacity); - return c; -} - -void leveldb_cache_destroy(leveldb_cache_t* cache) { - delete cache->rep; - delete cache; -} - -leveldb_env_t* leveldb_create_default_env() { - leveldb_env_t* result = new leveldb_env_t; - result->rep = Env::Default(); - result->is_default = true; - return result; -} - -void leveldb_env_destroy(leveldb_env_t* env) { - if (!env->is_default) delete env->rep; - delete env; -} - -void leveldb_free(void* ptr) { - free(ptr); -} - -int leveldb_major_version() { - return kMajorVersion; -} - -int leveldb_minor_version() { - return kMinorVersion; -} - -} // end extern "C" diff --git a/src/leveldb/db/c_test.c b/src/leveldb/db/c_test.c deleted file mode 100644 index 7cd5ee0207..0000000000 --- a/src/leveldb/db/c_test.c +++ /dev/null @@ -1,390 +0,0 @@ -/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. See the AUTHORS file for names of contributors. */ - -#include "leveldb/c.h" - -#include -#include -#include -#include -#include -#include - -const char* phase = ""; -static char dbname[200]; - -static void StartPhase(const char* name) { - fprintf(stderr, "=== Test %s\n", name); - phase = name; -} - -static const char* GetTempDir(void) { - const char* ret = getenv("TEST_TMPDIR"); - if (ret == NULL || ret[0] == '\0') - ret = "/tmp"; - return ret; -} - -#define CheckNoError(err) \ - if ((err) != NULL) { \ - fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, (err)); \ - abort(); \ - } - -#define CheckCondition(cond) \ - if (!(cond)) { \ - fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__, phase, #cond); \ - abort(); \ - } - -static void CheckEqual(const char* expected, const char* v, size_t n) { - if (expected == NULL && v == NULL) { - // ok - } else if (expected != NULL && v != NULL && n == strlen(expected) && - memcmp(expected, v, n) == 0) { - // ok - return; - } else { - fprintf(stderr, "%s: expected '%s', got '%s'\n", - phase, - (expected ? expected : "(null)"), - (v ? v : "(null")); - abort(); - } -} - -static void Free(char** ptr) { - if (*ptr) { - free(*ptr); - *ptr = NULL; - } -} - -static void CheckGet( - leveldb_t* db, - const leveldb_readoptions_t* options, - const char* key, - const char* expected) { - char* err = NULL; - size_t val_len; - char* val; - val = leveldb_get(db, options, key, strlen(key), &val_len, &err); - CheckNoError(err); - CheckEqual(expected, val, val_len); - Free(&val); -} - -static void CheckIter(leveldb_iterator_t* iter, - const char* key, const char* val) { - size_t len; - const char* str; - str = leveldb_iter_key(iter, &len); - CheckEqual(key, str, len); - str = leveldb_iter_value(iter, &len); - CheckEqual(val, str, len); -} - -// Callback from leveldb_writebatch_iterate() -static void CheckPut(void* ptr, - const char* k, size_t klen, - const char* v, size_t vlen) { - int* state = (int*) ptr; - CheckCondition(*state < 2); - switch (*state) { - case 0: - CheckEqual("bar", k, klen); - CheckEqual("b", v, vlen); - break; - case 1: - CheckEqual("box", k, klen); - CheckEqual("c", v, vlen); - break; - } - (*state)++; -} - -// Callback from leveldb_writebatch_iterate() -static void CheckDel(void* ptr, const char* k, size_t klen) { - int* state = (int*) ptr; - CheckCondition(*state == 2); - CheckEqual("bar", k, klen); - (*state)++; -} - -static void CmpDestroy(void* arg) { } - -static int CmpCompare(void* arg, const char* a, size_t alen, - const char* b, size_t blen) { - int n = (alen < blen) ? alen : blen; - int r = memcmp(a, b, n); - if (r == 0) { - if (alen < blen) r = -1; - else if (alen > blen) r = +1; - } - return r; -} - -static const char* CmpName(void* arg) { - return "foo"; -} - -// Custom filter policy -static unsigned char fake_filter_result = 1; -static void FilterDestroy(void* arg) { } -static const char* FilterName(void* arg) { - return "TestFilter"; -} -static char* FilterCreate( - void* arg, - const char* const* key_array, const size_t* key_length_array, - int num_keys, - size_t* filter_length) { - *filter_length = 4; - char* result = malloc(4); - memcpy(result, "fake", 4); - return result; -} -unsigned char FilterKeyMatch( - void* arg, - const char* key, size_t length, - const char* filter, size_t filter_length) { - CheckCondition(filter_length == 4); - CheckCondition(memcmp(filter, "fake", 4) == 0); - return fake_filter_result; -} - -int main(int argc, char** argv) { - leveldb_t* db; - leveldb_comparator_t* cmp; - leveldb_cache_t* cache; - leveldb_env_t* env; - leveldb_options_t* options; - leveldb_readoptions_t* roptions; - leveldb_writeoptions_t* woptions; - char* err = NULL; - int run = -1; - - CheckCondition(leveldb_major_version() >= 1); - CheckCondition(leveldb_minor_version() >= 1); - - snprintf(dbname, sizeof(dbname), - "%s/leveldb_c_test-%d", - GetTempDir(), - ((int) geteuid())); - - StartPhase("create_objects"); - cmp = leveldb_comparator_create(NULL, CmpDestroy, CmpCompare, CmpName); - env = leveldb_create_default_env(); - cache = leveldb_cache_create_lru(100000); - - options = leveldb_options_create(); - leveldb_options_set_comparator(options, cmp); - leveldb_options_set_error_if_exists(options, 1); - leveldb_options_set_cache(options, cache); - leveldb_options_set_env(options, env); - leveldb_options_set_info_log(options, NULL); - leveldb_options_set_write_buffer_size(options, 100000); - leveldb_options_set_paranoid_checks(options, 1); - leveldb_options_set_max_open_files(options, 10); - leveldb_options_set_block_size(options, 1024); - leveldb_options_set_block_restart_interval(options, 8); - leveldb_options_set_compression(options, leveldb_no_compression); - - roptions = leveldb_readoptions_create(); - leveldb_readoptions_set_verify_checksums(roptions, 1); - leveldb_readoptions_set_fill_cache(roptions, 0); - - woptions = leveldb_writeoptions_create(); - leveldb_writeoptions_set_sync(woptions, 1); - - StartPhase("destroy"); - leveldb_destroy_db(options, dbname, &err); - Free(&err); - - StartPhase("open_error"); - db = leveldb_open(options, dbname, &err); - CheckCondition(err != NULL); - Free(&err); - - StartPhase("leveldb_free"); - db = leveldb_open(options, dbname, &err); - CheckCondition(err != NULL); - leveldb_free(err); - err = NULL; - - StartPhase("open"); - leveldb_options_set_create_if_missing(options, 1); - db = leveldb_open(options, dbname, &err); - CheckNoError(err); - CheckGet(db, roptions, "foo", NULL); - - StartPhase("put"); - leveldb_put(db, woptions, "foo", 3, "hello", 5, &err); - CheckNoError(err); - CheckGet(db, roptions, "foo", "hello"); - - StartPhase("compactall"); - leveldb_compact_range(db, NULL, 0, NULL, 0); - CheckGet(db, roptions, "foo", "hello"); - - StartPhase("compactrange"); - leveldb_compact_range(db, "a", 1, "z", 1); - CheckGet(db, roptions, "foo", "hello"); - - StartPhase("writebatch"); - { - leveldb_writebatch_t* wb = leveldb_writebatch_create(); - leveldb_writebatch_put(wb, "foo", 3, "a", 1); - leveldb_writebatch_clear(wb); - leveldb_writebatch_put(wb, "bar", 3, "b", 1); - leveldb_writebatch_put(wb, "box", 3, "c", 1); - leveldb_writebatch_delete(wb, "bar", 3); - leveldb_write(db, woptions, wb, &err); - CheckNoError(err); - CheckGet(db, roptions, "foo", "hello"); - CheckGet(db, roptions, "bar", NULL); - CheckGet(db, roptions, "box", "c"); - int pos = 0; - leveldb_writebatch_iterate(wb, &pos, CheckPut, CheckDel); - CheckCondition(pos == 3); - leveldb_writebatch_destroy(wb); - } - - StartPhase("iter"); - { - leveldb_iterator_t* iter = leveldb_create_iterator(db, roptions); - CheckCondition(!leveldb_iter_valid(iter)); - leveldb_iter_seek_to_first(iter); - CheckCondition(leveldb_iter_valid(iter)); - CheckIter(iter, "box", "c"); - leveldb_iter_next(iter); - CheckIter(iter, "foo", "hello"); - leveldb_iter_prev(iter); - CheckIter(iter, "box", "c"); - leveldb_iter_prev(iter); - CheckCondition(!leveldb_iter_valid(iter)); - leveldb_iter_seek_to_last(iter); - CheckIter(iter, "foo", "hello"); - leveldb_iter_seek(iter, "b", 1); - CheckIter(iter, "box", "c"); - leveldb_iter_get_error(iter, &err); - CheckNoError(err); - leveldb_iter_destroy(iter); - } - - StartPhase("approximate_sizes"); - { - int i; - int n = 20000; - char keybuf[100]; - char valbuf[100]; - uint64_t sizes[2]; - const char* start[2] = { "a", "k00000000000000010000" }; - size_t start_len[2] = { 1, 21 }; - const char* limit[2] = { "k00000000000000010000", "z" }; - size_t limit_len[2] = { 21, 1 }; - leveldb_writeoptions_set_sync(woptions, 0); - for (i = 0; i < n; i++) { - snprintf(keybuf, sizeof(keybuf), "k%020d", i); - snprintf(valbuf, sizeof(valbuf), "v%020d", i); - leveldb_put(db, woptions, keybuf, strlen(keybuf), valbuf, strlen(valbuf), - &err); - CheckNoError(err); - } - leveldb_approximate_sizes(db, 2, start, start_len, limit, limit_len, sizes); - CheckCondition(sizes[0] > 0); - CheckCondition(sizes[1] > 0); - } - - StartPhase("property"); - { - char* prop = leveldb_property_value(db, "nosuchprop"); - CheckCondition(prop == NULL); - prop = leveldb_property_value(db, "leveldb.stats"); - CheckCondition(prop != NULL); - Free(&prop); - } - - StartPhase("snapshot"); - { - const leveldb_snapshot_t* snap; - snap = leveldb_create_snapshot(db); - leveldb_delete(db, woptions, "foo", 3, &err); - CheckNoError(err); - leveldb_readoptions_set_snapshot(roptions, snap); - CheckGet(db, roptions, "foo", "hello"); - leveldb_readoptions_set_snapshot(roptions, NULL); - CheckGet(db, roptions, "foo", NULL); - leveldb_release_snapshot(db, snap); - } - - StartPhase("repair"); - { - leveldb_close(db); - leveldb_options_set_create_if_missing(options, 0); - leveldb_options_set_error_if_exists(options, 0); - leveldb_repair_db(options, dbname, &err); - CheckNoError(err); - db = leveldb_open(options, dbname, &err); - CheckNoError(err); - CheckGet(db, roptions, "foo", NULL); - CheckGet(db, roptions, "bar", NULL); - CheckGet(db, roptions, "box", "c"); - leveldb_options_set_create_if_missing(options, 1); - leveldb_options_set_error_if_exists(options, 1); - } - - StartPhase("filter"); - for (run = 0; run < 2; run++) { - // First run uses custom filter, second run uses bloom filter - CheckNoError(err); - leveldb_filterpolicy_t* policy; - if (run == 0) { - policy = leveldb_filterpolicy_create( - NULL, FilterDestroy, FilterCreate, FilterKeyMatch, FilterName); - } else { - policy = leveldb_filterpolicy_create_bloom(10); - } - - // Create new database - leveldb_close(db); - leveldb_destroy_db(options, dbname, &err); - leveldb_options_set_filter_policy(options, policy); - db = leveldb_open(options, dbname, &err); - CheckNoError(err); - leveldb_put(db, woptions, "foo", 3, "foovalue", 8, &err); - CheckNoError(err); - leveldb_put(db, woptions, "bar", 3, "barvalue", 8, &err); - CheckNoError(err); - leveldb_compact_range(db, NULL, 0, NULL, 0); - - fake_filter_result = 1; - CheckGet(db, roptions, "foo", "foovalue"); - CheckGet(db, roptions, "bar", "barvalue"); - if (phase == 0) { - // Must not find value when custom filter returns false - fake_filter_result = 0; - CheckGet(db, roptions, "foo", NULL); - CheckGet(db, roptions, "bar", NULL); - fake_filter_result = 1; - - CheckGet(db, roptions, "foo", "foovalue"); - CheckGet(db, roptions, "bar", "barvalue"); - } - leveldb_options_set_filter_policy(options, NULL); - leveldb_filterpolicy_destroy(policy); - } - - StartPhase("cleanup"); - leveldb_close(db); - leveldb_options_destroy(options); - leveldb_readoptions_destroy(roptions); - leveldb_writeoptions_destroy(woptions); - leveldb_cache_destroy(cache); - leveldb_comparator_destroy(cmp); - leveldb_env_destroy(env); - - fprintf(stderr, "PASS\n"); - return 0; -} diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc deleted file mode 100644 index 96afc68913..0000000000 --- a/src/leveldb/db/corruption_test.cc +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/db.h" - -#include -#include -#include -#include -#include "leveldb/cache.h" -#include "leveldb/env.h" -#include "leveldb/table.h" -#include "leveldb/write_batch.h" -#include "db/db_impl.h" -#include "db/filename.h" -#include "db/log_format.h" -#include "db/version_set.h" -#include "util/logging.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -static const int kValueSize = 1000; - -class CorruptionTest { - public: - test::ErrorEnv env_; - std::string dbname_; - Cache* tiny_cache_; - Options options_; - DB* db_; - - CorruptionTest() { - tiny_cache_ = NewLRUCache(100); - options_.env = &env_; - options_.block_cache = tiny_cache_; - dbname_ = test::TmpDir() + "/db_test"; - DestroyDB(dbname_, options_); - - db_ = NULL; - options_.create_if_missing = true; - Reopen(); - options_.create_if_missing = false; - } - - ~CorruptionTest() { - delete db_; - DestroyDB(dbname_, Options()); - delete tiny_cache_; - } - - Status TryReopen() { - delete db_; - db_ = NULL; - return DB::Open(options_, dbname_, &db_); - } - - void Reopen() { - ASSERT_OK(TryReopen()); - } - - void RepairDB() { - delete db_; - db_ = NULL; - ASSERT_OK(::leveldb::RepairDB(dbname_, options_)); - } - - void Build(int n) { - std::string key_space, value_space; - WriteBatch batch; - for (int i = 0; i < n; i++) { - //if ((i % 100) == 0) fprintf(stderr, "@ %d of %d\n", i, n); - Slice key = Key(i, &key_space); - batch.Clear(); - batch.Put(key, Value(i, &value_space)); - WriteOptions options; - // Corrupt() doesn't work without this sync on windows; stat reports 0 for - // the file size. - if (i == n - 1) { - options.sync = true; - } - ASSERT_OK(db_->Write(options, &batch)); - } - } - - void Check(int min_expected, int max_expected) { - int next_expected = 0; - int missed = 0; - int bad_keys = 0; - int bad_values = 0; - int correct = 0; - std::string value_space; - Iterator* iter = db_->NewIterator(ReadOptions()); - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - uint64_t key; - Slice in(iter->key()); - if (in == "" || in == "~") { - // Ignore boundary keys. - continue; - } - if (!ConsumeDecimalNumber(&in, &key) || - !in.empty() || - key < next_expected) { - bad_keys++; - continue; - } - missed += (key - next_expected); - next_expected = key + 1; - if (iter->value() != Value(key, &value_space)) { - bad_values++; - } else { - correct++; - } - } - delete iter; - - fprintf(stderr, - "expected=%d..%d; got=%d; bad_keys=%d; bad_values=%d; missed=%d\n", - min_expected, max_expected, correct, bad_keys, bad_values, missed); - ASSERT_LE(min_expected, correct); - ASSERT_GE(max_expected, correct); - } - - void Corrupt(FileType filetype, int offset, int bytes_to_corrupt) { - // Pick file to corrupt - std::vector filenames; - ASSERT_OK(env_.GetChildren(dbname_, &filenames)); - uint64_t number; - FileType type; - std::string fname; - int picked_number = -1; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type) && - type == filetype && - int(number) > picked_number) { // Pick latest file - fname = dbname_ + "/" + filenames[i]; - picked_number = number; - } - } - ASSERT_TRUE(!fname.empty()) << filetype; - - struct stat sbuf; - if (stat(fname.c_str(), &sbuf) != 0) { - const char* msg = strerror(errno); - ASSERT_TRUE(false) << fname << ": " << msg; - } - - if (offset < 0) { - // Relative to end of file; make it absolute - if (-offset > sbuf.st_size) { - offset = 0; - } else { - offset = sbuf.st_size + offset; - } - } - if (offset > sbuf.st_size) { - offset = sbuf.st_size; - } - if (offset + bytes_to_corrupt > sbuf.st_size) { - bytes_to_corrupt = sbuf.st_size - offset; - } - - // Do it - std::string contents; - Status s = ReadFileToString(Env::Default(), fname, &contents); - ASSERT_TRUE(s.ok()) << s.ToString(); - for (int i = 0; i < bytes_to_corrupt; i++) { - contents[i + offset] ^= 0x80; - } - s = WriteStringToFile(Env::Default(), contents, fname); - ASSERT_TRUE(s.ok()) << s.ToString(); - } - - int Property(const std::string& name) { - std::string property; - int result; - if (db_->GetProperty(name, &property) && - sscanf(property.c_str(), "%d", &result) == 1) { - return result; - } else { - return -1; - } - } - - // Return the ith key - Slice Key(int i, std::string* storage) { - char buf[100]; - snprintf(buf, sizeof(buf), "%016d", i); - storage->assign(buf, strlen(buf)); - return Slice(*storage); - } - - // Return the value to associate with the specified key - Slice Value(int k, std::string* storage) { - Random r(k); - return test::RandomString(&r, kValueSize, storage); - } -}; - -TEST(CorruptionTest, Recovery) { - Build(100); - Check(100, 100); - Corrupt(kLogFile, 19, 1); // WriteBatch tag for first record - Corrupt(kLogFile, log::kBlockSize + 1000, 1); // Somewhere in second block - Reopen(); - - // The 64 records in the first two log blocks are completely lost. - Check(36, 36); -} - -TEST(CorruptionTest, RecoverWriteError) { - env_.writable_file_error_ = true; - Status s = TryReopen(); - ASSERT_TRUE(!s.ok()); -} - -TEST(CorruptionTest, NewFileErrorDuringWrite) { - // Do enough writing to force minor compaction - env_.writable_file_error_ = true; - const int num = 3 + (Options().write_buffer_size / kValueSize); - std::string value_storage; - Status s; - for (int i = 0; s.ok() && i < num; i++) { - WriteBatch batch; - batch.Put("a", Value(100, &value_storage)); - s = db_->Write(WriteOptions(), &batch); - } - ASSERT_TRUE(!s.ok()); - ASSERT_GE(env_.num_writable_file_errors_, 1); - env_.writable_file_error_ = false; - Reopen(); -} - -TEST(CorruptionTest, TableFile) { - Build(100); - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - dbi->TEST_CompactRange(0, NULL, NULL); - dbi->TEST_CompactRange(1, NULL, NULL); - - Corrupt(kTableFile, 100, 1); - Check(90, 99); -} - -TEST(CorruptionTest, TableFileRepair) { - options_.block_size = 2 * kValueSize; // Limit scope of corruption - options_.paranoid_checks = true; - Reopen(); - Build(100); - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - dbi->TEST_CompactRange(0, NULL, NULL); - dbi->TEST_CompactRange(1, NULL, NULL); - - Corrupt(kTableFile, 100, 1); - RepairDB(); - Reopen(); - Check(95, 99); -} - -TEST(CorruptionTest, TableFileIndexData) { - Build(10000); // Enough to build multiple Tables - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - - Corrupt(kTableFile, -2000, 500); - Reopen(); - Check(5000, 9999); -} - -TEST(CorruptionTest, MissingDescriptor) { - Build(1000); - RepairDB(); - Reopen(); - Check(1000, 1000); -} - -TEST(CorruptionTest, SequenceNumberRecovery) { - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v3")); - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v4")); - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v5")); - RepairDB(); - Reopen(); - std::string v; - ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); - ASSERT_EQ("v5", v); - // Write something. If sequence number was not recovered properly, - // it will be hidden by an earlier write. - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v6")); - ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); - ASSERT_EQ("v6", v); - Reopen(); - ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); - ASSERT_EQ("v6", v); -} - -TEST(CorruptionTest, CorruptedDescriptor) { - ASSERT_OK(db_->Put(WriteOptions(), "foo", "hello")); - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - dbi->TEST_CompactRange(0, NULL, NULL); - - Corrupt(kDescriptorFile, 0, 1000); - Status s = TryReopen(); - ASSERT_TRUE(!s.ok()); - - RepairDB(); - Reopen(); - std::string v; - ASSERT_OK(db_->Get(ReadOptions(), "foo", &v)); - ASSERT_EQ("hello", v); -} - -TEST(CorruptionTest, CompactionInputError) { - Build(10); - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - const int last = config::kMaxMemCompactLevel; - ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last))); - - Corrupt(kTableFile, 100, 1); - Check(5, 9); - - // Force compactions by writing lots of values - Build(10000); - Check(10000, 10000); -} - -TEST(CorruptionTest, CompactionInputErrorParanoid) { - options_.paranoid_checks = true; - options_.write_buffer_size = 512 << 10; - Reopen(); - DBImpl* dbi = reinterpret_cast(db_); - - // Make multiple inputs so we need to compact. - for (int i = 0; i < 2; i++) { - Build(10); - dbi->TEST_CompactMemTable(); - Corrupt(kTableFile, 100, 1); - env_.SleepForMicroseconds(100000); - } - dbi->CompactRange(NULL, NULL); - - // Write must fail because of corrupted table - std::string tmp1, tmp2; - Status s = db_->Put(WriteOptions(), Key(5, &tmp1), Value(5, &tmp2)); - ASSERT_TRUE(!s.ok()) << "write did not fail in corrupted paranoid db"; -} - -TEST(CorruptionTest, UnrelatedKeys) { - Build(10); - DBImpl* dbi = reinterpret_cast(db_); - dbi->TEST_CompactMemTable(); - Corrupt(kTableFile, 100, 1); - - std::string tmp1, tmp2; - ASSERT_OK(db_->Put(WriteOptions(), Key(1000, &tmp1), Value(1000, &tmp2))); - std::string v; - ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); - ASSERT_EQ(Value(1000, &tmp2).ToString(), v); - dbi->TEST_CompactMemTable(); - ASSERT_OK(db_->Get(ReadOptions(), Key(1000, &tmp1), &v)); - ASSERT_EQ(Value(1000, &tmp2).ToString(), v); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/db/db_bench.cc deleted file mode 100644 index 705a170aae..0000000000 --- a/src/leveldb/db/db_bench.cc +++ /dev/null @@ -1,978 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include -#include "db/db_impl.h" -#include "db/version_set.h" -#include "leveldb/cache.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "leveldb/write_batch.h" -#include "port/port.h" -#include "util/crc32c.h" -#include "util/histogram.h" -#include "util/mutexlock.h" -#include "util/random.h" -#include "util/testutil.h" - -// Comma-separated list of operations to run in the specified order -// Actual benchmarks: -// fillseq -- write N values in sequential key order in async mode -// fillrandom -- write N values in random key order in async mode -// overwrite -- overwrite N values in random key order in async mode -// fillsync -- write N/100 values in random key order in sync mode -// fill100K -- write N/1000 100K values in random order in async mode -// deleteseq -- delete N keys in sequential order -// deleterandom -- delete N keys in random order -// readseq -- read N times sequentially -// readreverse -- read N times in reverse order -// readrandom -- read N times in random order -// readmissing -- read N missing keys in random order -// readhot -- read N times in random order from 1% section of DB -// seekrandom -- N random seeks -// crc32c -- repeated crc32c of 4K of data -// acquireload -- load N*1000 times -// Meta operations: -// compact -- Compact the entire DB -// stats -- Print DB stats -// sstables -- Print sstable info -// heapprofile -- Dump a heap profile (if supported by this port) -static const char* FLAGS_benchmarks = - "fillseq," - "fillsync," - "fillrandom," - "overwrite," - "readrandom," - "readrandom," // Extra run to allow previous compactions to quiesce - "readseq," - "readreverse," - "compact," - "readrandom," - "readseq," - "readreverse," - "fill100K," - "crc32c," - "snappycomp," - "snappyuncomp," - "acquireload," - ; - -// Number of key/values to place in database -static int FLAGS_num = 1000000; - -// Number of read operations to do. If negative, do FLAGS_num reads. -static int FLAGS_reads = -1; - -// Number of concurrent threads to run. -static int FLAGS_threads = 1; - -// Size of each value -static int FLAGS_value_size = 100; - -// Arrange to generate values that shrink to this fraction of -// their original size after compression -static double FLAGS_compression_ratio = 0.5; - -// Print histogram of operation timings -static bool FLAGS_histogram = false; - -// Number of bytes to buffer in memtable before compacting -// (initialized to default value by "main") -static int FLAGS_write_buffer_size = 0; - -// Number of bytes to use as a cache of uncompressed data. -// Negative means use default settings. -static int FLAGS_cache_size = -1; - -// Maximum number of files to keep open at the same time (use default if == 0) -static int FLAGS_open_files = 0; - -// Bloom filter bits per key. -// Negative means use default settings. -static int FLAGS_bloom_bits = -1; - -// If true, do not destroy the existing database. If you set this -// flag and also specify a benchmark that wants a fresh database, that -// benchmark will fail. -static bool FLAGS_use_existing_db = false; - -// Use the db with the following name. -static const char* FLAGS_db = NULL; - -namespace leveldb { - -namespace { - -// Helper for quickly generating random data. -class RandomGenerator { - private: - std::string data_; - int pos_; - - public: - RandomGenerator() { - // We use a limited amount of data over and over again and ensure - // that it is larger than the compression window (32KB), and also - // large enough to serve all typical value sizes we want to write. - Random rnd(301); - std::string piece; - while (data_.size() < 1048576) { - // Add a short fragment that is as compressible as specified - // by FLAGS_compression_ratio. - test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); - data_.append(piece); - } - pos_ = 0; - } - - Slice Generate(size_t len) { - if (pos_ + len > data_.size()) { - pos_ = 0; - assert(len < data_.size()); - } - pos_ += len; - return Slice(data_.data() + pos_ - len, len); - } -}; - -static Slice TrimSpace(Slice s) { - size_t start = 0; - while (start < s.size() && isspace(s[start])) { - start++; - } - size_t limit = s.size(); - while (limit > start && isspace(s[limit-1])) { - limit--; - } - return Slice(s.data() + start, limit - start); -} - -static void AppendWithSpace(std::string* str, Slice msg) { - if (msg.empty()) return; - if (!str->empty()) { - str->push_back(' '); - } - str->append(msg.data(), msg.size()); -} - -class Stats { - private: - double start_; - double finish_; - double seconds_; - int done_; - int next_report_; - int64_t bytes_; - double last_op_finish_; - Histogram hist_; - std::string message_; - - public: - Stats() { Start(); } - - void Start() { - next_report_ = 100; - last_op_finish_ = start_; - hist_.Clear(); - done_ = 0; - bytes_ = 0; - seconds_ = 0; - start_ = Env::Default()->NowMicros(); - finish_ = start_; - message_.clear(); - } - - void Merge(const Stats& other) { - hist_.Merge(other.hist_); - done_ += other.done_; - bytes_ += other.bytes_; - seconds_ += other.seconds_; - if (other.start_ < start_) start_ = other.start_; - if (other.finish_ > finish_) finish_ = other.finish_; - - // Just keep the messages from one thread - if (message_.empty()) message_ = other.message_; - } - - void Stop() { - finish_ = Env::Default()->NowMicros(); - seconds_ = (finish_ - start_) * 1e-6; - } - - void AddMessage(Slice msg) { - AppendWithSpace(&message_, msg); - } - - void FinishedSingleOp() { - if (FLAGS_histogram) { - double now = Env::Default()->NowMicros(); - double micros = now - last_op_finish_; - hist_.Add(micros); - if (micros > 20000) { - fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); - fflush(stderr); - } - last_op_finish_ = now; - } - - done_++; - if (done_ >= next_report_) { - if (next_report_ < 1000) next_report_ += 100; - else if (next_report_ < 5000) next_report_ += 500; - else if (next_report_ < 10000) next_report_ += 1000; - else if (next_report_ < 50000) next_report_ += 5000; - else if (next_report_ < 100000) next_report_ += 10000; - else if (next_report_ < 500000) next_report_ += 50000; - else next_report_ += 100000; - fprintf(stderr, "... finished %d ops%30s\r", done_, ""); - fflush(stderr); - } - } - - void AddBytes(int64_t n) { - bytes_ += n; - } - - void Report(const Slice& name) { - // Pretend at least one op was done in case we are running a benchmark - // that does not call FinishedSingleOp(). - if (done_ < 1) done_ = 1; - - std::string extra; - if (bytes_ > 0) { - // Rate is computed on actual elapsed time, not the sum of per-thread - // elapsed times. - double elapsed = (finish_ - start_) * 1e-6; - char rate[100]; - snprintf(rate, sizeof(rate), "%6.1f MB/s", - (bytes_ / 1048576.0) / elapsed); - extra = rate; - } - AppendWithSpace(&extra, message_); - - fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", - name.ToString().c_str(), - seconds_ * 1e6 / done_, - (extra.empty() ? "" : " "), - extra.c_str()); - if (FLAGS_histogram) { - fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); - } - fflush(stdout); - } -}; - -// State shared by all concurrent executions of the same benchmark. -struct SharedState { - port::Mutex mu; - port::CondVar cv; - int total; - - // Each thread goes through the following states: - // (1) initializing - // (2) waiting for others to be initialized - // (3) running - // (4) done - - int num_initialized; - int num_done; - bool start; - - SharedState() : cv(&mu) { } -}; - -// Per-thread state for concurrent executions of the same benchmark. -struct ThreadState { - int tid; // 0..n-1 when running in n threads - Random rand; // Has different seeds for different threads - Stats stats; - SharedState* shared; - - ThreadState(int index) - : tid(index), - rand(1000 + index) { - } -}; - -} // namespace - -class Benchmark { - private: - Cache* cache_; - const FilterPolicy* filter_policy_; - DB* db_; - int num_; - int value_size_; - int entries_per_batch_; - WriteOptions write_options_; - int reads_; - int heap_counter_; - - void PrintHeader() { - const int kKeySize = 16; - PrintEnvironment(); - fprintf(stdout, "Keys: %d bytes each\n", kKeySize); - fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", - FLAGS_value_size, - static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); - fprintf(stdout, "Entries: %d\n", num_); - fprintf(stdout, "RawSize: %.1f MB (estimated)\n", - ((static_cast(kKeySize + FLAGS_value_size) * num_) - / 1048576.0)); - fprintf(stdout, "FileSize: %.1f MB (estimated)\n", - (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) - / 1048576.0)); - PrintWarnings(); - fprintf(stdout, "------------------------------------------------\n"); - } - - void PrintWarnings() { -#if defined(__GNUC__) && !defined(__OPTIMIZE__) - fprintf(stdout, - "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" - ); -#endif -#ifndef NDEBUG - fprintf(stdout, - "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); -#endif - - // See if snappy is working by attempting to compress a compressible string - const char text[] = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; - std::string compressed; - if (!port::Snappy_Compress(text, sizeof(text), &compressed)) { - fprintf(stdout, "WARNING: Snappy compression is not enabled\n"); - } else if (compressed.size() >= sizeof(text)) { - fprintf(stdout, "WARNING: Snappy compression is not effective\n"); - } - } - - void PrintEnvironment() { - fprintf(stderr, "LevelDB: version %d.%d\n", - kMajorVersion, kMinorVersion); - -#if defined(__linux) - time_t now = time(NULL); - fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline - - FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); - if (cpuinfo != NULL) { - char line[1000]; - int num_cpus = 0; - std::string cpu_type; - std::string cache_size; - while (fgets(line, sizeof(line), cpuinfo) != NULL) { - const char* sep = strchr(line, ':'); - if (sep == NULL) { - continue; - } - Slice key = TrimSpace(Slice(line, sep - 1 - line)); - Slice val = TrimSpace(Slice(sep + 1)); - if (key == "model name") { - ++num_cpus; - cpu_type = val.ToString(); - } else if (key == "cache size") { - cache_size = val.ToString(); - } - } - fclose(cpuinfo); - fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); - fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); - } -#endif - } - - public: - Benchmark() - : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : NULL), - filter_policy_(FLAGS_bloom_bits >= 0 - ? NewBloomFilterPolicy(FLAGS_bloom_bits) - : NULL), - db_(NULL), - num_(FLAGS_num), - value_size_(FLAGS_value_size), - entries_per_batch_(1), - reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), - heap_counter_(0) { - std::vector files; - Env::Default()->GetChildren(FLAGS_db, &files); - for (size_t i = 0; i < files.size(); i++) { - if (Slice(files[i]).starts_with("heap-")) { - Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); - } - } - if (!FLAGS_use_existing_db) { - DestroyDB(FLAGS_db, Options()); - } - } - - ~Benchmark() { - delete db_; - delete cache_; - delete filter_policy_; - } - - void Run() { - PrintHeader(); - Open(); - - const char* benchmarks = FLAGS_benchmarks; - while (benchmarks != NULL) { - const char* sep = strchr(benchmarks, ','); - Slice name; - if (sep == NULL) { - name = benchmarks; - benchmarks = NULL; - } else { - name = Slice(benchmarks, sep - benchmarks); - benchmarks = sep + 1; - } - - // Reset parameters that may be overridden below - num_ = FLAGS_num; - reads_ = (FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads); - value_size_ = FLAGS_value_size; - entries_per_batch_ = 1; - write_options_ = WriteOptions(); - - void (Benchmark::*method)(ThreadState*) = NULL; - bool fresh_db = false; - int num_threads = FLAGS_threads; - - if (name == Slice("fillseq")) { - fresh_db = true; - method = &Benchmark::WriteSeq; - } else if (name == Slice("fillbatch")) { - fresh_db = true; - entries_per_batch_ = 1000; - method = &Benchmark::WriteSeq; - } else if (name == Slice("fillrandom")) { - fresh_db = true; - method = &Benchmark::WriteRandom; - } else if (name == Slice("overwrite")) { - fresh_db = false; - method = &Benchmark::WriteRandom; - } else if (name == Slice("fillsync")) { - fresh_db = true; - num_ /= 1000; - write_options_.sync = true; - method = &Benchmark::WriteRandom; - } else if (name == Slice("fill100K")) { - fresh_db = true; - num_ /= 1000; - value_size_ = 100 * 1000; - method = &Benchmark::WriteRandom; - } else if (name == Slice("readseq")) { - method = &Benchmark::ReadSequential; - } else if (name == Slice("readreverse")) { - method = &Benchmark::ReadReverse; - } else if (name == Slice("readrandom")) { - method = &Benchmark::ReadRandom; - } else if (name == Slice("readmissing")) { - method = &Benchmark::ReadMissing; - } else if (name == Slice("seekrandom")) { - method = &Benchmark::SeekRandom; - } else if (name == Slice("readhot")) { - method = &Benchmark::ReadHot; - } else if (name == Slice("readrandomsmall")) { - reads_ /= 1000; - method = &Benchmark::ReadRandom; - } else if (name == Slice("deleteseq")) { - method = &Benchmark::DeleteSeq; - } else if (name == Slice("deleterandom")) { - method = &Benchmark::DeleteRandom; - } else if (name == Slice("readwhilewriting")) { - num_threads++; // Add extra thread for writing - method = &Benchmark::ReadWhileWriting; - } else if (name == Slice("compact")) { - method = &Benchmark::Compact; - } else if (name == Slice("crc32c")) { - method = &Benchmark::Crc32c; - } else if (name == Slice("acquireload")) { - method = &Benchmark::AcquireLoad; - } else if (name == Slice("snappycomp")) { - method = &Benchmark::SnappyCompress; - } else if (name == Slice("snappyuncomp")) { - method = &Benchmark::SnappyUncompress; - } else if (name == Slice("heapprofile")) { - HeapProfile(); - } else if (name == Slice("stats")) { - PrintStats("leveldb.stats"); - } else if (name == Slice("sstables")) { - PrintStats("leveldb.sstables"); - } else { - if (name != Slice()) { // No error message for empty name - fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); - } - } - - if (fresh_db) { - if (FLAGS_use_existing_db) { - fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n", - name.ToString().c_str()); - method = NULL; - } else { - delete db_; - db_ = NULL; - DestroyDB(FLAGS_db, Options()); - Open(); - } - } - - if (method != NULL) { - RunBenchmark(num_threads, name, method); - } - } - } - - private: - struct ThreadArg { - Benchmark* bm; - SharedState* shared; - ThreadState* thread; - void (Benchmark::*method)(ThreadState*); - }; - - static void ThreadBody(void* v) { - ThreadArg* arg = reinterpret_cast(v); - SharedState* shared = arg->shared; - ThreadState* thread = arg->thread; - { - MutexLock l(&shared->mu); - shared->num_initialized++; - if (shared->num_initialized >= shared->total) { - shared->cv.SignalAll(); - } - while (!shared->start) { - shared->cv.Wait(); - } - } - - thread->stats.Start(); - (arg->bm->*(arg->method))(thread); - thread->stats.Stop(); - - { - MutexLock l(&shared->mu); - shared->num_done++; - if (shared->num_done >= shared->total) { - shared->cv.SignalAll(); - } - } - } - - void RunBenchmark(int n, Slice name, - void (Benchmark::*method)(ThreadState*)) { - SharedState shared; - shared.total = n; - shared.num_initialized = 0; - shared.num_done = 0; - shared.start = false; - - ThreadArg* arg = new ThreadArg[n]; - for (int i = 0; i < n; i++) { - arg[i].bm = this; - arg[i].method = method; - arg[i].shared = &shared; - arg[i].thread = new ThreadState(i); - arg[i].thread->shared = &shared; - Env::Default()->StartThread(ThreadBody, &arg[i]); - } - - shared.mu.Lock(); - while (shared.num_initialized < n) { - shared.cv.Wait(); - } - - shared.start = true; - shared.cv.SignalAll(); - while (shared.num_done < n) { - shared.cv.Wait(); - } - shared.mu.Unlock(); - - for (int i = 1; i < n; i++) { - arg[0].thread->stats.Merge(arg[i].thread->stats); - } - arg[0].thread->stats.Report(name); - - for (int i = 0; i < n; i++) { - delete arg[i].thread; - } - delete[] arg; - } - - void Crc32c(ThreadState* thread) { - // Checksum about 500MB of data total - const int size = 4096; - const char* label = "(4K per op)"; - std::string data(size, 'x'); - int64_t bytes = 0; - uint32_t crc = 0; - while (bytes < 500 * 1048576) { - crc = crc32c::Value(data.data(), size); - thread->stats.FinishedSingleOp(); - bytes += size; - } - // Print so result is not dead - fprintf(stderr, "... crc=0x%x\r", static_cast(crc)); - - thread->stats.AddBytes(bytes); - thread->stats.AddMessage(label); - } - - void AcquireLoad(ThreadState* thread) { - int dummy; - port::AtomicPointer ap(&dummy); - int count = 0; - void *ptr = NULL; - thread->stats.AddMessage("(each op is 1000 loads)"); - while (count < 100000) { - for (int i = 0; i < 1000; i++) { - ptr = ap.Acquire_Load(); - } - count++; - thread->stats.FinishedSingleOp(); - } - if (ptr == NULL) exit(1); // Disable unused variable warning. - } - - void SnappyCompress(ThreadState* thread) { - RandomGenerator gen; - Slice input = gen.Generate(Options().block_size); - int64_t bytes = 0; - int64_t produced = 0; - bool ok = true; - std::string compressed; - while (ok && bytes < 1024 * 1048576) { // Compress 1G - ok = port::Snappy_Compress(input.data(), input.size(), &compressed); - produced += compressed.size(); - bytes += input.size(); - thread->stats.FinishedSingleOp(); - } - - if (!ok) { - thread->stats.AddMessage("(snappy failure)"); - } else { - char buf[100]; - snprintf(buf, sizeof(buf), "(output: %.1f%%)", - (produced * 100.0) / bytes); - thread->stats.AddMessage(buf); - thread->stats.AddBytes(bytes); - } - } - - void SnappyUncompress(ThreadState* thread) { - RandomGenerator gen; - Slice input = gen.Generate(Options().block_size); - std::string compressed; - bool ok = port::Snappy_Compress(input.data(), input.size(), &compressed); - int64_t bytes = 0; - char* uncompressed = new char[input.size()]; - while (ok && bytes < 1024 * 1048576) { // Compress 1G - ok = port::Snappy_Uncompress(compressed.data(), compressed.size(), - uncompressed); - bytes += input.size(); - thread->stats.FinishedSingleOp(); - } - delete[] uncompressed; - - if (!ok) { - thread->stats.AddMessage("(snappy failure)"); - } else { - thread->stats.AddBytes(bytes); - } - } - - void Open() { - assert(db_ == NULL); - Options options; - options.create_if_missing = !FLAGS_use_existing_db; - options.block_cache = cache_; - options.write_buffer_size = FLAGS_write_buffer_size; - options.max_open_files = FLAGS_open_files; - options.filter_policy = filter_policy_; - Status s = DB::Open(options, FLAGS_db, &db_); - if (!s.ok()) { - fprintf(stderr, "open error: %s\n", s.ToString().c_str()); - exit(1); - } - } - - void WriteSeq(ThreadState* thread) { - DoWrite(thread, true); - } - - void WriteRandom(ThreadState* thread) { - DoWrite(thread, false); - } - - void DoWrite(ThreadState* thread, bool seq) { - if (num_ != FLAGS_num) { - char msg[100]; - snprintf(msg, sizeof(msg), "(%d ops)", num_); - thread->stats.AddMessage(msg); - } - - RandomGenerator gen; - WriteBatch batch; - Status s; - int64_t bytes = 0; - for (int i = 0; i < num_; i += entries_per_batch_) { - batch.Clear(); - for (int j = 0; j < entries_per_batch_; j++) { - const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); - char key[100]; - snprintf(key, sizeof(key), "%016d", k); - batch.Put(key, gen.Generate(value_size_)); - bytes += value_size_ + strlen(key); - thread->stats.FinishedSingleOp(); - } - s = db_->Write(write_options_, &batch); - if (!s.ok()) { - fprintf(stderr, "put error: %s\n", s.ToString().c_str()); - exit(1); - } - } - thread->stats.AddBytes(bytes); - } - - void ReadSequential(ThreadState* thread) { - Iterator* iter = db_->NewIterator(ReadOptions()); - int i = 0; - int64_t bytes = 0; - for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) { - bytes += iter->key().size() + iter->value().size(); - thread->stats.FinishedSingleOp(); - ++i; - } - delete iter; - thread->stats.AddBytes(bytes); - } - - void ReadReverse(ThreadState* thread) { - Iterator* iter = db_->NewIterator(ReadOptions()); - int i = 0; - int64_t bytes = 0; - for (iter->SeekToLast(); i < reads_ && iter->Valid(); iter->Prev()) { - bytes += iter->key().size() + iter->value().size(); - thread->stats.FinishedSingleOp(); - ++i; - } - delete iter; - thread->stats.AddBytes(bytes); - } - - void ReadRandom(ThreadState* thread) { - ReadOptions options; - std::string value; - int found = 0; - for (int i = 0; i < reads_; i++) { - char key[100]; - const int k = thread->rand.Next() % FLAGS_num; - snprintf(key, sizeof(key), "%016d", k); - if (db_->Get(options, key, &value).ok()) { - found++; - } - thread->stats.FinishedSingleOp(); - } - char msg[100]; - snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_); - thread->stats.AddMessage(msg); - } - - void ReadMissing(ThreadState* thread) { - ReadOptions options; - std::string value; - for (int i = 0; i < reads_; i++) { - char key[100]; - const int k = thread->rand.Next() % FLAGS_num; - snprintf(key, sizeof(key), "%016d.", k); - db_->Get(options, key, &value); - thread->stats.FinishedSingleOp(); - } - } - - void ReadHot(ThreadState* thread) { - ReadOptions options; - std::string value; - const int range = (FLAGS_num + 99) / 100; - for (int i = 0; i < reads_; i++) { - char key[100]; - const int k = thread->rand.Next() % range; - snprintf(key, sizeof(key), "%016d", k); - db_->Get(options, key, &value); - thread->stats.FinishedSingleOp(); - } - } - - void SeekRandom(ThreadState* thread) { - ReadOptions options; - int found = 0; - for (int i = 0; i < reads_; i++) { - Iterator* iter = db_->NewIterator(options); - char key[100]; - const int k = thread->rand.Next() % FLAGS_num; - snprintf(key, sizeof(key), "%016d", k); - iter->Seek(key); - if (iter->Valid() && iter->key() == key) found++; - delete iter; - thread->stats.FinishedSingleOp(); - } - char msg[100]; - snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_); - thread->stats.AddMessage(msg); - } - - void DoDelete(ThreadState* thread, bool seq) { - RandomGenerator gen; - WriteBatch batch; - Status s; - for (int i = 0; i < num_; i += entries_per_batch_) { - batch.Clear(); - for (int j = 0; j < entries_per_batch_; j++) { - const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num); - char key[100]; - snprintf(key, sizeof(key), "%016d", k); - batch.Delete(key); - thread->stats.FinishedSingleOp(); - } - s = db_->Write(write_options_, &batch); - if (!s.ok()) { - fprintf(stderr, "del error: %s\n", s.ToString().c_str()); - exit(1); - } - } - } - - void DeleteSeq(ThreadState* thread) { - DoDelete(thread, true); - } - - void DeleteRandom(ThreadState* thread) { - DoDelete(thread, false); - } - - void ReadWhileWriting(ThreadState* thread) { - if (thread->tid > 0) { - ReadRandom(thread); - } else { - // Special thread that keeps writing until other threads are done. - RandomGenerator gen; - while (true) { - { - MutexLock l(&thread->shared->mu); - if (thread->shared->num_done + 1 >= thread->shared->num_initialized) { - // Other threads have finished - break; - } - } - - const int k = thread->rand.Next() % FLAGS_num; - char key[100]; - snprintf(key, sizeof(key), "%016d", k); - Status s = db_->Put(write_options_, key, gen.Generate(value_size_)); - if (!s.ok()) { - fprintf(stderr, "put error: %s\n", s.ToString().c_str()); - exit(1); - } - } - - // Do not count any of the preceding work/delay in stats. - thread->stats.Start(); - } - } - - void Compact(ThreadState* thread) { - db_->CompactRange(NULL, NULL); - } - - void PrintStats(const char* key) { - std::string stats; - if (!db_->GetProperty(key, &stats)) { - stats = "(failed)"; - } - fprintf(stdout, "\n%s\n", stats.c_str()); - } - - static void WriteToFile(void* arg, const char* buf, int n) { - reinterpret_cast(arg)->Append(Slice(buf, n)); - } - - void HeapProfile() { - char fname[100]; - snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_); - WritableFile* file; - Status s = Env::Default()->NewWritableFile(fname, &file); - if (!s.ok()) { - fprintf(stderr, "%s\n", s.ToString().c_str()); - return; - } - bool ok = port::GetHeapProfile(WriteToFile, file); - delete file; - if (!ok) { - fprintf(stderr, "heap profiling not supported\n"); - Env::Default()->DeleteFile(fname); - } - } -}; - -} // namespace leveldb - -int main(int argc, char** argv) { - FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; - FLAGS_open_files = leveldb::Options().max_open_files; - std::string default_db_path; - - for (int i = 1; i < argc; i++) { - double d; - int n; - char junk; - if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { - FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); - } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { - FLAGS_compression_ratio = d; - } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_histogram = n; - } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_use_existing_db = n; - } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { - FLAGS_num = n; - } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { - FLAGS_reads = n; - } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) { - FLAGS_threads = n; - } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { - FLAGS_value_size = n; - } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { - FLAGS_write_buffer_size = n; - } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { - FLAGS_cache_size = n; - } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) { - FLAGS_bloom_bits = n; - } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) { - FLAGS_open_files = n; - } else if (strncmp(argv[i], "--db=", 5) == 0) { - FLAGS_db = argv[i] + 5; - } else { - fprintf(stderr, "Invalid flag '%s'\n", argv[i]); - exit(1); - } - } - - // Choose a location for the test database if none given with --db= - if (FLAGS_db == NULL) { - leveldb::Env::Default()->GetTestDirectory(&default_db_path); - default_db_path += "/dbbench"; - FLAGS_db = default_db_path.c_str(); - } - - leveldb::Benchmark benchmark; - benchmark.Run(); - return 0; -} diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc deleted file mode 100644 index 49b95953b4..0000000000 --- a/src/leveldb/db/db_impl.cc +++ /dev/null @@ -1,1513 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/db_impl.h" - -#include -#include -#include -#include -#include -#include -#include "db/builder.h" -#include "db/db_iter.h" -#include "db/dbformat.h" -#include "db/filename.h" -#include "db/log_reader.h" -#include "db/log_writer.h" -#include "db/memtable.h" -#include "db/table_cache.h" -#include "db/version_set.h" -#include "db/write_batch_internal.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "leveldb/status.h" -#include "leveldb/table.h" -#include "leveldb/table_builder.h" -#include "port/port.h" -#include "table/block.h" -#include "table/merger.h" -#include "table/two_level_iterator.h" -#include "util/coding.h" -#include "util/logging.h" -#include "util/mutexlock.h" - -namespace leveldb { - -const int kNumNonTableCacheFiles = 10; - -// Information kept for every waiting writer -struct DBImpl::Writer { - Status status; - WriteBatch* batch; - bool sync; - bool done; - port::CondVar cv; - - explicit Writer(port::Mutex* mu) : cv(mu) { } -}; - -struct DBImpl::CompactionState { - Compaction* const compaction; - - // Sequence numbers < smallest_snapshot are not significant since we - // will never have to service a snapshot below smallest_snapshot. - // Therefore if we have seen a sequence number S <= smallest_snapshot, - // we can drop all entries for the same key with sequence numbers < S. - SequenceNumber smallest_snapshot; - - // Files produced by compaction - struct Output { - uint64_t number; - uint64_t file_size; - InternalKey smallest, largest; - }; - std::vector outputs; - - // State kept for output being generated - WritableFile* outfile; - TableBuilder* builder; - - uint64_t total_bytes; - - Output* current_output() { return &outputs[outputs.size()-1]; } - - explicit CompactionState(Compaction* c) - : compaction(c), - outfile(NULL), - builder(NULL), - total_bytes(0) { - } -}; - -// Fix user-supplied options to be reasonable -template -static void ClipToRange(T* ptr, V minvalue, V maxvalue) { - if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; - if (static_cast(*ptr) < minvalue) *ptr = minvalue; -} -Options SanitizeOptions(const std::string& dbname, - const InternalKeyComparator* icmp, - const InternalFilterPolicy* ipolicy, - const Options& src) { - Options result = src; - result.comparator = icmp; - result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL; - ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); - ClipToRange(&result.write_buffer_size, 64<<10, 1<<30); - ClipToRange(&result.block_size, 1<<10, 4<<20); - if (result.info_log == NULL) { - // Open a log file in the same directory as the db - src.env->CreateDir(dbname); // In case it does not exist - src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname)); - Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log); - if (!s.ok()) { - // No place suitable for logging - result.info_log = NULL; - } - } - if (result.block_cache == NULL) { - result.block_cache = NewLRUCache(8 << 20); - } - return result; -} - -DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) - : env_(raw_options.env), - internal_comparator_(raw_options.comparator), - internal_filter_policy_(raw_options.filter_policy), - options_(SanitizeOptions(dbname, &internal_comparator_, - &internal_filter_policy_, raw_options)), - owns_info_log_(options_.info_log != raw_options.info_log), - owns_cache_(options_.block_cache != raw_options.block_cache), - dbname_(dbname), - db_lock_(NULL), - shutting_down_(NULL), - bg_cv_(&mutex_), - mem_(new MemTable(internal_comparator_)), - imm_(NULL), - logfile_(NULL), - logfile_number_(0), - log_(NULL), - seed_(0), - tmp_batch_(new WriteBatch), - bg_compaction_scheduled_(false), - manual_compaction_(NULL) { - mem_->Ref(); - has_imm_.Release_Store(NULL); - - // Reserve ten files or so for other uses and give the rest to TableCache. - const int table_cache_size = options_.max_open_files - kNumNonTableCacheFiles; - table_cache_ = new TableCache(dbname_, &options_, table_cache_size); - - versions_ = new VersionSet(dbname_, &options_, table_cache_, - &internal_comparator_); -} - -DBImpl::~DBImpl() { - // Wait for background work to finish - mutex_.Lock(); - shutting_down_.Release_Store(this); // Any non-NULL value is ok - while (bg_compaction_scheduled_) { - bg_cv_.Wait(); - } - mutex_.Unlock(); - - if (db_lock_ != NULL) { - env_->UnlockFile(db_lock_); - } - - delete versions_; - if (mem_ != NULL) mem_->Unref(); - if (imm_ != NULL) imm_->Unref(); - delete tmp_batch_; - delete log_; - delete logfile_; - delete table_cache_; - - if (owns_info_log_) { - delete options_.info_log; - } - if (owns_cache_) { - delete options_.block_cache; - } -} - -Status DBImpl::NewDB() { - VersionEdit new_db; - new_db.SetComparatorName(user_comparator()->Name()); - new_db.SetLogNumber(0); - new_db.SetNextFile(2); - new_db.SetLastSequence(0); - - const std::string manifest = DescriptorFileName(dbname_, 1); - WritableFile* file; - Status s = env_->NewWritableFile(manifest, &file); - if (!s.ok()) { - return s; - } - { - log::Writer log(file); - std::string record; - new_db.EncodeTo(&record); - s = log.AddRecord(record); - if (s.ok()) { - s = file->Close(); - } - } - delete file; - if (s.ok()) { - // Make "CURRENT" file that points to the new manifest file. - s = SetCurrentFile(env_, dbname_, 1); - } else { - env_->DeleteFile(manifest); - } - return s; -} - -void DBImpl::MaybeIgnoreError(Status* s) const { - if (s->ok() || options_.paranoid_checks) { - // No change needed - } else { - Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); - *s = Status::OK(); - } -} - -void DBImpl::DeleteObsoleteFiles() { - if (!bg_error_.ok()) { - // After a background error, we don't know whether a new version may - // or may not have been committed, so we cannot safely garbage collect. - return; - } - - // Make a set of all of the live files - std::set live = pending_outputs_; - versions_->AddLiveFiles(&live); - - std::vector filenames; - env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose - uint64_t number; - FileType type; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type)) { - bool keep = true; - switch (type) { - case kLogFile: - keep = ((number >= versions_->LogNumber()) || - (number == versions_->PrevLogNumber())); - break; - case kDescriptorFile: - // Keep my manifest file, and any newer incarnations' - // (in case there is a race that allows other incarnations) - keep = (number >= versions_->ManifestFileNumber()); - break; - case kTableFile: - keep = (live.find(number) != live.end()); - break; - case kTempFile: - // Any temp files that are currently being written to must - // be recorded in pending_outputs_, which is inserted into "live" - keep = (live.find(number) != live.end()); - break; - case kCurrentFile: - case kDBLockFile: - case kInfoLogFile: - keep = true; - break; - } - - if (!keep) { - if (type == kTableFile) { - table_cache_->Evict(number); - } - Log(options_.info_log, "Delete type=%d #%lld\n", - int(type), - static_cast(number)); - env_->DeleteFile(dbname_ + "/" + filenames[i]); - } - } - } -} - -Status DBImpl::Recover(VersionEdit* edit) { - mutex_.AssertHeld(); - - // Ignore error from CreateDir since the creation of the DB is - // committed only when the descriptor is created, and this directory - // may already exist from a previous failed creation attempt. - env_->CreateDir(dbname_); - assert(db_lock_ == NULL); - Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); - if (!s.ok()) { - return s; - } - - if (!env_->FileExists(CurrentFileName(dbname_))) { - if (options_.create_if_missing) { - s = NewDB(); - if (!s.ok()) { - return s; - } - } else { - return Status::InvalidArgument( - dbname_, "does not exist (create_if_missing is false)"); - } - } else { - if (options_.error_if_exists) { - return Status::InvalidArgument( - dbname_, "exists (error_if_exists is true)"); - } - } - - s = versions_->Recover(); - if (s.ok()) { - SequenceNumber max_sequence(0); - - // Recover from all newer log files than the ones named in the - // descriptor (new log files may have been added by the previous - // incarnation without registering them in the descriptor). - // - // Note that PrevLogNumber() is no longer used, but we pay - // attention to it in case we are recovering a database - // produced by an older version of leveldb. - const uint64_t min_log = versions_->LogNumber(); - const uint64_t prev_log = versions_->PrevLogNumber(); - std::vector filenames; - s = env_->GetChildren(dbname_, &filenames); - if (!s.ok()) { - return s; - } - std::set expected; - versions_->AddLiveFiles(&expected); - uint64_t number; - FileType type; - std::vector logs; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type)) { - expected.erase(number); - if (type == kLogFile && ((number >= min_log) || (number == prev_log))) - logs.push_back(number); - } - } - if (!expected.empty()) { - char buf[50]; - snprintf(buf, sizeof(buf), "%d missing files; e.g.", - static_cast(expected.size())); - return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin()))); - } - - // Recover in the order in which the logs were generated - std::sort(logs.begin(), logs.end()); - for (size_t i = 0; i < logs.size(); i++) { - s = RecoverLogFile(logs[i], edit, &max_sequence); - - // The previous incarnation may not have written any MANIFEST - // records after allocating this log number. So we manually - // update the file number allocation counter in VersionSet. - versions_->MarkFileNumberUsed(logs[i]); - } - - if (s.ok()) { - if (versions_->LastSequence() < max_sequence) { - versions_->SetLastSequence(max_sequence); - } - } - } - - return s; -} - -Status DBImpl::RecoverLogFile(uint64_t log_number, - VersionEdit* edit, - SequenceNumber* max_sequence) { - struct LogReporter : public log::Reader::Reporter { - Env* env; - Logger* info_log; - const char* fname; - Status* status; // NULL if options_.paranoid_checks==false - virtual void Corruption(size_t bytes, const Status& s) { - Log(info_log, "%s%s: dropping %d bytes; %s", - (this->status == NULL ? "(ignoring error) " : ""), - fname, static_cast(bytes), s.ToString().c_str()); - if (this->status != NULL && this->status->ok()) *this->status = s; - } - }; - - mutex_.AssertHeld(); - - // Open the log file - std::string fname = LogFileName(dbname_, log_number); - SequentialFile* file; - Status status = env_->NewSequentialFile(fname, &file); - if (!status.ok()) { - MaybeIgnoreError(&status); - return status; - } - - // Create the log reader. - LogReporter reporter; - reporter.env = env_; - reporter.info_log = options_.info_log; - reporter.fname = fname.c_str(); - reporter.status = (options_.paranoid_checks ? &status : NULL); - // We intentionally make log::Reader do checksumming even if - // paranoid_checks==false so that corruptions cause entire commits - // to be skipped instead of propagating bad information (like overly - // large sequence numbers). - log::Reader reader(file, &reporter, true/*checksum*/, - 0/*initial_offset*/); - Log(options_.info_log, "Recovering log #%llu", - (unsigned long long) log_number); - - // Read all the records and add to a memtable - std::string scratch; - Slice record; - WriteBatch batch; - MemTable* mem = NULL; - while (reader.ReadRecord(&record, &scratch) && - status.ok()) { - if (record.size() < 12) { - reporter.Corruption( - record.size(), Status::Corruption("log record too small")); - continue; - } - WriteBatchInternal::SetContents(&batch, record); - - if (mem == NULL) { - mem = new MemTable(internal_comparator_); - mem->Ref(); - } - status = WriteBatchInternal::InsertInto(&batch, mem); - MaybeIgnoreError(&status); - if (!status.ok()) { - break; - } - const SequenceNumber last_seq = - WriteBatchInternal::Sequence(&batch) + - WriteBatchInternal::Count(&batch) - 1; - if (last_seq > *max_sequence) { - *max_sequence = last_seq; - } - - if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) { - status = WriteLevel0Table(mem, edit, NULL); - if (!status.ok()) { - // Reflect errors immediately so that conditions like full - // file-systems cause the DB::Open() to fail. - break; - } - mem->Unref(); - mem = NULL; - } - } - - if (status.ok() && mem != NULL) { - status = WriteLevel0Table(mem, edit, NULL); - // Reflect errors immediately so that conditions like full - // file-systems cause the DB::Open() to fail. - } - - if (mem != NULL) mem->Unref(); - delete file; - return status; -} - -Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, - Version* base) { - mutex_.AssertHeld(); - const uint64_t start_micros = env_->NowMicros(); - FileMetaData meta; - meta.number = versions_->NewFileNumber(); - pending_outputs_.insert(meta.number); - Iterator* iter = mem->NewIterator(); - Log(options_.info_log, "Level-0 table #%llu: started", - (unsigned long long) meta.number); - - Status s; - { - mutex_.Unlock(); - s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); - mutex_.Lock(); - } - - Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", - (unsigned long long) meta.number, - (unsigned long long) meta.file_size, - s.ToString().c_str()); - delete iter; - pending_outputs_.erase(meta.number); - - - // Note that if file_size is zero, the file has been deleted and - // should not be added to the manifest. - int level = 0; - if (s.ok() && meta.file_size > 0) { - const Slice min_user_key = meta.smallest.user_key(); - const Slice max_user_key = meta.largest.user_key(); - if (base != NULL) { - level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); - } - edit->AddFile(level, meta.number, meta.file_size, - meta.smallest, meta.largest); - } - - CompactionStats stats; - stats.micros = env_->NowMicros() - start_micros; - stats.bytes_written = meta.file_size; - stats_[level].Add(stats); - return s; -} - -void DBImpl::CompactMemTable() { - mutex_.AssertHeld(); - assert(imm_ != NULL); - - // Save the contents of the memtable as a new Table - VersionEdit edit; - Version* base = versions_->current(); - base->Ref(); - Status s = WriteLevel0Table(imm_, &edit, base); - base->Unref(); - - if (s.ok() && shutting_down_.Acquire_Load()) { - s = Status::IOError("Deleting DB during memtable compaction"); - } - - // Replace immutable memtable with the generated Table - if (s.ok()) { - edit.SetPrevLogNumber(0); - edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed - s = versions_->LogAndApply(&edit, &mutex_); - } - - if (s.ok()) { - // Commit to the new state - imm_->Unref(); - imm_ = NULL; - has_imm_.Release_Store(NULL); - DeleteObsoleteFiles(); - } else { - RecordBackgroundError(s); - } -} - -void DBImpl::CompactRange(const Slice* begin, const Slice* end) { - int max_level_with_files = 1; - { - MutexLock l(&mutex_); - Version* base = versions_->current(); - for (int level = 1; level < config::kNumLevels; level++) { - if (base->OverlapInLevel(level, begin, end)) { - max_level_with_files = level; - } - } - } - TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap - for (int level = 0; level < max_level_with_files; level++) { - TEST_CompactRange(level, begin, end); - } -} - -void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) { - assert(level >= 0); - assert(level + 1 < config::kNumLevels); - - InternalKey begin_storage, end_storage; - - ManualCompaction manual; - manual.level = level; - manual.done = false; - if (begin == NULL) { - manual.begin = NULL; - } else { - begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); - manual.begin = &begin_storage; - } - if (end == NULL) { - manual.end = NULL; - } else { - end_storage = InternalKey(*end, 0, static_cast(0)); - manual.end = &end_storage; - } - - MutexLock l(&mutex_); - while (!manual.done && !shutting_down_.Acquire_Load() && bg_error_.ok()) { - if (manual_compaction_ == NULL) { // Idle - manual_compaction_ = &manual; - MaybeScheduleCompaction(); - } else { // Running either my compaction or another compaction. - bg_cv_.Wait(); - } - } - if (manual_compaction_ == &manual) { - // Cancel my manual compaction since we aborted early for some reason. - manual_compaction_ = NULL; - } -} - -Status DBImpl::TEST_CompactMemTable() { - // NULL batch means just wait for earlier writes to be done - Status s = Write(WriteOptions(), NULL); - if (s.ok()) { - // Wait until the compaction completes - MutexLock l(&mutex_); - while (imm_ != NULL && bg_error_.ok()) { - bg_cv_.Wait(); - } - if (imm_ != NULL) { - s = bg_error_; - } - } - return s; -} - -void DBImpl::RecordBackgroundError(const Status& s) { - mutex_.AssertHeld(); - if (bg_error_.ok()) { - bg_error_ = s; - bg_cv_.SignalAll(); - } -} - -void DBImpl::MaybeScheduleCompaction() { - mutex_.AssertHeld(); - if (bg_compaction_scheduled_) { - // Already scheduled - } else if (shutting_down_.Acquire_Load()) { - // DB is being deleted; no more background compactions - } else if (!bg_error_.ok()) { - // Already got an error; no more changes - } else if (imm_ == NULL && - manual_compaction_ == NULL && - !versions_->NeedsCompaction()) { - // No work to be done - } else { - bg_compaction_scheduled_ = true; - env_->Schedule(&DBImpl::BGWork, this); - } -} - -void DBImpl::BGWork(void* db) { - reinterpret_cast(db)->BackgroundCall(); -} - -void DBImpl::BackgroundCall() { - MutexLock l(&mutex_); - assert(bg_compaction_scheduled_); - if (shutting_down_.Acquire_Load()) { - // No more background work when shutting down. - } else if (!bg_error_.ok()) { - // No more background work after a background error. - } else { - BackgroundCompaction(); - } - - bg_compaction_scheduled_ = false; - - // Previous compaction may have produced too many files in a level, - // so reschedule another compaction if needed. - MaybeScheduleCompaction(); - bg_cv_.SignalAll(); -} - -void DBImpl::BackgroundCompaction() { - mutex_.AssertHeld(); - - if (imm_ != NULL) { - CompactMemTable(); - return; - } - - Compaction* c; - bool is_manual = (manual_compaction_ != NULL); - InternalKey manual_end; - if (is_manual) { - ManualCompaction* m = manual_compaction_; - c = versions_->CompactRange(m->level, m->begin, m->end); - m->done = (c == NULL); - if (c != NULL) { - manual_end = c->input(0, c->num_input_files(0) - 1)->largest; - } - Log(options_.info_log, - "Manual compaction at level-%d from %s .. %s; will stop at %s\n", - m->level, - (m->begin ? m->begin->DebugString().c_str() : "(begin)"), - (m->end ? m->end->DebugString().c_str() : "(end)"), - (m->done ? "(end)" : manual_end.DebugString().c_str())); - } else { - c = versions_->PickCompaction(); - } - - Status status; - if (c == NULL) { - // Nothing to do - } else if (!is_manual && c->IsTrivialMove()) { - // Move file to next level - assert(c->num_input_files(0) == 1); - FileMetaData* f = c->input(0, 0); - c->edit()->DeleteFile(c->level(), f->number); - c->edit()->AddFile(c->level() + 1, f->number, f->file_size, - f->smallest, f->largest); - status = versions_->LogAndApply(c->edit(), &mutex_); - if (!status.ok()) { - RecordBackgroundError(status); - } - VersionSet::LevelSummaryStorage tmp; - Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", - static_cast(f->number), - c->level() + 1, - static_cast(f->file_size), - status.ToString().c_str(), - versions_->LevelSummary(&tmp)); - } else { - CompactionState* compact = new CompactionState(c); - status = DoCompactionWork(compact); - if (!status.ok()) { - RecordBackgroundError(status); - } - CleanupCompaction(compact); - c->ReleaseInputs(); - DeleteObsoleteFiles(); - } - delete c; - - if (status.ok()) { - // Done - } else if (shutting_down_.Acquire_Load()) { - // Ignore compaction errors found during shutting down - } else { - Log(options_.info_log, - "Compaction error: %s", status.ToString().c_str()); - } - - if (is_manual) { - ManualCompaction* m = manual_compaction_; - if (!status.ok()) { - m->done = true; - } - if (!m->done) { - // We only compacted part of the requested range. Update *m - // to the range that is left to be compacted. - m->tmp_storage = manual_end; - m->begin = &m->tmp_storage; - } - manual_compaction_ = NULL; - } -} - -void DBImpl::CleanupCompaction(CompactionState* compact) { - mutex_.AssertHeld(); - if (compact->builder != NULL) { - // May happen if we get a shutdown call in the middle of compaction - compact->builder->Abandon(); - delete compact->builder; - } else { - assert(compact->outfile == NULL); - } - delete compact->outfile; - for (size_t i = 0; i < compact->outputs.size(); i++) { - const CompactionState::Output& out = compact->outputs[i]; - pending_outputs_.erase(out.number); - } - delete compact; -} - -Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { - assert(compact != NULL); - assert(compact->builder == NULL); - uint64_t file_number; - { - mutex_.Lock(); - file_number = versions_->NewFileNumber(); - pending_outputs_.insert(file_number); - CompactionState::Output out; - out.number = file_number; - out.smallest.Clear(); - out.largest.Clear(); - compact->outputs.push_back(out); - mutex_.Unlock(); - } - - // Make the output file - std::string fname = TableFileName(dbname_, file_number); - Status s = env_->NewWritableFile(fname, &compact->outfile); - if (s.ok()) { - compact->builder = new TableBuilder(options_, compact->outfile); - } - return s; -} - -Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, - Iterator* input) { - assert(compact != NULL); - assert(compact->outfile != NULL); - assert(compact->builder != NULL); - - const uint64_t output_number = compact->current_output()->number; - assert(output_number != 0); - - // Check for iterator errors - Status s = input->status(); - const uint64_t current_entries = compact->builder->NumEntries(); - if (s.ok()) { - s = compact->builder->Finish(); - } else { - compact->builder->Abandon(); - } - const uint64_t current_bytes = compact->builder->FileSize(); - compact->current_output()->file_size = current_bytes; - compact->total_bytes += current_bytes; - delete compact->builder; - compact->builder = NULL; - - // Finish and check for file errors - if (s.ok()) { - s = compact->outfile->Sync(); - } - if (s.ok()) { - s = compact->outfile->Close(); - } - delete compact->outfile; - compact->outfile = NULL; - - if (s.ok() && current_entries > 0) { - // Verify that the table is usable - Iterator* iter = table_cache_->NewIterator(ReadOptions(), - output_number, - current_bytes); - s = iter->status(); - delete iter; - if (s.ok()) { - Log(options_.info_log, - "Generated table #%llu: %lld keys, %lld bytes", - (unsigned long long) output_number, - (unsigned long long) current_entries, - (unsigned long long) current_bytes); - } - } - return s; -} - - -Status DBImpl::InstallCompactionResults(CompactionState* compact) { - mutex_.AssertHeld(); - Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", - compact->compaction->num_input_files(0), - compact->compaction->level(), - compact->compaction->num_input_files(1), - compact->compaction->level() + 1, - static_cast(compact->total_bytes)); - - // Add compaction outputs - compact->compaction->AddInputDeletions(compact->compaction->edit()); - const int level = compact->compaction->level(); - for (size_t i = 0; i < compact->outputs.size(); i++) { - const CompactionState::Output& out = compact->outputs[i]; - compact->compaction->edit()->AddFile( - level + 1, - out.number, out.file_size, out.smallest, out.largest); - } - return versions_->LogAndApply(compact->compaction->edit(), &mutex_); -} - -Status DBImpl::DoCompactionWork(CompactionState* compact) { - const uint64_t start_micros = env_->NowMicros(); - int64_t imm_micros = 0; // Micros spent doing imm_ compactions - - Log(options_.info_log, "Compacting %d@%d + %d@%d files", - compact->compaction->num_input_files(0), - compact->compaction->level(), - compact->compaction->num_input_files(1), - compact->compaction->level() + 1); - - assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); - assert(compact->builder == NULL); - assert(compact->outfile == NULL); - if (snapshots_.empty()) { - compact->smallest_snapshot = versions_->LastSequence(); - } else { - compact->smallest_snapshot = snapshots_.oldest()->number_; - } - - // Release mutex while we're actually doing the compaction work - mutex_.Unlock(); - - Iterator* input = versions_->MakeInputIterator(compact->compaction); - input->SeekToFirst(); - Status status; - ParsedInternalKey ikey; - std::string current_user_key; - bool has_current_user_key = false; - SequenceNumber last_sequence_for_key = kMaxSequenceNumber; - for (; input->Valid() && !shutting_down_.Acquire_Load(); ) { - // Prioritize immutable compaction work - if (has_imm_.NoBarrier_Load() != NULL) { - const uint64_t imm_start = env_->NowMicros(); - mutex_.Lock(); - if (imm_ != NULL) { - CompactMemTable(); - bg_cv_.SignalAll(); // Wakeup MakeRoomForWrite() if necessary - } - mutex_.Unlock(); - imm_micros += (env_->NowMicros() - imm_start); - } - - Slice key = input->key(); - if (compact->compaction->ShouldStopBefore(key) && - compact->builder != NULL) { - status = FinishCompactionOutputFile(compact, input); - if (!status.ok()) { - break; - } - } - - // Handle key/value, add to state, etc. - bool drop = false; - if (!ParseInternalKey(key, &ikey)) { - // Do not hide error keys - current_user_key.clear(); - has_current_user_key = false; - last_sequence_for_key = kMaxSequenceNumber; - } else { - if (!has_current_user_key || - user_comparator()->Compare(ikey.user_key, - Slice(current_user_key)) != 0) { - // First occurrence of this user key - current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); - has_current_user_key = true; - last_sequence_for_key = kMaxSequenceNumber; - } - - if (last_sequence_for_key <= compact->smallest_snapshot) { - // Hidden by an newer entry for same user key - drop = true; // (A) - } else if (ikey.type == kTypeDeletion && - ikey.sequence <= compact->smallest_snapshot && - compact->compaction->IsBaseLevelForKey(ikey.user_key)) { - // For this user key: - // (1) there is no data in higher levels - // (2) data in lower levels will have larger sequence numbers - // (3) data in layers that are being compacted here and have - // smaller sequence numbers will be dropped in the next - // few iterations of this loop (by rule (A) above). - // Therefore this deletion marker is obsolete and can be dropped. - drop = true; - } - - last_sequence_for_key = ikey.sequence; - } -#if 0 - Log(options_.info_log, - " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " - "%d smallest_snapshot: %d", - ikey.user_key.ToString().c_str(), - (int)ikey.sequence, ikey.type, kTypeValue, drop, - compact->compaction->IsBaseLevelForKey(ikey.user_key), - (int)last_sequence_for_key, (int)compact->smallest_snapshot); -#endif - - if (!drop) { - // Open output file if necessary - if (compact->builder == NULL) { - status = OpenCompactionOutputFile(compact); - if (!status.ok()) { - break; - } - } - if (compact->builder->NumEntries() == 0) { - compact->current_output()->smallest.DecodeFrom(key); - } - compact->current_output()->largest.DecodeFrom(key); - compact->builder->Add(key, input->value()); - - // Close output file if it is big enough - if (compact->builder->FileSize() >= - compact->compaction->MaxOutputFileSize()) { - status = FinishCompactionOutputFile(compact, input); - if (!status.ok()) { - break; - } - } - } - - input->Next(); - } - - if (status.ok() && shutting_down_.Acquire_Load()) { - status = Status::IOError("Deleting DB during compaction"); - } - if (status.ok() && compact->builder != NULL) { - status = FinishCompactionOutputFile(compact, input); - } - if (status.ok()) { - status = input->status(); - } - delete input; - input = NULL; - - CompactionStats stats; - stats.micros = env_->NowMicros() - start_micros - imm_micros; - for (int which = 0; which < 2; which++) { - for (int i = 0; i < compact->compaction->num_input_files(which); i++) { - stats.bytes_read += compact->compaction->input(which, i)->file_size; - } - } - for (size_t i = 0; i < compact->outputs.size(); i++) { - stats.bytes_written += compact->outputs[i].file_size; - } - - mutex_.Lock(); - stats_[compact->compaction->level() + 1].Add(stats); - - if (status.ok()) { - status = InstallCompactionResults(compact); - } - if (!status.ok()) { - RecordBackgroundError(status); - } - VersionSet::LevelSummaryStorage tmp; - Log(options_.info_log, - "compacted to: %s", versions_->LevelSummary(&tmp)); - return status; -} - -namespace { -struct IterState { - port::Mutex* mu; - Version* version; - MemTable* mem; - MemTable* imm; -}; - -static void CleanupIteratorState(void* arg1, void* arg2) { - IterState* state = reinterpret_cast(arg1); - state->mu->Lock(); - state->mem->Unref(); - if (state->imm != NULL) state->imm->Unref(); - state->version->Unref(); - state->mu->Unlock(); - delete state; -} -} // namespace - -Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, - SequenceNumber* latest_snapshot, - uint32_t* seed) { - IterState* cleanup = new IterState; - mutex_.Lock(); - *latest_snapshot = versions_->LastSequence(); - - // Collect together all needed child iterators - std::vector list; - list.push_back(mem_->NewIterator()); - mem_->Ref(); - if (imm_ != NULL) { - list.push_back(imm_->NewIterator()); - imm_->Ref(); - } - versions_->current()->AddIterators(options, &list); - Iterator* internal_iter = - NewMergingIterator(&internal_comparator_, &list[0], list.size()); - versions_->current()->Ref(); - - cleanup->mu = &mutex_; - cleanup->mem = mem_; - cleanup->imm = imm_; - cleanup->version = versions_->current(); - internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, NULL); - - *seed = ++seed_; - mutex_.Unlock(); - return internal_iter; -} - -Iterator* DBImpl::TEST_NewInternalIterator() { - SequenceNumber ignored; - uint32_t ignored_seed; - return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed); -} - -int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { - MutexLock l(&mutex_); - return versions_->MaxNextLevelOverlappingBytes(); -} - -Status DBImpl::Get(const ReadOptions& options, - const Slice& key, - std::string* value) { - Status s; - MutexLock l(&mutex_); - SequenceNumber snapshot; - if (options.snapshot != NULL) { - snapshot = reinterpret_cast(options.snapshot)->number_; - } else { - snapshot = versions_->LastSequence(); - } - - MemTable* mem = mem_; - MemTable* imm = imm_; - Version* current = versions_->current(); - mem->Ref(); - if (imm != NULL) imm->Ref(); - current->Ref(); - - bool have_stat_update = false; - Version::GetStats stats; - - // Unlock while reading from files and memtables - { - mutex_.Unlock(); - // First look in the memtable, then in the immutable memtable (if any). - LookupKey lkey(key, snapshot); - if (mem->Get(lkey, value, &s)) { - // Done - } else if (imm != NULL && imm->Get(lkey, value, &s)) { - // Done - } else { - s = current->Get(options, lkey, value, &stats); - have_stat_update = true; - } - mutex_.Lock(); - } - - if (have_stat_update && current->UpdateStats(stats)) { - MaybeScheduleCompaction(); - } - mem->Unref(); - if (imm != NULL) imm->Unref(); - current->Unref(); - return s; -} - -Iterator* DBImpl::NewIterator(const ReadOptions& options) { - SequenceNumber latest_snapshot; - uint32_t seed; - Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed); - return NewDBIterator( - this, user_comparator(), iter, - (options.snapshot != NULL - ? reinterpret_cast(options.snapshot)->number_ - : latest_snapshot), - seed); -} - -void DBImpl::RecordReadSample(Slice key) { - MutexLock l(&mutex_); - if (versions_->current()->RecordReadSample(key)) { - MaybeScheduleCompaction(); - } -} - -const Snapshot* DBImpl::GetSnapshot() { - MutexLock l(&mutex_); - return snapshots_.New(versions_->LastSequence()); -} - -void DBImpl::ReleaseSnapshot(const Snapshot* s) { - MutexLock l(&mutex_); - snapshots_.Delete(reinterpret_cast(s)); -} - -// Convenience methods -Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { - return DB::Put(o, key, val); -} - -Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { - return DB::Delete(options, key); -} - -Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) { - Writer w(&mutex_); - w.batch = my_batch; - w.sync = options.sync; - w.done = false; - - MutexLock l(&mutex_); - writers_.push_back(&w); - while (!w.done && &w != writers_.front()) { - w.cv.Wait(); - } - if (w.done) { - return w.status; - } - - // May temporarily unlock and wait. - Status status = MakeRoomForWrite(my_batch == NULL); - uint64_t last_sequence = versions_->LastSequence(); - Writer* last_writer = &w; - if (status.ok() && my_batch != NULL) { // NULL batch is for compactions - WriteBatch* updates = BuildBatchGroup(&last_writer); - WriteBatchInternal::SetSequence(updates, last_sequence + 1); - last_sequence += WriteBatchInternal::Count(updates); - - // Add to log and apply to memtable. We can release the lock - // during this phase since &w is currently responsible for logging - // and protects against concurrent loggers and concurrent writes - // into mem_. - { - mutex_.Unlock(); - status = log_->AddRecord(WriteBatchInternal::Contents(updates)); - bool sync_error = false; - if (status.ok() && options.sync) { - status = logfile_->Sync(); - if (!status.ok()) { - sync_error = true; - } - } - if (status.ok()) { - status = WriteBatchInternal::InsertInto(updates, mem_); - } - mutex_.Lock(); - if (sync_error) { - // The state of the log file is indeterminate: the log record we - // just added may or may not show up when the DB is re-opened. - // So we force the DB into a mode where all future writes fail. - RecordBackgroundError(status); - } - } - if (updates == tmp_batch_) tmp_batch_->Clear(); - - versions_->SetLastSequence(last_sequence); - } - - while (true) { - Writer* ready = writers_.front(); - writers_.pop_front(); - if (ready != &w) { - ready->status = status; - ready->done = true; - ready->cv.Signal(); - } - if (ready == last_writer) break; - } - - // Notify new head of write queue - if (!writers_.empty()) { - writers_.front()->cv.Signal(); - } - - return status; -} - -// REQUIRES: Writer list must be non-empty -// REQUIRES: First writer must have a non-NULL batch -WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { - assert(!writers_.empty()); - Writer* first = writers_.front(); - WriteBatch* result = first->batch; - assert(result != NULL); - - size_t size = WriteBatchInternal::ByteSize(first->batch); - - // Allow the group to grow up to a maximum size, but if the - // original write is small, limit the growth so we do not slow - // down the small write too much. - size_t max_size = 1 << 20; - if (size <= (128<<10)) { - max_size = size + (128<<10); - } - - *last_writer = first; - std::deque::iterator iter = writers_.begin(); - ++iter; // Advance past "first" - for (; iter != writers_.end(); ++iter) { - Writer* w = *iter; - if (w->sync && !first->sync) { - // Do not include a sync write into a batch handled by a non-sync write. - break; - } - - if (w->batch != NULL) { - size += WriteBatchInternal::ByteSize(w->batch); - if (size > max_size) { - // Do not make batch too big - break; - } - - // Append to *result - if (result == first->batch) { - // Switch to temporary batch instead of disturbing caller's batch - result = tmp_batch_; - assert(WriteBatchInternal::Count(result) == 0); - WriteBatchInternal::Append(result, first->batch); - } - WriteBatchInternal::Append(result, w->batch); - } - *last_writer = w; - } - return result; -} - -// REQUIRES: mutex_ is held -// REQUIRES: this thread is currently at the front of the writer queue -Status DBImpl::MakeRoomForWrite(bool force) { - mutex_.AssertHeld(); - assert(!writers_.empty()); - bool allow_delay = !force; - Status s; - while (true) { - if (!bg_error_.ok()) { - // Yield previous error - s = bg_error_; - break; - } else if ( - allow_delay && - versions_->NumLevelFiles(0) >= config::kL0_SlowdownWritesTrigger) { - // We are getting close to hitting a hard limit on the number of - // L0 files. Rather than delaying a single write by several - // seconds when we hit the hard limit, start delaying each - // individual write by 1ms to reduce latency variance. Also, - // this delay hands over some CPU to the compaction thread in - // case it is sharing the same core as the writer. - mutex_.Unlock(); - env_->SleepForMicroseconds(1000); - allow_delay = false; // Do not delay a single write more than once - mutex_.Lock(); - } else if (!force && - (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { - // There is room in current memtable - break; - } else if (imm_ != NULL) { - // We have filled up the current memtable, but the previous - // one is still being compacted, so we wait. - Log(options_.info_log, "Current memtable full; waiting...\n"); - bg_cv_.Wait(); - } else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) { - // There are too many level-0 files. - Log(options_.info_log, "Too many L0 files; waiting...\n"); - bg_cv_.Wait(); - } else { - // Attempt to switch to a new memtable and trigger compaction of old - assert(versions_->PrevLogNumber() == 0); - uint64_t new_log_number = versions_->NewFileNumber(); - WritableFile* lfile = NULL; - s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); - if (!s.ok()) { - // Avoid chewing through file number space in a tight loop. - versions_->ReuseFileNumber(new_log_number); - break; - } - delete log_; - delete logfile_; - logfile_ = lfile; - logfile_number_ = new_log_number; - log_ = new log::Writer(lfile); - imm_ = mem_; - has_imm_.Release_Store(imm_); - mem_ = new MemTable(internal_comparator_); - mem_->Ref(); - force = false; // Do not force another compaction if have room - MaybeScheduleCompaction(); - } - } - return s; -} - -bool DBImpl::GetProperty(const Slice& property, std::string* value) { - value->clear(); - - MutexLock l(&mutex_); - Slice in = property; - Slice prefix("leveldb."); - if (!in.starts_with(prefix)) return false; - in.remove_prefix(prefix.size()); - - if (in.starts_with("num-files-at-level")) { - in.remove_prefix(strlen("num-files-at-level")); - uint64_t level; - bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); - if (!ok || level >= config::kNumLevels) { - return false; - } else { - char buf[100]; - snprintf(buf, sizeof(buf), "%d", - versions_->NumLevelFiles(static_cast(level))); - *value = buf; - return true; - } - } else if (in == "stats") { - char buf[200]; - snprintf(buf, sizeof(buf), - " Compactions\n" - "Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n" - "--------------------------------------------------\n" - ); - value->append(buf); - for (int level = 0; level < config::kNumLevels; level++) { - int files = versions_->NumLevelFiles(level); - if (stats_[level].micros > 0 || files > 0) { - snprintf( - buf, sizeof(buf), - "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", - level, - files, - versions_->NumLevelBytes(level) / 1048576.0, - stats_[level].micros / 1e6, - stats_[level].bytes_read / 1048576.0, - stats_[level].bytes_written / 1048576.0); - value->append(buf); - } - } - return true; - } else if (in == "sstables") { - *value = versions_->current()->DebugString(); - return true; - } - - return false; -} - -void DBImpl::GetApproximateSizes( - const Range* range, int n, - uint64_t* sizes) { - // TODO(opt): better implementation - Version* v; - { - MutexLock l(&mutex_); - versions_->current()->Ref(); - v = versions_->current(); - } - - for (int i = 0; i < n; i++) { - // Convert user_key into a corresponding internal key. - InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); - InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); - uint64_t start = versions_->ApproximateOffsetOf(v, k1); - uint64_t limit = versions_->ApproximateOffsetOf(v, k2); - sizes[i] = (limit >= start ? limit - start : 0); - } - - { - MutexLock l(&mutex_); - v->Unref(); - } -} - -// Default implementations of convenience methods that subclasses of DB -// can call if they wish -Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { - WriteBatch batch; - batch.Put(key, value); - return Write(opt, &batch); -} - -Status DB::Delete(const WriteOptions& opt, const Slice& key) { - WriteBatch batch; - batch.Delete(key); - return Write(opt, &batch); -} - -DB::~DB() { } - -Status DB::Open(const Options& options, const std::string& dbname, - DB** dbptr) { - *dbptr = NULL; - - DBImpl* impl = new DBImpl(options, dbname); - impl->mutex_.Lock(); - VersionEdit edit; - Status s = impl->Recover(&edit); // Handles create_if_missing, error_if_exists - if (s.ok()) { - uint64_t new_log_number = impl->versions_->NewFileNumber(); - WritableFile* lfile; - s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), - &lfile); - if (s.ok()) { - edit.SetLogNumber(new_log_number); - impl->logfile_ = lfile; - impl->logfile_number_ = new_log_number; - impl->log_ = new log::Writer(lfile); - s = impl->versions_->LogAndApply(&edit, &impl->mutex_); - } - if (s.ok()) { - impl->DeleteObsoleteFiles(); - impl->MaybeScheduleCompaction(); - } - } - impl->mutex_.Unlock(); - if (s.ok()) { - *dbptr = impl; - } else { - delete impl; - } - return s; -} - -Snapshot::~Snapshot() { -} - -Status DestroyDB(const std::string& dbname, const Options& options) { - Env* env = options.env; - std::vector filenames; - // Ignore error in case directory does not exist - env->GetChildren(dbname, &filenames); - if (filenames.empty()) { - return Status::OK(); - } - - FileLock* lock; - const std::string lockname = LockFileName(dbname); - Status result = env->LockFile(lockname, &lock); - if (result.ok()) { - uint64_t number; - FileType type; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type) && - type != kDBLockFile) { // Lock file will be deleted at end - Status del = env->DeleteFile(dbname + "/" + filenames[i]); - if (result.ok() && !del.ok()) { - result = del; - } - } - } - env->UnlockFile(lock); // Ignore error since state is already gone - env->DeleteFile(lockname); - env->DeleteDir(dbname); // Ignore error in case dir contains other files - } - return result; -} - -} // namespace leveldb diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h deleted file mode 100644 index cfc998164a..0000000000 --- a/src/leveldb/db/db_impl.h +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ -#define STORAGE_LEVELDB_DB_DB_IMPL_H_ - -#include -#include -#include "db/dbformat.h" -#include "db/log_writer.h" -#include "db/snapshot.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "port/port.h" -#include "port/thread_annotations.h" - -namespace leveldb { - -class MemTable; -class TableCache; -class Version; -class VersionEdit; -class VersionSet; - -class DBImpl : public DB { - public: - DBImpl(const Options& options, const std::string& dbname); - virtual ~DBImpl(); - - // Implementations of the DB interface - virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); - virtual Status Delete(const WriteOptions&, const Slice& key); - virtual Status Write(const WriteOptions& options, WriteBatch* updates); - virtual Status Get(const ReadOptions& options, - const Slice& key, - std::string* value); - virtual Iterator* NewIterator(const ReadOptions&); - virtual const Snapshot* GetSnapshot(); - virtual void ReleaseSnapshot(const Snapshot* snapshot); - virtual bool GetProperty(const Slice& property, std::string* value); - virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); - virtual void CompactRange(const Slice* begin, const Slice* end); - - // Extra methods (for testing) that are not in the public DB interface - - // Compact any files in the named level that overlap [*begin,*end] - void TEST_CompactRange(int level, const Slice* begin, const Slice* end); - - // Force current memtable contents to be compacted. - Status TEST_CompactMemTable(); - - // Return an internal iterator over the current state of the database. - // The keys of this iterator are internal keys (see format.h). - // The returned iterator should be deleted when no longer needed. - Iterator* TEST_NewInternalIterator(); - - // Return the maximum overlapping data (in bytes) at next level for any - // file at a level >= 1. - int64_t TEST_MaxNextLevelOverlappingBytes(); - - // Record a sample of bytes read at the specified internal key. - // Samples are taken approximately once every config::kReadBytesPeriod - // bytes. - void RecordReadSample(Slice key); - - private: - friend class DB; - struct CompactionState; - struct Writer; - - Iterator* NewInternalIterator(const ReadOptions&, - SequenceNumber* latest_snapshot, - uint32_t* seed); - - Status NewDB(); - - // Recover the descriptor from persistent storage. May do a significant - // amount of work to recover recently logged updates. Any changes to - // be made to the descriptor are added to *edit. - Status Recover(VersionEdit* edit) EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - void MaybeIgnoreError(Status* s) const; - - // Delete any unneeded files and stale in-memory entries. - void DeleteObsoleteFiles(); - - // Compact the in-memory write buffer to disk. Switches to a new - // log-file/memtable and writes a new descriptor iff successful. - // Errors are recorded in bg_error_. - void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - Status RecoverLogFile(uint64_t log_number, - VersionEdit* edit, - SequenceNumber* max_sequence) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - Status MakeRoomForWrite(bool force /* compact even if there is room? */) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - WriteBatch* BuildBatchGroup(Writer** last_writer); - - void RecordBackgroundError(const Status& s); - - void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); - static void BGWork(void* db); - void BackgroundCall(); - void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); - void CleanupCompaction(CompactionState* compact) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - Status DoCompactionWork(CompactionState* compact) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - Status OpenCompactionOutputFile(CompactionState* compact); - Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); - Status InstallCompactionResults(CompactionState* compact) - EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // Constant after construction - Env* const env_; - const InternalKeyComparator internal_comparator_; - const InternalFilterPolicy internal_filter_policy_; - const Options options_; // options_.comparator == &internal_comparator_ - bool owns_info_log_; - bool owns_cache_; - const std::string dbname_; - - // table_cache_ provides its own synchronization - TableCache* table_cache_; - - // Lock over the persistent DB state. Non-NULL iff successfully acquired. - FileLock* db_lock_; - - // State below is protected by mutex_ - port::Mutex mutex_; - port::AtomicPointer shutting_down_; - port::CondVar bg_cv_; // Signalled when background work finishes - MemTable* mem_; - MemTable* imm_; // Memtable being compacted - port::AtomicPointer has_imm_; // So bg thread can detect non-NULL imm_ - WritableFile* logfile_; - uint64_t logfile_number_; - log::Writer* log_; - uint32_t seed_; // For sampling. - - // Queue of writers. - std::deque writers_; - WriteBatch* tmp_batch_; - - SnapshotList snapshots_; - - // Set of table files to protect from deletion because they are - // part of ongoing compactions. - std::set pending_outputs_; - - // Has a background compaction been scheduled or is running? - bool bg_compaction_scheduled_; - - // Information for a manual compaction - struct ManualCompaction { - int level; - bool done; - const InternalKey* begin; // NULL means beginning of key range - const InternalKey* end; // NULL means end of key range - InternalKey tmp_storage; // Used to keep track of compaction progress - }; - ManualCompaction* manual_compaction_; - - VersionSet* versions_; - - // Have we encountered a background error in paranoid mode? - Status bg_error_; - - // Per level compaction stats. stats_[level] stores the stats for - // compactions that produced data for the specified "level". - struct CompactionStats { - int64_t micros; - int64_t bytes_read; - int64_t bytes_written; - - CompactionStats() : micros(0), bytes_read(0), bytes_written(0) { } - - void Add(const CompactionStats& c) { - this->micros += c.micros; - this->bytes_read += c.bytes_read; - this->bytes_written += c.bytes_written; - } - }; - CompactionStats stats_[config::kNumLevels]; - - // No copying allowed - DBImpl(const DBImpl&); - void operator=(const DBImpl&); - - const Comparator* user_comparator() const { - return internal_comparator_.user_comparator(); - } -}; - -// Sanitize db options. The caller should delete result.info_log if -// it is not equal to src.info_log. -extern Options SanitizeOptions(const std::string& db, - const InternalKeyComparator* icmp, - const InternalFilterPolicy* ipolicy, - const Options& src); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc deleted file mode 100644 index 3b2035e9e3..0000000000 --- a/src/leveldb/db/db_iter.cc +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/db_iter.h" - -#include "db/filename.h" -#include "db/db_impl.h" -#include "db/dbformat.h" -#include "leveldb/env.h" -#include "leveldb/iterator.h" -#include "port/port.h" -#include "util/logging.h" -#include "util/mutexlock.h" -#include "util/random.h" - -namespace leveldb { - -#if 0 -static void DumpInternalIter(Iterator* iter) { - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - ParsedInternalKey k; - if (!ParseInternalKey(iter->key(), &k)) { - fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); - } else { - fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); - } - } -} -#endif - -namespace { - -// Memtables and sstables that make the DB representation contain -// (userkey,seq,type) => uservalue entries. DBIter -// combines multiple entries for the same userkey found in the DB -// representation into a single entry while accounting for sequence -// numbers, deletion markers, overwrites, etc. -class DBIter: public Iterator { - public: - // Which direction is the iterator currently moving? - // (1) When moving forward, the internal iterator is positioned at - // the exact entry that yields this->key(), this->value() - // (2) When moving backwards, the internal iterator is positioned - // just before all entries whose user key == this->key(). - enum Direction { - kForward, - kReverse - }; - - DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s, - uint32_t seed) - : db_(db), - user_comparator_(cmp), - iter_(iter), - sequence_(s), - direction_(kForward), - valid_(false), - rnd_(seed), - bytes_counter_(RandomPeriod()) { - } - virtual ~DBIter() { - delete iter_; - } - virtual bool Valid() const { return valid_; } - virtual Slice key() const { - assert(valid_); - return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; - } - virtual Slice value() const { - assert(valid_); - return (direction_ == kForward) ? iter_->value() : saved_value_; - } - virtual Status status() const { - if (status_.ok()) { - return iter_->status(); - } else { - return status_; - } - } - - virtual void Next(); - virtual void Prev(); - virtual void Seek(const Slice& target); - virtual void SeekToFirst(); - virtual void SeekToLast(); - - private: - void FindNextUserEntry(bool skipping, std::string* skip); - void FindPrevUserEntry(); - bool ParseKey(ParsedInternalKey* key); - - inline void SaveKey(const Slice& k, std::string* dst) { - dst->assign(k.data(), k.size()); - } - - inline void ClearSavedValue() { - if (saved_value_.capacity() > 1048576) { - std::string empty; - swap(empty, saved_value_); - } else { - saved_value_.clear(); - } - } - - // Pick next gap with average value of config::kReadBytesPeriod. - ssize_t RandomPeriod() { - return rnd_.Uniform(2*config::kReadBytesPeriod); - } - - DBImpl* db_; - const Comparator* const user_comparator_; - Iterator* const iter_; - SequenceNumber const sequence_; - - Status status_; - std::string saved_key_; // == current key when direction_==kReverse - std::string saved_value_; // == current raw value when direction_==kReverse - Direction direction_; - bool valid_; - - Random rnd_; - ssize_t bytes_counter_; - - // No copying allowed - DBIter(const DBIter&); - void operator=(const DBIter&); -}; - -inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { - Slice k = iter_->key(); - ssize_t n = k.size() + iter_->value().size(); - bytes_counter_ -= n; - while (bytes_counter_ < 0) { - bytes_counter_ += RandomPeriod(); - db_->RecordReadSample(k); - } - if (!ParseInternalKey(k, ikey)) { - status_ = Status::Corruption("corrupted internal key in DBIter"); - return false; - } else { - return true; - } -} - -void DBIter::Next() { - assert(valid_); - - if (direction_ == kReverse) { // Switch directions? - direction_ = kForward; - // iter_ is pointing just before the entries for this->key(), - // so advance into the range of entries for this->key() and then - // use the normal skipping code below. - if (!iter_->Valid()) { - iter_->SeekToFirst(); - } else { - iter_->Next(); - } - if (!iter_->Valid()) { - valid_ = false; - saved_key_.clear(); - return; - } - // saved_key_ already contains the key to skip past. - } else { - // Store in saved_key_ the current key so we skip it below. - SaveKey(ExtractUserKey(iter_->key()), &saved_key_); - } - - FindNextUserEntry(true, &saved_key_); -} - -void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { - // Loop until we hit an acceptable entry to yield - assert(iter_->Valid()); - assert(direction_ == kForward); - do { - ParsedInternalKey ikey; - if (ParseKey(&ikey) && ikey.sequence <= sequence_) { - switch (ikey.type) { - case kTypeDeletion: - // Arrange to skip all upcoming entries for this key since - // they are hidden by this deletion. - SaveKey(ikey.user_key, skip); - skipping = true; - break; - case kTypeValue: - if (skipping && - user_comparator_->Compare(ikey.user_key, *skip) <= 0) { - // Entry hidden - } else { - valid_ = true; - saved_key_.clear(); - return; - } - break; - } - } - iter_->Next(); - } while (iter_->Valid()); - saved_key_.clear(); - valid_ = false; -} - -void DBIter::Prev() { - assert(valid_); - - if (direction_ == kForward) { // Switch directions? - // iter_ is pointing at the current entry. Scan backwards until - // the key changes so we can use the normal reverse scanning code. - assert(iter_->Valid()); // Otherwise valid_ would have been false - SaveKey(ExtractUserKey(iter_->key()), &saved_key_); - while (true) { - iter_->Prev(); - if (!iter_->Valid()) { - valid_ = false; - saved_key_.clear(); - ClearSavedValue(); - return; - } - if (user_comparator_->Compare(ExtractUserKey(iter_->key()), - saved_key_) < 0) { - break; - } - } - direction_ = kReverse; - } - - FindPrevUserEntry(); -} - -void DBIter::FindPrevUserEntry() { - assert(direction_ == kReverse); - - ValueType value_type = kTypeDeletion; - if (iter_->Valid()) { - do { - ParsedInternalKey ikey; - if (ParseKey(&ikey) && ikey.sequence <= sequence_) { - if ((value_type != kTypeDeletion) && - user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { - // We encountered a non-deleted value in entries for previous keys, - break; - } - value_type = ikey.type; - if (value_type == kTypeDeletion) { - saved_key_.clear(); - ClearSavedValue(); - } else { - Slice raw_value = iter_->value(); - if (saved_value_.capacity() > raw_value.size() + 1048576) { - std::string empty; - swap(empty, saved_value_); - } - SaveKey(ExtractUserKey(iter_->key()), &saved_key_); - saved_value_.assign(raw_value.data(), raw_value.size()); - } - } - iter_->Prev(); - } while (iter_->Valid()); - } - - if (value_type == kTypeDeletion) { - // End - valid_ = false; - saved_key_.clear(); - ClearSavedValue(); - direction_ = kForward; - } else { - valid_ = true; - } -} - -void DBIter::Seek(const Slice& target) { - direction_ = kForward; - ClearSavedValue(); - saved_key_.clear(); - AppendInternalKey( - &saved_key_, ParsedInternalKey(target, sequence_, kValueTypeForSeek)); - iter_->Seek(saved_key_); - if (iter_->Valid()) { - FindNextUserEntry(false, &saved_key_ /* temporary storage */); - } else { - valid_ = false; - } -} - -void DBIter::SeekToFirst() { - direction_ = kForward; - ClearSavedValue(); - iter_->SeekToFirst(); - if (iter_->Valid()) { - FindNextUserEntry(false, &saved_key_ /* temporary storage */); - } else { - valid_ = false; - } -} - -void DBIter::SeekToLast() { - direction_ = kReverse; - ClearSavedValue(); - iter_->SeekToLast(); - FindPrevUserEntry(); -} - -} // anonymous namespace - -Iterator* NewDBIterator( - DBImpl* db, - const Comparator* user_key_comparator, - Iterator* internal_iter, - SequenceNumber sequence, - uint32_t seed) { - return new DBIter(db, user_key_comparator, internal_iter, sequence, seed); -} - -} // namespace leveldb diff --git a/src/leveldb/db/db_iter.h b/src/leveldb/db/db_iter.h deleted file mode 100644 index 04927e937b..0000000000 --- a/src/leveldb/db/db_iter.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ -#define STORAGE_LEVELDB_DB_DB_ITER_H_ - -#include -#include "leveldb/db.h" -#include "db/dbformat.h" - -namespace leveldb { - -class DBImpl; - -// Return a new iterator that converts internal keys (yielded by -// "*internal_iter") that were live at the specified "sequence" number -// into appropriate user keys. -extern Iterator* NewDBIterator( - DBImpl* db, - const Comparator* user_key_comparator, - Iterator* internal_iter, - SequenceNumber sequence, - uint32_t seed); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/src/leveldb/db/db_test.cc b/src/leveldb/db/db_test.cc deleted file mode 100644 index 0fed9137d5..0000000000 --- a/src/leveldb/db/db_test.cc +++ /dev/null @@ -1,2128 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/db.h" -#include "leveldb/filter_policy.h" -#include "db/db_impl.h" -#include "db/filename.h" -#include "db/version_set.h" -#include "db/write_batch_internal.h" -#include "leveldb/cache.h" -#include "leveldb/env.h" -#include "leveldb/table.h" -#include "util/hash.h" -#include "util/logging.h" -#include "util/mutexlock.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -static std::string RandomString(Random* rnd, int len) { - std::string r; - test::RandomString(rnd, len, &r); - return r; -} - -namespace { -class AtomicCounter { - private: - port::Mutex mu_; - int count_; - public: - AtomicCounter() : count_(0) { } - void Increment() { - IncrementBy(1); - } - void IncrementBy(int count) { - MutexLock l(&mu_); - count_ += count; - } - int Read() { - MutexLock l(&mu_); - return count_; - } - void Reset() { - MutexLock l(&mu_); - count_ = 0; - } -}; - -void DelayMilliseconds(int millis) { - Env::Default()->SleepForMicroseconds(millis * 1000); -} -} - -// Special Env used to delay background operations -class SpecialEnv : public EnvWrapper { - public: - // sstable/log Sync() calls are blocked while this pointer is non-NULL. - port::AtomicPointer delay_data_sync_; - - // sstable/log Sync() calls return an error. - port::AtomicPointer data_sync_error_; - - // Simulate no-space errors while this pointer is non-NULL. - port::AtomicPointer no_space_; - - // Simulate non-writable file system while this pointer is non-NULL - port::AtomicPointer non_writable_; - - // Force sync of manifest files to fail while this pointer is non-NULL - port::AtomicPointer manifest_sync_error_; - - // Force write to manifest files to fail while this pointer is non-NULL - port::AtomicPointer manifest_write_error_; - - bool count_random_reads_; - AtomicCounter random_read_counter_; - - explicit SpecialEnv(Env* base) : EnvWrapper(base) { - delay_data_sync_.Release_Store(NULL); - data_sync_error_.Release_Store(NULL); - no_space_.Release_Store(NULL); - non_writable_.Release_Store(NULL); - count_random_reads_ = false; - manifest_sync_error_.Release_Store(NULL); - manifest_write_error_.Release_Store(NULL); - } - - Status NewWritableFile(const std::string& f, WritableFile** r) { - class DataFile : public WritableFile { - private: - SpecialEnv* env_; - WritableFile* base_; - - public: - DataFile(SpecialEnv* env, WritableFile* base) - : env_(env), - base_(base) { - } - ~DataFile() { delete base_; } - Status Append(const Slice& data) { - if (env_->no_space_.Acquire_Load() != NULL) { - // Drop writes on the floor - return Status::OK(); - } else { - return base_->Append(data); - } - } - Status Close() { return base_->Close(); } - Status Flush() { return base_->Flush(); } - Status Sync() { - if (env_->data_sync_error_.Acquire_Load() != NULL) { - return Status::IOError("simulated data sync error"); - } - while (env_->delay_data_sync_.Acquire_Load() != NULL) { - DelayMilliseconds(100); - } - return base_->Sync(); - } - }; - class ManifestFile : public WritableFile { - private: - SpecialEnv* env_; - WritableFile* base_; - public: - ManifestFile(SpecialEnv* env, WritableFile* b) : env_(env), base_(b) { } - ~ManifestFile() { delete base_; } - Status Append(const Slice& data) { - if (env_->manifest_write_error_.Acquire_Load() != NULL) { - return Status::IOError("simulated writer error"); - } else { - return base_->Append(data); - } - } - Status Close() { return base_->Close(); } - Status Flush() { return base_->Flush(); } - Status Sync() { - if (env_->manifest_sync_error_.Acquire_Load() != NULL) { - return Status::IOError("simulated sync error"); - } else { - return base_->Sync(); - } - } - }; - - if (non_writable_.Acquire_Load() != NULL) { - return Status::IOError("simulated write error"); - } - - Status s = target()->NewWritableFile(f, r); - if (s.ok()) { - if (strstr(f.c_str(), ".ldb") != NULL || - strstr(f.c_str(), ".log") != NULL) { - *r = new DataFile(this, *r); - } else if (strstr(f.c_str(), "MANIFEST") != NULL) { - *r = new ManifestFile(this, *r); - } - } - return s; - } - - Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) { - class CountingFile : public RandomAccessFile { - private: - RandomAccessFile* target_; - AtomicCounter* counter_; - public: - CountingFile(RandomAccessFile* target, AtomicCounter* counter) - : target_(target), counter_(counter) { - } - virtual ~CountingFile() { delete target_; } - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const { - counter_->Increment(); - return target_->Read(offset, n, result, scratch); - } - }; - - Status s = target()->NewRandomAccessFile(f, r); - if (s.ok() && count_random_reads_) { - *r = new CountingFile(*r, &random_read_counter_); - } - return s; - } -}; - -class DBTest { - private: - const FilterPolicy* filter_policy_; - - // Sequence of option configurations to try - enum OptionConfig { - kDefault, - kFilter, - kUncompressed, - kEnd - }; - int option_config_; - - public: - std::string dbname_; - SpecialEnv* env_; - DB* db_; - - Options last_options_; - - DBTest() : option_config_(kDefault), - env_(new SpecialEnv(Env::Default())) { - filter_policy_ = NewBloomFilterPolicy(10); - dbname_ = test::TmpDir() + "/db_test"; - DestroyDB(dbname_, Options()); - db_ = NULL; - Reopen(); - } - - ~DBTest() { - delete db_; - DestroyDB(dbname_, Options()); - delete env_; - delete filter_policy_; - } - - // Switch to a fresh database with the next option configuration to - // test. Return false if there are no more configurations to test. - bool ChangeOptions() { - option_config_++; - if (option_config_ >= kEnd) { - return false; - } else { - DestroyAndReopen(); - return true; - } - } - - // Return the current option configuration. - Options CurrentOptions() { - Options options; - switch (option_config_) { - case kFilter: - options.filter_policy = filter_policy_; - break; - case kUncompressed: - options.compression = kNoCompression; - break; - default: - break; - } - return options; - } - - DBImpl* dbfull() { - return reinterpret_cast(db_); - } - - void Reopen(Options* options = NULL) { - ASSERT_OK(TryReopen(options)); - } - - void Close() { - delete db_; - db_ = NULL; - } - - void DestroyAndReopen(Options* options = NULL) { - delete db_; - db_ = NULL; - DestroyDB(dbname_, Options()); - ASSERT_OK(TryReopen(options)); - } - - Status TryReopen(Options* options) { - delete db_; - db_ = NULL; - Options opts; - if (options != NULL) { - opts = *options; - } else { - opts = CurrentOptions(); - opts.create_if_missing = true; - } - last_options_ = opts; - - return DB::Open(opts, dbname_, &db_); - } - - Status Put(const std::string& k, const std::string& v) { - return db_->Put(WriteOptions(), k, v); - } - - Status Delete(const std::string& k) { - return db_->Delete(WriteOptions(), k); - } - - std::string Get(const std::string& k, const Snapshot* snapshot = NULL) { - ReadOptions options; - options.snapshot = snapshot; - std::string result; - Status s = db_->Get(options, k, &result); - if (s.IsNotFound()) { - result = "NOT_FOUND"; - } else if (!s.ok()) { - result = s.ToString(); - } - return result; - } - - // Return a string that contains all key,value pairs in order, - // formatted like "(k1->v1)(k2->v2)". - std::string Contents() { - std::vector forward; - std::string result; - Iterator* iter = db_->NewIterator(ReadOptions()); - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - std::string s = IterStatus(iter); - result.push_back('('); - result.append(s); - result.push_back(')'); - forward.push_back(s); - } - - // Check reverse iteration results are the reverse of forward results - size_t matched = 0; - for (iter->SeekToLast(); iter->Valid(); iter->Prev()) { - ASSERT_LT(matched, forward.size()); - ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]); - matched++; - } - ASSERT_EQ(matched, forward.size()); - - delete iter; - return result; - } - - std::string AllEntriesFor(const Slice& user_key) { - Iterator* iter = dbfull()->TEST_NewInternalIterator(); - InternalKey target(user_key, kMaxSequenceNumber, kTypeValue); - iter->Seek(target.Encode()); - std::string result; - if (!iter->status().ok()) { - result = iter->status().ToString(); - } else { - result = "[ "; - bool first = true; - while (iter->Valid()) { - ParsedInternalKey ikey; - if (!ParseInternalKey(iter->key(), &ikey)) { - result += "CORRUPTED"; - } else { - if (last_options_.comparator->Compare(ikey.user_key, user_key) != 0) { - break; - } - if (!first) { - result += ", "; - } - first = false; - switch (ikey.type) { - case kTypeValue: - result += iter->value().ToString(); - break; - case kTypeDeletion: - result += "DEL"; - break; - } - } - iter->Next(); - } - if (!first) { - result += " "; - } - result += "]"; - } - delete iter; - return result; - } - - int NumTableFilesAtLevel(int level) { - std::string property; - ASSERT_TRUE( - db_->GetProperty("leveldb.num-files-at-level" + NumberToString(level), - &property)); - return atoi(property.c_str()); - } - - int TotalTableFiles() { - int result = 0; - for (int level = 0; level < config::kNumLevels; level++) { - result += NumTableFilesAtLevel(level); - } - return result; - } - - // Return spread of files per level - std::string FilesPerLevel() { - std::string result; - int last_non_zero_offset = 0; - for (int level = 0; level < config::kNumLevels; level++) { - int f = NumTableFilesAtLevel(level); - char buf[100]; - snprintf(buf, sizeof(buf), "%s%d", (level ? "," : ""), f); - result += buf; - if (f > 0) { - last_non_zero_offset = result.size(); - } - } - result.resize(last_non_zero_offset); - return result; - } - - int CountFiles() { - std::vector files; - env_->GetChildren(dbname_, &files); - return static_cast(files.size()); - } - - uint64_t Size(const Slice& start, const Slice& limit) { - Range r(start, limit); - uint64_t size; - db_->GetApproximateSizes(&r, 1, &size); - return size; - } - - void Compact(const Slice& start, const Slice& limit) { - db_->CompactRange(&start, &limit); - } - - // Do n memtable compactions, each of which produces an sstable - // covering the range [small,large]. - void MakeTables(int n, const std::string& small, const std::string& large) { - for (int i = 0; i < n; i++) { - Put(small, "begin"); - Put(large, "end"); - dbfull()->TEST_CompactMemTable(); - } - } - - // Prevent pushing of new sstables into deeper levels by adding - // tables that cover a specified range to all levels. - void FillLevels(const std::string& smallest, const std::string& largest) { - MakeTables(config::kNumLevels, smallest, largest); - } - - void DumpFileCounts(const char* label) { - fprintf(stderr, "---\n%s:\n", label); - fprintf(stderr, "maxoverlap: %lld\n", - static_cast( - dbfull()->TEST_MaxNextLevelOverlappingBytes())); - for (int level = 0; level < config::kNumLevels; level++) { - int num = NumTableFilesAtLevel(level); - if (num > 0) { - fprintf(stderr, " level %3d : %d files\n", level, num); - } - } - } - - std::string DumpSSTableList() { - std::string property; - db_->GetProperty("leveldb.sstables", &property); - return property; - } - - std::string IterStatus(Iterator* iter) { - std::string result; - if (iter->Valid()) { - result = iter->key().ToString() + "->" + iter->value().ToString(); - } else { - result = "(invalid)"; - } - return result; - } - - bool DeleteAnSSTFile() { - std::vector filenames; - ASSERT_OK(env_->GetChildren(dbname_, &filenames)); - uint64_t number; - FileType type; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) { - ASSERT_OK(env_->DeleteFile(TableFileName(dbname_, number))); - return true; - } - } - return false; - } - - // Returns number of files renamed. - int RenameLDBToSST() { - std::vector filenames; - ASSERT_OK(env_->GetChildren(dbname_, &filenames)); - uint64_t number; - FileType type; - int files_renamed = 0; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) { - const std::string from = TableFileName(dbname_, number); - const std::string to = SSTTableFileName(dbname_, number); - ASSERT_OK(env_->RenameFile(from, to)); - files_renamed++; - } - } - return files_renamed; - } -}; - -TEST(DBTest, Empty) { - do { - ASSERT_TRUE(db_ != NULL); - ASSERT_EQ("NOT_FOUND", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, ReadWrite) { - do { - ASSERT_OK(Put("foo", "v1")); - ASSERT_EQ("v1", Get("foo")); - ASSERT_OK(Put("bar", "v2")); - ASSERT_OK(Put("foo", "v3")); - ASSERT_EQ("v3", Get("foo")); - ASSERT_EQ("v2", Get("bar")); - } while (ChangeOptions()); -} - -TEST(DBTest, PutDeleteGet) { - do { - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v1")); - ASSERT_EQ("v1", Get("foo")); - ASSERT_OK(db_->Put(WriteOptions(), "foo", "v2")); - ASSERT_EQ("v2", Get("foo")); - ASSERT_OK(db_->Delete(WriteOptions(), "foo")); - ASSERT_EQ("NOT_FOUND", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, GetFromImmutableLayer) { - do { - Options options = CurrentOptions(); - options.env = env_; - options.write_buffer_size = 100000; // Small write buffer - Reopen(&options); - - ASSERT_OK(Put("foo", "v1")); - ASSERT_EQ("v1", Get("foo")); - - env_->delay_data_sync_.Release_Store(env_); // Block sync calls - Put("k1", std::string(100000, 'x')); // Fill memtable - Put("k2", std::string(100000, 'y')); // Trigger compaction - ASSERT_EQ("v1", Get("foo")); - env_->delay_data_sync_.Release_Store(NULL); // Release sync calls - } while (ChangeOptions()); -} - -TEST(DBTest, GetFromVersions) { - do { - ASSERT_OK(Put("foo", "v1")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("v1", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, GetSnapshot) { - do { - // Try with both a short key and a long key - for (int i = 0; i < 2; i++) { - std::string key = (i == 0) ? std::string("foo") : std::string(200, 'x'); - ASSERT_OK(Put(key, "v1")); - const Snapshot* s1 = db_->GetSnapshot(); - ASSERT_OK(Put(key, "v2")); - ASSERT_EQ("v2", Get(key)); - ASSERT_EQ("v1", Get(key, s1)); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("v2", Get(key)); - ASSERT_EQ("v1", Get(key, s1)); - db_->ReleaseSnapshot(s1); - } - } while (ChangeOptions()); -} - -TEST(DBTest, GetLevel0Ordering) { - do { - // Check that we process level-0 files in correct order. The code - // below generates two level-0 files where the earlier one comes - // before the later one in the level-0 file list since the earlier - // one has a smaller "smallest" key. - ASSERT_OK(Put("bar", "b")); - ASSERT_OK(Put("foo", "v1")); - dbfull()->TEST_CompactMemTable(); - ASSERT_OK(Put("foo", "v2")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("v2", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, GetOrderedByLevels) { - do { - ASSERT_OK(Put("foo", "v1")); - Compact("a", "z"); - ASSERT_EQ("v1", Get("foo")); - ASSERT_OK(Put("foo", "v2")); - ASSERT_EQ("v2", Get("foo")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("v2", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, GetPicksCorrectFile) { - do { - // Arrange to have multiple files in a non-level-0 level. - ASSERT_OK(Put("a", "va")); - Compact("a", "b"); - ASSERT_OK(Put("x", "vx")); - Compact("x", "y"); - ASSERT_OK(Put("f", "vf")); - Compact("f", "g"); - ASSERT_EQ("va", Get("a")); - ASSERT_EQ("vf", Get("f")); - ASSERT_EQ("vx", Get("x")); - } while (ChangeOptions()); -} - -TEST(DBTest, GetEncountersEmptyLevel) { - do { - // Arrange for the following to happen: - // * sstable A in level 0 - // * nothing in level 1 - // * sstable B in level 2 - // Then do enough Get() calls to arrange for an automatic compaction - // of sstable A. A bug would cause the compaction to be marked as - // occurring at level 1 (instead of the correct level 0). - - // Step 1: First place sstables in levels 0 and 2 - int compaction_count = 0; - while (NumTableFilesAtLevel(0) == 0 || - NumTableFilesAtLevel(2) == 0) { - ASSERT_LE(compaction_count, 100) << "could not fill levels 0 and 2"; - compaction_count++; - Put("a", "begin"); - Put("z", "end"); - dbfull()->TEST_CompactMemTable(); - } - - // Step 2: clear level 1 if necessary. - dbfull()->TEST_CompactRange(1, NULL, NULL); - ASSERT_EQ(NumTableFilesAtLevel(0), 1); - ASSERT_EQ(NumTableFilesAtLevel(1), 0); - ASSERT_EQ(NumTableFilesAtLevel(2), 1); - - // Step 3: read a bunch of times - for (int i = 0; i < 1000; i++) { - ASSERT_EQ("NOT_FOUND", Get("missing")); - } - - // Step 4: Wait for compaction to finish - DelayMilliseconds(1000); - - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - } while (ChangeOptions()); -} - -TEST(DBTest, IterEmpty) { - Iterator* iter = db_->NewIterator(ReadOptions()); - - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->Seek("foo"); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - delete iter; -} - -TEST(DBTest, IterSingle) { - ASSERT_OK(Put("a", "va")); - Iterator* iter = db_->NewIterator(ReadOptions()); - - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->Seek(""); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->Seek("a"); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->Seek("b"); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - delete iter; -} - -TEST(DBTest, IterMulti) { - ASSERT_OK(Put("a", "va")); - ASSERT_OK(Put("b", "vb")); - ASSERT_OK(Put("c", "vc")); - Iterator* iter = db_->NewIterator(ReadOptions()); - - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->Seek(""); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Seek("a"); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Seek("ax"); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Seek("b"); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Seek("z"); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - // Switch from reverse to forward - iter->SeekToLast(); - iter->Prev(); - iter->Prev(); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - - // Switch from forward to reverse - iter->SeekToFirst(); - iter->Next(); - iter->Next(); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - - // Make sure iter stays at snapshot - ASSERT_OK(Put("a", "va2")); - ASSERT_OK(Put("a2", "va3")); - ASSERT_OK(Put("b", "vb2")); - ASSERT_OK(Put("c", "vc2")); - ASSERT_OK(Delete("b")); - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "b->vb"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - delete iter; -} - -TEST(DBTest, IterSmallAndLargeMix) { - ASSERT_OK(Put("a", "va")); - ASSERT_OK(Put("b", std::string(100000, 'b'))); - ASSERT_OK(Put("c", "vc")); - ASSERT_OK(Put("d", std::string(100000, 'd'))); - ASSERT_OK(Put("e", std::string(100000, 'e'))); - - Iterator* iter = db_->NewIterator(ReadOptions()); - - iter->SeekToFirst(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); - iter->Next(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - iter->SeekToLast(); - ASSERT_EQ(IterStatus(iter), "e->" + std::string(100000, 'e')); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "d->" + std::string(100000, 'd')); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "b->" + std::string(100000, 'b')); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "a->va"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "(invalid)"); - - delete iter; -} - -TEST(DBTest, IterMultiWithDelete) { - do { - ASSERT_OK(Put("a", "va")); - ASSERT_OK(Put("b", "vb")); - ASSERT_OK(Put("c", "vc")); - ASSERT_OK(Delete("b")); - ASSERT_EQ("NOT_FOUND", Get("b")); - - Iterator* iter = db_->NewIterator(ReadOptions()); - iter->Seek("c"); - ASSERT_EQ(IterStatus(iter), "c->vc"); - iter->Prev(); - ASSERT_EQ(IterStatus(iter), "a->va"); - delete iter; - } while (ChangeOptions()); -} - -TEST(DBTest, Recover) { - do { - ASSERT_OK(Put("foo", "v1")); - ASSERT_OK(Put("baz", "v5")); - - Reopen(); - ASSERT_EQ("v1", Get("foo")); - - ASSERT_EQ("v1", Get("foo")); - ASSERT_EQ("v5", Get("baz")); - ASSERT_OK(Put("bar", "v2")); - ASSERT_OK(Put("foo", "v3")); - - Reopen(); - ASSERT_EQ("v3", Get("foo")); - ASSERT_OK(Put("foo", "v4")); - ASSERT_EQ("v4", Get("foo")); - ASSERT_EQ("v2", Get("bar")); - ASSERT_EQ("v5", Get("baz")); - } while (ChangeOptions()); -} - -TEST(DBTest, RecoveryWithEmptyLog) { - do { - ASSERT_OK(Put("foo", "v1")); - ASSERT_OK(Put("foo", "v2")); - Reopen(); - Reopen(); - ASSERT_OK(Put("foo", "v3")); - Reopen(); - ASSERT_EQ("v3", Get("foo")); - } while (ChangeOptions()); -} - -// Check that writes done during a memtable compaction are recovered -// if the database is shutdown during the memtable compaction. -TEST(DBTest, RecoverDuringMemtableCompaction) { - do { - Options options = CurrentOptions(); - options.env = env_; - options.write_buffer_size = 1000000; - Reopen(&options); - - // Trigger a long memtable compaction and reopen the database during it - ASSERT_OK(Put("foo", "v1")); // Goes to 1st log file - ASSERT_OK(Put("big1", std::string(10000000, 'x'))); // Fills memtable - ASSERT_OK(Put("big2", std::string(1000, 'y'))); // Triggers compaction - ASSERT_OK(Put("bar", "v2")); // Goes to new log file - - Reopen(&options); - ASSERT_EQ("v1", Get("foo")); - ASSERT_EQ("v2", Get("bar")); - ASSERT_EQ(std::string(10000000, 'x'), Get("big1")); - ASSERT_EQ(std::string(1000, 'y'), Get("big2")); - } while (ChangeOptions()); -} - -static std::string Key(int i) { - char buf[100]; - snprintf(buf, sizeof(buf), "key%06d", i); - return std::string(buf); -} - -TEST(DBTest, MinorCompactionsHappen) { - Options options = CurrentOptions(); - options.write_buffer_size = 10000; - Reopen(&options); - - const int N = 500; - - int starting_num_tables = TotalTableFiles(); - for (int i = 0; i < N; i++) { - ASSERT_OK(Put(Key(i), Key(i) + std::string(1000, 'v'))); - } - int ending_num_tables = TotalTableFiles(); - ASSERT_GT(ending_num_tables, starting_num_tables); - - for (int i = 0; i < N; i++) { - ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); - } - - Reopen(); - - for (int i = 0; i < N; i++) { - ASSERT_EQ(Key(i) + std::string(1000, 'v'), Get(Key(i))); - } -} - -TEST(DBTest, RecoverWithLargeLog) { - { - Options options = CurrentOptions(); - Reopen(&options); - ASSERT_OK(Put("big1", std::string(200000, '1'))); - ASSERT_OK(Put("big2", std::string(200000, '2'))); - ASSERT_OK(Put("small3", std::string(10, '3'))); - ASSERT_OK(Put("small4", std::string(10, '4'))); - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - } - - // Make sure that if we re-open with a small write buffer size that - // we flush table files in the middle of a large log file. - Options options = CurrentOptions(); - options.write_buffer_size = 100000; - Reopen(&options); - ASSERT_EQ(NumTableFilesAtLevel(0), 3); - ASSERT_EQ(std::string(200000, '1'), Get("big1")); - ASSERT_EQ(std::string(200000, '2'), Get("big2")); - ASSERT_EQ(std::string(10, '3'), Get("small3")); - ASSERT_EQ(std::string(10, '4'), Get("small4")); - ASSERT_GT(NumTableFilesAtLevel(0), 1); -} - -TEST(DBTest, CompactionsGenerateMultipleFiles) { - Options options = CurrentOptions(); - options.write_buffer_size = 100000000; // Large write buffer - Reopen(&options); - - Random rnd(301); - - // Write 8MB (80 values, each 100K) - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - std::vector values; - for (int i = 0; i < 80; i++) { - values.push_back(RandomString(&rnd, 100000)); - ASSERT_OK(Put(Key(i), values[i])); - } - - // Reopening moves updates to level-0 - Reopen(&options); - dbfull()->TEST_CompactRange(0, NULL, NULL); - - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - ASSERT_GT(NumTableFilesAtLevel(1), 1); - for (int i = 0; i < 80; i++) { - ASSERT_EQ(Get(Key(i)), values[i]); - } -} - -TEST(DBTest, RepeatedWritesToSameKey) { - Options options = CurrentOptions(); - options.env = env_; - options.write_buffer_size = 100000; // Small write buffer - Reopen(&options); - - // We must have at most one file per level except for level-0, - // which may have up to kL0_StopWritesTrigger files. - const int kMaxFiles = config::kNumLevels + config::kL0_StopWritesTrigger; - - Random rnd(301); - std::string value = RandomString(&rnd, 2 * options.write_buffer_size); - for (int i = 0; i < 5 * kMaxFiles; i++) { - Put("key", value); - ASSERT_LE(TotalTableFiles(), kMaxFiles); - fprintf(stderr, "after %d: %d files\n", int(i+1), TotalTableFiles()); - } -} - -TEST(DBTest, SparseMerge) { - Options options = CurrentOptions(); - options.compression = kNoCompression; - Reopen(&options); - - FillLevels("A", "Z"); - - // Suppose there is: - // small amount of data with prefix A - // large amount of data with prefix B - // small amount of data with prefix C - // and that recent updates have made small changes to all three prefixes. - // Check that we do not do a compaction that merges all of B in one shot. - const std::string value(1000, 'x'); - Put("A", "va"); - // Write approximately 100MB of "B" values - for (int i = 0; i < 100000; i++) { - char key[100]; - snprintf(key, sizeof(key), "B%010d", i); - Put(key, value); - } - Put("C", "vc"); - dbfull()->TEST_CompactMemTable(); - dbfull()->TEST_CompactRange(0, NULL, NULL); - - // Make sparse update - Put("A", "va2"); - Put("B100", "bvalue2"); - Put("C", "vc2"); - dbfull()->TEST_CompactMemTable(); - - // Compactions should not cause us to create a situation where - // a file overlaps too much data at the next level. - ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); - dbfull()->TEST_CompactRange(0, NULL, NULL); - ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); - dbfull()->TEST_CompactRange(1, NULL, NULL); - ASSERT_LE(dbfull()->TEST_MaxNextLevelOverlappingBytes(), 20*1048576); -} - -static bool Between(uint64_t val, uint64_t low, uint64_t high) { - bool result = (val >= low) && (val <= high); - if (!result) { - fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", - (unsigned long long)(val), - (unsigned long long)(low), - (unsigned long long)(high)); - } - return result; -} - -TEST(DBTest, ApproximateSizes) { - do { - Options options = CurrentOptions(); - options.write_buffer_size = 100000000; // Large write buffer - options.compression = kNoCompression; - DestroyAndReopen(); - - ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); - Reopen(&options); - ASSERT_TRUE(Between(Size("", "xyz"), 0, 0)); - - // Write 8MB (80 values, each 100K) - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - const int N = 80; - static const int S1 = 100000; - static const int S2 = 105000; // Allow some expansion from metadata - Random rnd(301); - for (int i = 0; i < N; i++) { - ASSERT_OK(Put(Key(i), RandomString(&rnd, S1))); - } - - // 0 because GetApproximateSizes() does not account for memtable space - ASSERT_TRUE(Between(Size("", Key(50)), 0, 0)); - - // Check sizes across recovery by reopening a few times - for (int run = 0; run < 3; run++) { - Reopen(&options); - - for (int compact_start = 0; compact_start < N; compact_start += 10) { - for (int i = 0; i < N; i += 10) { - ASSERT_TRUE(Between(Size("", Key(i)), S1*i, S2*i)); - ASSERT_TRUE(Between(Size("", Key(i)+".suffix"), S1*(i+1), S2*(i+1))); - ASSERT_TRUE(Between(Size(Key(i), Key(i+10)), S1*10, S2*10)); - } - ASSERT_TRUE(Between(Size("", Key(50)), S1*50, S2*50)); - ASSERT_TRUE(Between(Size("", Key(50)+".suffix"), S1*50, S2*50)); - - std::string cstart_str = Key(compact_start); - std::string cend_str = Key(compact_start + 9); - Slice cstart = cstart_str; - Slice cend = cend_str; - dbfull()->TEST_CompactRange(0, &cstart, &cend); - } - - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - ASSERT_GT(NumTableFilesAtLevel(1), 0); - } - } while (ChangeOptions()); -} - -TEST(DBTest, ApproximateSizes_MixOfSmallAndLarge) { - do { - Options options = CurrentOptions(); - options.compression = kNoCompression; - Reopen(); - - Random rnd(301); - std::string big1 = RandomString(&rnd, 100000); - ASSERT_OK(Put(Key(0), RandomString(&rnd, 10000))); - ASSERT_OK(Put(Key(1), RandomString(&rnd, 10000))); - ASSERT_OK(Put(Key(2), big1)); - ASSERT_OK(Put(Key(3), RandomString(&rnd, 10000))); - ASSERT_OK(Put(Key(4), big1)); - ASSERT_OK(Put(Key(5), RandomString(&rnd, 10000))); - ASSERT_OK(Put(Key(6), RandomString(&rnd, 300000))); - ASSERT_OK(Put(Key(7), RandomString(&rnd, 10000))); - - // Check sizes across recovery by reopening a few times - for (int run = 0; run < 3; run++) { - Reopen(&options); - - ASSERT_TRUE(Between(Size("", Key(0)), 0, 0)); - ASSERT_TRUE(Between(Size("", Key(1)), 10000, 11000)); - ASSERT_TRUE(Between(Size("", Key(2)), 20000, 21000)); - ASSERT_TRUE(Between(Size("", Key(3)), 120000, 121000)); - ASSERT_TRUE(Between(Size("", Key(4)), 130000, 131000)); - ASSERT_TRUE(Between(Size("", Key(5)), 230000, 231000)); - ASSERT_TRUE(Between(Size("", Key(6)), 240000, 241000)); - ASSERT_TRUE(Between(Size("", Key(7)), 540000, 541000)); - ASSERT_TRUE(Between(Size("", Key(8)), 550000, 560000)); - - ASSERT_TRUE(Between(Size(Key(3), Key(5)), 110000, 111000)); - - dbfull()->TEST_CompactRange(0, NULL, NULL); - } - } while (ChangeOptions()); -} - -TEST(DBTest, IteratorPinsRef) { - Put("foo", "hello"); - - // Get iterator that will yield the current contents of the DB. - Iterator* iter = db_->NewIterator(ReadOptions()); - - // Write to force compactions - Put("foo", "newvalue1"); - for (int i = 0; i < 100; i++) { - ASSERT_OK(Put(Key(i), Key(i) + std::string(100000, 'v'))); // 100K values - } - Put("foo", "newvalue2"); - - iter->SeekToFirst(); - ASSERT_TRUE(iter->Valid()); - ASSERT_EQ("foo", iter->key().ToString()); - ASSERT_EQ("hello", iter->value().ToString()); - iter->Next(); - ASSERT_TRUE(!iter->Valid()); - delete iter; -} - -TEST(DBTest, Snapshot) { - do { - Put("foo", "v1"); - const Snapshot* s1 = db_->GetSnapshot(); - Put("foo", "v2"); - const Snapshot* s2 = db_->GetSnapshot(); - Put("foo", "v3"); - const Snapshot* s3 = db_->GetSnapshot(); - - Put("foo", "v4"); - ASSERT_EQ("v1", Get("foo", s1)); - ASSERT_EQ("v2", Get("foo", s2)); - ASSERT_EQ("v3", Get("foo", s3)); - ASSERT_EQ("v4", Get("foo")); - - db_->ReleaseSnapshot(s3); - ASSERT_EQ("v1", Get("foo", s1)); - ASSERT_EQ("v2", Get("foo", s2)); - ASSERT_EQ("v4", Get("foo")); - - db_->ReleaseSnapshot(s1); - ASSERT_EQ("v2", Get("foo", s2)); - ASSERT_EQ("v4", Get("foo")); - - db_->ReleaseSnapshot(s2); - ASSERT_EQ("v4", Get("foo")); - } while (ChangeOptions()); -} - -TEST(DBTest, HiddenValuesAreRemoved) { - do { - Random rnd(301); - FillLevels("a", "z"); - - std::string big = RandomString(&rnd, 50000); - Put("foo", big); - Put("pastfoo", "v"); - const Snapshot* snapshot = db_->GetSnapshot(); - Put("foo", "tiny"); - Put("pastfoo2", "v2"); // Advance sequence number one more - - ASSERT_OK(dbfull()->TEST_CompactMemTable()); - ASSERT_GT(NumTableFilesAtLevel(0), 0); - - ASSERT_EQ(big, Get("foo", snapshot)); - ASSERT_TRUE(Between(Size("", "pastfoo"), 50000, 60000)); - db_->ReleaseSnapshot(snapshot); - ASSERT_EQ(AllEntriesFor("foo"), "[ tiny, " + big + " ]"); - Slice x("x"); - dbfull()->TEST_CompactRange(0, NULL, &x); - ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); - ASSERT_EQ(NumTableFilesAtLevel(0), 0); - ASSERT_GE(NumTableFilesAtLevel(1), 1); - dbfull()->TEST_CompactRange(1, NULL, &x); - ASSERT_EQ(AllEntriesFor("foo"), "[ tiny ]"); - - ASSERT_TRUE(Between(Size("", "pastfoo"), 0, 1000)); - } while (ChangeOptions()); -} - -TEST(DBTest, DeletionMarkers1) { - Put("foo", "v1"); - ASSERT_OK(dbfull()->TEST_CompactMemTable()); - const int last = config::kMaxMemCompactLevel; - ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level - - // Place a table at level last-1 to prevent merging with preceding mutation - Put("a", "begin"); - Put("z", "end"); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ(NumTableFilesAtLevel(last), 1); - ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); - - Delete("foo"); - Put("foo", "v2"); - ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); - ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 - ASSERT_EQ(AllEntriesFor("foo"), "[ v2, DEL, v1 ]"); - Slice z("z"); - dbfull()->TEST_CompactRange(last-2, NULL, &z); - // DEL eliminated, but v1 remains because we aren't compacting that level - // (DEL can be eliminated because v2 hides v1). - ASSERT_EQ(AllEntriesFor("foo"), "[ v2, v1 ]"); - dbfull()->TEST_CompactRange(last-1, NULL, NULL); - // Merging last-1 w/ last, so we are the base level for "foo", so - // DEL is removed. (as is v1). - ASSERT_EQ(AllEntriesFor("foo"), "[ v2 ]"); -} - -TEST(DBTest, DeletionMarkers2) { - Put("foo", "v1"); - ASSERT_OK(dbfull()->TEST_CompactMemTable()); - const int last = config::kMaxMemCompactLevel; - ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo => v1 is now in last level - - // Place a table at level last-1 to prevent merging with preceding mutation - Put("a", "begin"); - Put("z", "end"); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ(NumTableFilesAtLevel(last), 1); - ASSERT_EQ(NumTableFilesAtLevel(last-1), 1); - - Delete("foo"); - ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); - ASSERT_OK(dbfull()->TEST_CompactMemTable()); // Moves to level last-2 - ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); - dbfull()->TEST_CompactRange(last-2, NULL, NULL); - // DEL kept: "last" file overlaps - ASSERT_EQ(AllEntriesFor("foo"), "[ DEL, v1 ]"); - dbfull()->TEST_CompactRange(last-1, NULL, NULL); - // Merging last-1 w/ last, so we are the base level for "foo", so - // DEL is removed. (as is v1). - ASSERT_EQ(AllEntriesFor("foo"), "[ ]"); -} - -TEST(DBTest, OverlapInLevel0) { - do { - ASSERT_EQ(config::kMaxMemCompactLevel, 2) << "Fix test to match config"; - - // Fill levels 1 and 2 to disable the pushing of new memtables to levels > 0. - ASSERT_OK(Put("100", "v100")); - ASSERT_OK(Put("999", "v999")); - dbfull()->TEST_CompactMemTable(); - ASSERT_OK(Delete("100")); - ASSERT_OK(Delete("999")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("0,1,1", FilesPerLevel()); - - // Make files spanning the following ranges in level-0: - // files[0] 200 .. 900 - // files[1] 300 .. 500 - // Note that files are sorted by smallest key. - ASSERT_OK(Put("300", "v300")); - ASSERT_OK(Put("500", "v500")); - dbfull()->TEST_CompactMemTable(); - ASSERT_OK(Put("200", "v200")); - ASSERT_OK(Put("600", "v600")); - ASSERT_OK(Put("900", "v900")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("2,1,1", FilesPerLevel()); - - // Compact away the placeholder files we created initially - dbfull()->TEST_CompactRange(1, NULL, NULL); - dbfull()->TEST_CompactRange(2, NULL, NULL); - ASSERT_EQ("2", FilesPerLevel()); - - // Do a memtable compaction. Before bug-fix, the compaction would - // not detect the overlap with level-0 files and would incorrectly place - // the deletion in a deeper level. - ASSERT_OK(Delete("600")); - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("3", FilesPerLevel()); - ASSERT_EQ("NOT_FOUND", Get("600")); - } while (ChangeOptions()); -} - -TEST(DBTest, L0_CompactionBug_Issue44_a) { - Reopen(); - ASSERT_OK(Put("b", "v")); - Reopen(); - ASSERT_OK(Delete("b")); - ASSERT_OK(Delete("a")); - Reopen(); - ASSERT_OK(Delete("a")); - Reopen(); - ASSERT_OK(Put("a", "v")); - Reopen(); - Reopen(); - ASSERT_EQ("(a->v)", Contents()); - DelayMilliseconds(1000); // Wait for compaction to finish - ASSERT_EQ("(a->v)", Contents()); -} - -TEST(DBTest, L0_CompactionBug_Issue44_b) { - Reopen(); - Put("",""); - Reopen(); - Delete("e"); - Put("",""); - Reopen(); - Put("c", "cv"); - Reopen(); - Put("",""); - Reopen(); - Put("",""); - DelayMilliseconds(1000); // Wait for compaction to finish - Reopen(); - Put("d","dv"); - Reopen(); - Put("",""); - Reopen(); - Delete("d"); - Delete("b"); - Reopen(); - ASSERT_EQ("(->)(c->cv)", Contents()); - DelayMilliseconds(1000); // Wait for compaction to finish - ASSERT_EQ("(->)(c->cv)", Contents()); -} - -TEST(DBTest, ComparatorCheck) { - class NewComparator : public Comparator { - public: - virtual const char* Name() const { return "leveldb.NewComparator"; } - virtual int Compare(const Slice& a, const Slice& b) const { - return BytewiseComparator()->Compare(a, b); - } - virtual void FindShortestSeparator(std::string* s, const Slice& l) const { - BytewiseComparator()->FindShortestSeparator(s, l); - } - virtual void FindShortSuccessor(std::string* key) const { - BytewiseComparator()->FindShortSuccessor(key); - } - }; - NewComparator cmp; - Options new_options = CurrentOptions(); - new_options.comparator = &cmp; - Status s = TryReopen(&new_options); - ASSERT_TRUE(!s.ok()); - ASSERT_TRUE(s.ToString().find("comparator") != std::string::npos) - << s.ToString(); -} - -TEST(DBTest, CustomComparator) { - class NumberComparator : public Comparator { - public: - virtual const char* Name() const { return "test.NumberComparator"; } - virtual int Compare(const Slice& a, const Slice& b) const { - return ToNumber(a) - ToNumber(b); - } - virtual void FindShortestSeparator(std::string* s, const Slice& l) const { - ToNumber(*s); // Check format - ToNumber(l); // Check format - } - virtual void FindShortSuccessor(std::string* key) const { - ToNumber(*key); // Check format - } - private: - static int ToNumber(const Slice& x) { - // Check that there are no extra characters. - ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']') - << EscapeString(x); - int val; - char ignored; - ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1) - << EscapeString(x); - return val; - } - }; - NumberComparator cmp; - Options new_options = CurrentOptions(); - new_options.create_if_missing = true; - new_options.comparator = &cmp; - new_options.filter_policy = NULL; // Cannot use bloom filters - new_options.write_buffer_size = 1000; // Compact more often - DestroyAndReopen(&new_options); - ASSERT_OK(Put("[10]", "ten")); - ASSERT_OK(Put("[0x14]", "twenty")); - for (int i = 0; i < 2; i++) { - ASSERT_EQ("ten", Get("[10]")); - ASSERT_EQ("ten", Get("[0xa]")); - ASSERT_EQ("twenty", Get("[20]")); - ASSERT_EQ("twenty", Get("[0x14]")); - ASSERT_EQ("NOT_FOUND", Get("[15]")); - ASSERT_EQ("NOT_FOUND", Get("[0xf]")); - Compact("[0]", "[9999]"); - } - - for (int run = 0; run < 2; run++) { - for (int i = 0; i < 1000; i++) { - char buf[100]; - snprintf(buf, sizeof(buf), "[%d]", i*10); - ASSERT_OK(Put(buf, buf)); - } - Compact("[0]", "[1000000]"); - } -} - -TEST(DBTest, ManualCompaction) { - ASSERT_EQ(config::kMaxMemCompactLevel, 2) - << "Need to update this test to match kMaxMemCompactLevel"; - - MakeTables(3, "p", "q"); - ASSERT_EQ("1,1,1", FilesPerLevel()); - - // Compaction range falls before files - Compact("", "c"); - ASSERT_EQ("1,1,1", FilesPerLevel()); - - // Compaction range falls after files - Compact("r", "z"); - ASSERT_EQ("1,1,1", FilesPerLevel()); - - // Compaction range overlaps files - Compact("p1", "p9"); - ASSERT_EQ("0,0,1", FilesPerLevel()); - - // Populate a different range - MakeTables(3, "c", "e"); - ASSERT_EQ("1,1,2", FilesPerLevel()); - - // Compact just the new range - Compact("b", "f"); - ASSERT_EQ("0,0,2", FilesPerLevel()); - - // Compact all - MakeTables(1, "a", "z"); - ASSERT_EQ("0,1,2", FilesPerLevel()); - db_->CompactRange(NULL, NULL); - ASSERT_EQ("0,0,1", FilesPerLevel()); -} - -TEST(DBTest, DBOpen_Options) { - std::string dbname = test::TmpDir() + "/db_options_test"; - DestroyDB(dbname, Options()); - - // Does not exist, and create_if_missing == false: error - DB* db = NULL; - Options opts; - opts.create_if_missing = false; - Status s = DB::Open(opts, dbname, &db); - ASSERT_TRUE(strstr(s.ToString().c_str(), "does not exist") != NULL); - ASSERT_TRUE(db == NULL); - - // Does not exist, and create_if_missing == true: OK - opts.create_if_missing = true; - s = DB::Open(opts, dbname, &db); - ASSERT_OK(s); - ASSERT_TRUE(db != NULL); - - delete db; - db = NULL; - - // Does exist, and error_if_exists == true: error - opts.create_if_missing = false; - opts.error_if_exists = true; - s = DB::Open(opts, dbname, &db); - ASSERT_TRUE(strstr(s.ToString().c_str(), "exists") != NULL); - ASSERT_TRUE(db == NULL); - - // Does exist, and error_if_exists == false: OK - opts.create_if_missing = true; - opts.error_if_exists = false; - s = DB::Open(opts, dbname, &db); - ASSERT_OK(s); - ASSERT_TRUE(db != NULL); - - delete db; - db = NULL; -} - -TEST(DBTest, Locking) { - DB* db2 = NULL; - Status s = DB::Open(CurrentOptions(), dbname_, &db2); - ASSERT_TRUE(!s.ok()) << "Locking did not prevent re-opening db"; -} - -// Check that number of files does not grow when we are out of space -TEST(DBTest, NoSpace) { - Options options = CurrentOptions(); - options.env = env_; - Reopen(&options); - - ASSERT_OK(Put("foo", "v1")); - ASSERT_EQ("v1", Get("foo")); - Compact("a", "z"); - const int num_files = CountFiles(); - env_->no_space_.Release_Store(env_); // Force out-of-space errors - for (int i = 0; i < 10; i++) { - for (int level = 0; level < config::kNumLevels-1; level++) { - dbfull()->TEST_CompactRange(level, NULL, NULL); - } - } - env_->no_space_.Release_Store(NULL); - ASSERT_LT(CountFiles(), num_files + 3); -} - -TEST(DBTest, NonWritableFileSystem) { - Options options = CurrentOptions(); - options.write_buffer_size = 1000; - options.env = env_; - Reopen(&options); - ASSERT_OK(Put("foo", "v1")); - env_->non_writable_.Release_Store(env_); // Force errors for new files - std::string big(100000, 'x'); - int errors = 0; - for (int i = 0; i < 20; i++) { - fprintf(stderr, "iter %d; errors %d\n", i, errors); - if (!Put("foo", big).ok()) { - errors++; - DelayMilliseconds(100); - } - } - ASSERT_GT(errors, 0); - env_->non_writable_.Release_Store(NULL); -} - -TEST(DBTest, WriteSyncError) { - // Check that log sync errors cause the DB to disallow future writes. - - // (a) Cause log sync calls to fail - Options options = CurrentOptions(); - options.env = env_; - Reopen(&options); - env_->data_sync_error_.Release_Store(env_); - - // (b) Normal write should succeed - WriteOptions w; - ASSERT_OK(db_->Put(w, "k1", "v1")); - ASSERT_EQ("v1", Get("k1")); - - // (c) Do a sync write; should fail - w.sync = true; - ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok()); - ASSERT_EQ("v1", Get("k1")); - ASSERT_EQ("NOT_FOUND", Get("k2")); - - // (d) make sync behave normally - env_->data_sync_error_.Release_Store(NULL); - - // (e) Do a non-sync write; should fail - w.sync = false; - ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok()); - ASSERT_EQ("v1", Get("k1")); - ASSERT_EQ("NOT_FOUND", Get("k2")); - ASSERT_EQ("NOT_FOUND", Get("k3")); -} - -TEST(DBTest, ManifestWriteError) { - // Test for the following problem: - // (a) Compaction produces file F - // (b) Log record containing F is written to MANIFEST file, but Sync() fails - // (c) GC deletes F - // (d) After reopening DB, reads fail since deleted F is named in log record - - // We iterate twice. In the second iteration, everything is the - // same except the log record never makes it to the MANIFEST file. - for (int iter = 0; iter < 2; iter++) { - port::AtomicPointer* error_type = (iter == 0) - ? &env_->manifest_sync_error_ - : &env_->manifest_write_error_; - - // Insert foo=>bar mapping - Options options = CurrentOptions(); - options.env = env_; - options.create_if_missing = true; - options.error_if_exists = false; - DestroyAndReopen(&options); - ASSERT_OK(Put("foo", "bar")); - ASSERT_EQ("bar", Get("foo")); - - // Memtable compaction (will succeed) - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("bar", Get("foo")); - const int last = config::kMaxMemCompactLevel; - ASSERT_EQ(NumTableFilesAtLevel(last), 1); // foo=>bar is now in last level - - // Merging compaction (will fail) - error_type->Release_Store(env_); - dbfull()->TEST_CompactRange(last, NULL, NULL); // Should fail - ASSERT_EQ("bar", Get("foo")); - - // Recovery: should not lose data - error_type->Release_Store(NULL); - Reopen(&options); - ASSERT_EQ("bar", Get("foo")); - } -} - -TEST(DBTest, MissingSSTFile) { - ASSERT_OK(Put("foo", "bar")); - ASSERT_EQ("bar", Get("foo")); - - // Dump the memtable to disk. - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("bar", Get("foo")); - - Close(); - ASSERT_TRUE(DeleteAnSSTFile()); - Options options = CurrentOptions(); - options.paranoid_checks = true; - Status s = TryReopen(&options); - ASSERT_TRUE(!s.ok()); - ASSERT_TRUE(s.ToString().find("issing") != std::string::npos) - << s.ToString(); -} - -TEST(DBTest, StillReadSST) { - ASSERT_OK(Put("foo", "bar")); - ASSERT_EQ("bar", Get("foo")); - - // Dump the memtable to disk. - dbfull()->TEST_CompactMemTable(); - ASSERT_EQ("bar", Get("foo")); - Close(); - ASSERT_GT(RenameLDBToSST(), 0); - Options options = CurrentOptions(); - options.paranoid_checks = true; - Status s = TryReopen(&options); - ASSERT_TRUE(s.ok()); - ASSERT_EQ("bar", Get("foo")); -} - -TEST(DBTest, FilesDeletedAfterCompaction) { - ASSERT_OK(Put("foo", "v2")); - Compact("a", "z"); - const int num_files = CountFiles(); - for (int i = 0; i < 10; i++) { - ASSERT_OK(Put("foo", "v2")); - Compact("a", "z"); - } - ASSERT_EQ(CountFiles(), num_files); -} - -TEST(DBTest, BloomFilter) { - env_->count_random_reads_ = true; - Options options = CurrentOptions(); - options.env = env_; - options.block_cache = NewLRUCache(0); // Prevent cache hits - options.filter_policy = NewBloomFilterPolicy(10); - Reopen(&options); - - // Populate multiple layers - const int N = 10000; - for (int i = 0; i < N; i++) { - ASSERT_OK(Put(Key(i), Key(i))); - } - Compact("a", "z"); - for (int i = 0; i < N; i += 100) { - ASSERT_OK(Put(Key(i), Key(i))); - } - dbfull()->TEST_CompactMemTable(); - - // Prevent auto compactions triggered by seeks - env_->delay_data_sync_.Release_Store(env_); - - // Lookup present keys. Should rarely read from small sstable. - env_->random_read_counter_.Reset(); - for (int i = 0; i < N; i++) { - ASSERT_EQ(Key(i), Get(Key(i))); - } - int reads = env_->random_read_counter_.Read(); - fprintf(stderr, "%d present => %d reads\n", N, reads); - ASSERT_GE(reads, N); - ASSERT_LE(reads, N + 2*N/100); - - // Lookup present keys. Should rarely read from either sstable. - env_->random_read_counter_.Reset(); - for (int i = 0; i < N; i++) { - ASSERT_EQ("NOT_FOUND", Get(Key(i) + ".missing")); - } - reads = env_->random_read_counter_.Read(); - fprintf(stderr, "%d missing => %d reads\n", N, reads); - ASSERT_LE(reads, 3*N/100); - - env_->delay_data_sync_.Release_Store(NULL); - Close(); - delete options.block_cache; - delete options.filter_policy; -} - -// Multi-threaded test: -namespace { - -static const int kNumThreads = 4; -static const int kTestSeconds = 10; -static const int kNumKeys = 1000; - -struct MTState { - DBTest* test; - port::AtomicPointer stop; - port::AtomicPointer counter[kNumThreads]; - port::AtomicPointer thread_done[kNumThreads]; -}; - -struct MTThread { - MTState* state; - int id; -}; - -static void MTThreadBody(void* arg) { - MTThread* t = reinterpret_cast(arg); - int id = t->id; - DB* db = t->state->test->db_; - uintptr_t counter = 0; - fprintf(stderr, "... starting thread %d\n", id); - Random rnd(1000 + id); - std::string value; - char valbuf[1500]; - while (t->state->stop.Acquire_Load() == NULL) { - t->state->counter[id].Release_Store(reinterpret_cast(counter)); - - int key = rnd.Uniform(kNumKeys); - char keybuf[20]; - snprintf(keybuf, sizeof(keybuf), "%016d", key); - - if (rnd.OneIn(2)) { - // Write values of the form . - // We add some padding for force compactions. - snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d", - key, id, static_cast(counter)); - ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf))); - } else { - // Read a value and verify that it matches the pattern written above. - Status s = db->Get(ReadOptions(), Slice(keybuf), &value); - if (s.IsNotFound()) { - // Key has not yet been written - } else { - // Check that the writer thread counter is >= the counter in the value - ASSERT_OK(s); - int k, w, c; - ASSERT_EQ(3, sscanf(value.c_str(), "%d.%d.%d", &k, &w, &c)) << value; - ASSERT_EQ(k, key); - ASSERT_GE(w, 0); - ASSERT_LT(w, kNumThreads); - ASSERT_LE(static_cast(c), reinterpret_cast( - t->state->counter[w].Acquire_Load())); - } - } - counter++; - } - t->state->thread_done[id].Release_Store(t); - fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter)); -} - -} // namespace - -TEST(DBTest, MultiThreaded) { - do { - // Initialize state - MTState mt; - mt.test = this; - mt.stop.Release_Store(0); - for (int id = 0; id < kNumThreads; id++) { - mt.counter[id].Release_Store(0); - mt.thread_done[id].Release_Store(0); - } - - // Start threads - MTThread thread[kNumThreads]; - for (int id = 0; id < kNumThreads; id++) { - thread[id].state = &mt; - thread[id].id = id; - env_->StartThread(MTThreadBody, &thread[id]); - } - - // Let them run for a while - DelayMilliseconds(kTestSeconds * 1000); - - // Stop the threads and wait for them to finish - mt.stop.Release_Store(&mt); - for (int id = 0; id < kNumThreads; id++) { - while (mt.thread_done[id].Acquire_Load() == NULL) { - DelayMilliseconds(100); - } - } - } while (ChangeOptions()); -} - -namespace { -typedef std::map KVMap; -} - -class ModelDB: public DB { - public: - class ModelSnapshot : public Snapshot { - public: - KVMap map_; - }; - - explicit ModelDB(const Options& options): options_(options) { } - ~ModelDB() { } - virtual Status Put(const WriteOptions& o, const Slice& k, const Slice& v) { - return DB::Put(o, k, v); - } - virtual Status Delete(const WriteOptions& o, const Slice& key) { - return DB::Delete(o, key); - } - virtual Status Get(const ReadOptions& options, - const Slice& key, std::string* value) { - assert(false); // Not implemented - return Status::NotFound(key); - } - virtual Iterator* NewIterator(const ReadOptions& options) { - if (options.snapshot == NULL) { - KVMap* saved = new KVMap; - *saved = map_; - return new ModelIter(saved, true); - } else { - const KVMap* snapshot_state = - &(reinterpret_cast(options.snapshot)->map_); - return new ModelIter(snapshot_state, false); - } - } - virtual const Snapshot* GetSnapshot() { - ModelSnapshot* snapshot = new ModelSnapshot; - snapshot->map_ = map_; - return snapshot; - } - - virtual void ReleaseSnapshot(const Snapshot* snapshot) { - delete reinterpret_cast(snapshot); - } - virtual Status Write(const WriteOptions& options, WriteBatch* batch) { - class Handler : public WriteBatch::Handler { - public: - KVMap* map_; - virtual void Put(const Slice& key, const Slice& value) { - (*map_)[key.ToString()] = value.ToString(); - } - virtual void Delete(const Slice& key) { - map_->erase(key.ToString()); - } - }; - Handler handler; - handler.map_ = &map_; - return batch->Iterate(&handler); - } - - virtual bool GetProperty(const Slice& property, std::string* value) { - return false; - } - virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) { - for (int i = 0; i < n; i++) { - sizes[i] = 0; - } - } - virtual void CompactRange(const Slice* start, const Slice* end) { - } - - private: - class ModelIter: public Iterator { - public: - ModelIter(const KVMap* map, bool owned) - : map_(map), owned_(owned), iter_(map_->end()) { - } - ~ModelIter() { - if (owned_) delete map_; - } - virtual bool Valid() const { return iter_ != map_->end(); } - virtual void SeekToFirst() { iter_ = map_->begin(); } - virtual void SeekToLast() { - if (map_->empty()) { - iter_ = map_->end(); - } else { - iter_ = map_->find(map_->rbegin()->first); - } - } - virtual void Seek(const Slice& k) { - iter_ = map_->lower_bound(k.ToString()); - } - virtual void Next() { ++iter_; } - virtual void Prev() { --iter_; } - virtual Slice key() const { return iter_->first; } - virtual Slice value() const { return iter_->second; } - virtual Status status() const { return Status::OK(); } - private: - const KVMap* const map_; - const bool owned_; // Do we own map_ - KVMap::const_iterator iter_; - }; - const Options options_; - KVMap map_; -}; - -static std::string RandomKey(Random* rnd) { - int len = (rnd->OneIn(3) - ? 1 // Short sometimes to encourage collisions - : (rnd->OneIn(100) ? rnd->Skewed(10) : rnd->Uniform(10))); - return test::RandomKey(rnd, len); -} - -static bool CompareIterators(int step, - DB* model, - DB* db, - const Snapshot* model_snap, - const Snapshot* db_snap) { - ReadOptions options; - options.snapshot = model_snap; - Iterator* miter = model->NewIterator(options); - options.snapshot = db_snap; - Iterator* dbiter = db->NewIterator(options); - bool ok = true; - int count = 0; - for (miter->SeekToFirst(), dbiter->SeekToFirst(); - ok && miter->Valid() && dbiter->Valid(); - miter->Next(), dbiter->Next()) { - count++; - if (miter->key().compare(dbiter->key()) != 0) { - fprintf(stderr, "step %d: Key mismatch: '%s' vs. '%s'\n", - step, - EscapeString(miter->key()).c_str(), - EscapeString(dbiter->key()).c_str()); - ok = false; - break; - } - - if (miter->value().compare(dbiter->value()) != 0) { - fprintf(stderr, "step %d: Value mismatch for key '%s': '%s' vs. '%s'\n", - step, - EscapeString(miter->key()).c_str(), - EscapeString(miter->value()).c_str(), - EscapeString(miter->value()).c_str()); - ok = false; - } - } - - if (ok) { - if (miter->Valid() != dbiter->Valid()) { - fprintf(stderr, "step %d: Mismatch at end of iterators: %d vs. %d\n", - step, miter->Valid(), dbiter->Valid()); - ok = false; - } - } - fprintf(stderr, "%d entries compared: ok=%d\n", count, ok); - delete miter; - delete dbiter; - return ok; -} - -TEST(DBTest, Randomized) { - Random rnd(test::RandomSeed()); - do { - ModelDB model(CurrentOptions()); - const int N = 10000; - const Snapshot* model_snap = NULL; - const Snapshot* db_snap = NULL; - std::string k, v; - for (int step = 0; step < N; step++) { - if (step % 100 == 0) { - fprintf(stderr, "Step %d of %d\n", step, N); - } - // TODO(sanjay): Test Get() works - int p = rnd.Uniform(100); - if (p < 45) { // Put - k = RandomKey(&rnd); - v = RandomString(&rnd, - rnd.OneIn(20) - ? 100 + rnd.Uniform(100) - : rnd.Uniform(8)); - ASSERT_OK(model.Put(WriteOptions(), k, v)); - ASSERT_OK(db_->Put(WriteOptions(), k, v)); - - } else if (p < 90) { // Delete - k = RandomKey(&rnd); - ASSERT_OK(model.Delete(WriteOptions(), k)); - ASSERT_OK(db_->Delete(WriteOptions(), k)); - - - } else { // Multi-element batch - WriteBatch b; - const int num = rnd.Uniform(8); - for (int i = 0; i < num; i++) { - if (i == 0 || !rnd.OneIn(10)) { - k = RandomKey(&rnd); - } else { - // Periodically re-use the same key from the previous iter, so - // we have multiple entries in the write batch for the same key - } - if (rnd.OneIn(2)) { - v = RandomString(&rnd, rnd.Uniform(10)); - b.Put(k, v); - } else { - b.Delete(k); - } - } - ASSERT_OK(model.Write(WriteOptions(), &b)); - ASSERT_OK(db_->Write(WriteOptions(), &b)); - } - - if ((step % 100) == 0) { - ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); - ASSERT_TRUE(CompareIterators(step, &model, db_, model_snap, db_snap)); - // Save a snapshot from each DB this time that we'll use next - // time we compare things, to make sure the current state is - // preserved with the snapshot - if (model_snap != NULL) model.ReleaseSnapshot(model_snap); - if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); - - Reopen(); - ASSERT_TRUE(CompareIterators(step, &model, db_, NULL, NULL)); - - model_snap = model.GetSnapshot(); - db_snap = db_->GetSnapshot(); - } - } - if (model_snap != NULL) model.ReleaseSnapshot(model_snap); - if (db_snap != NULL) db_->ReleaseSnapshot(db_snap); - } while (ChangeOptions()); -} - -std::string MakeKey(unsigned int num) { - char buf[30]; - snprintf(buf, sizeof(buf), "%016u", num); - return std::string(buf); -} - -void BM_LogAndApply(int iters, int num_base_files) { - std::string dbname = test::TmpDir() + "/leveldb_test_benchmark"; - DestroyDB(dbname, Options()); - - DB* db = NULL; - Options opts; - opts.create_if_missing = true; - Status s = DB::Open(opts, dbname, &db); - ASSERT_OK(s); - ASSERT_TRUE(db != NULL); - - delete db; - db = NULL; - - Env* env = Env::Default(); - - port::Mutex mu; - MutexLock l(&mu); - - InternalKeyComparator cmp(BytewiseComparator()); - Options options; - VersionSet vset(dbname, &options, NULL, &cmp); - ASSERT_OK(vset.Recover()); - VersionEdit vbase; - uint64_t fnum = 1; - for (int i = 0; i < num_base_files; i++) { - InternalKey start(MakeKey(2*fnum), 1, kTypeValue); - InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); - vbase.AddFile(2, fnum++, 1 /* file size */, start, limit); - } - ASSERT_OK(vset.LogAndApply(&vbase, &mu)); - - uint64_t start_micros = env->NowMicros(); - - for (int i = 0; i < iters; i++) { - VersionEdit vedit; - vedit.DeleteFile(2, fnum); - InternalKey start(MakeKey(2*fnum), 1, kTypeValue); - InternalKey limit(MakeKey(2*fnum+1), 1, kTypeDeletion); - vedit.AddFile(2, fnum++, 1 /* file size */, start, limit); - vset.LogAndApply(&vedit, &mu); - } - uint64_t stop_micros = env->NowMicros(); - unsigned int us = stop_micros - start_micros; - char buf[16]; - snprintf(buf, sizeof(buf), "%d", num_base_files); - fprintf(stderr, - "BM_LogAndApply/%-6s %8d iters : %9u us (%7.0f us / iter)\n", - buf, iters, us, ((float)us) / iters); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - if (argc > 1 && std::string(argv[1]) == "--benchmark") { - leveldb::BM_LogAndApply(1000, 1); - leveldb::BM_LogAndApply(1000, 100); - leveldb::BM_LogAndApply(1000, 10000); - leveldb::BM_LogAndApply(100, 100000); - return 0; - } - - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/dbformat.cc b/src/leveldb/db/dbformat.cc deleted file mode 100644 index 20a7ca4462..0000000000 --- a/src/leveldb/db/dbformat.cc +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include "db/dbformat.h" -#include "port/port.h" -#include "util/coding.h" - -namespace leveldb { - -static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { - assert(seq <= kMaxSequenceNumber); - assert(t <= kValueTypeForSeek); - return (seq << 8) | t; -} - -void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { - result->append(key.user_key.data(), key.user_key.size()); - PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); -} - -std::string ParsedInternalKey::DebugString() const { - char buf[50]; - snprintf(buf, sizeof(buf), "' @ %llu : %d", - (unsigned long long) sequence, - int(type)); - std::string result = "'"; - result += EscapeString(user_key.ToString()); - result += buf; - return result; -} - -std::string InternalKey::DebugString() const { - std::string result; - ParsedInternalKey parsed; - if (ParseInternalKey(rep_, &parsed)) { - result = parsed.DebugString(); - } else { - result = "(bad)"; - result.append(EscapeString(rep_)); - } - return result; -} - -const char* InternalKeyComparator::Name() const { - return "leveldb.InternalKeyComparator"; -} - -int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { - // Order by: - // increasing user key (according to user-supplied comparator) - // decreasing sequence number - // decreasing type (though sequence# should be enough to disambiguate) - int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); - if (r == 0) { - const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); - const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); - if (anum > bnum) { - r = -1; - } else if (anum < bnum) { - r = +1; - } - } - return r; -} - -void InternalKeyComparator::FindShortestSeparator( - std::string* start, - const Slice& limit) const { - // Attempt to shorten the user portion of the key - Slice user_start = ExtractUserKey(*start); - Slice user_limit = ExtractUserKey(limit); - std::string tmp(user_start.data(), user_start.size()); - user_comparator_->FindShortestSeparator(&tmp, user_limit); - if (tmp.size() < user_start.size() && - user_comparator_->Compare(user_start, tmp) < 0) { - // User key has become shorter physically, but larger logically. - // Tack on the earliest possible number to the shortened user key. - PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); - assert(this->Compare(*start, tmp) < 0); - assert(this->Compare(tmp, limit) < 0); - start->swap(tmp); - } -} - -void InternalKeyComparator::FindShortSuccessor(std::string* key) const { - Slice user_key = ExtractUserKey(*key); - std::string tmp(user_key.data(), user_key.size()); - user_comparator_->FindShortSuccessor(&tmp); - if (tmp.size() < user_key.size() && - user_comparator_->Compare(user_key, tmp) < 0) { - // User key has become shorter physically, but larger logically. - // Tack on the earliest possible number to the shortened user key. - PutFixed64(&tmp, PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek)); - assert(this->Compare(*key, tmp) < 0); - key->swap(tmp); - } -} - -const char* InternalFilterPolicy::Name() const { - return user_policy_->Name(); -} - -void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, - std::string* dst) const { - // We rely on the fact that the code in table.cc does not mind us - // adjusting keys[]. - Slice* mkey = const_cast(keys); - for (int i = 0; i < n; i++) { - mkey[i] = ExtractUserKey(keys[i]); - // TODO(sanjay): Suppress dups? - } - user_policy_->CreateFilter(keys, n, dst); -} - -bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { - return user_policy_->KeyMayMatch(ExtractUserKey(key), f); -} - -LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { - size_t usize = user_key.size(); - size_t needed = usize + 13; // A conservative estimate - char* dst; - if (needed <= sizeof(space_)) { - dst = space_; - } else { - dst = new char[needed]; - } - start_ = dst; - dst = EncodeVarint32(dst, usize + 8); - kstart_ = dst; - memcpy(dst, user_key.data(), usize); - dst += usize; - EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); - dst += 8; - end_ = dst; -} - -} // namespace leveldb diff --git a/src/leveldb/db/dbformat.h b/src/leveldb/db/dbformat.h deleted file mode 100644 index ea897b13c0..0000000000 --- a/src/leveldb/db/dbformat.h +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_ -#define STORAGE_LEVELDB_DB_DBFORMAT_H_ - -#include -#include "leveldb/comparator.h" -#include "leveldb/db.h" -#include "leveldb/filter_policy.h" -#include "leveldb/slice.h" -#include "leveldb/table_builder.h" -#include "util/coding.h" -#include "util/logging.h" - -namespace leveldb { - -// Grouping of constants. We may want to make some of these -// parameters set via options. -namespace config { -static const int kNumLevels = 7; - -// Level-0 compaction is started when we hit this many files. -static const int kL0_CompactionTrigger = 4; - -// Soft limit on number of level-0 files. We slow down writes at this point. -static const int kL0_SlowdownWritesTrigger = 8; - -// Maximum number of level-0 files. We stop writes at this point. -static const int kL0_StopWritesTrigger = 12; - -// Maximum level to which a new compacted memtable is pushed if it -// does not create overlap. We try to push to level 2 to avoid the -// relatively expensive level 0=>1 compactions and to avoid some -// expensive manifest file operations. We do not push all the way to -// the largest level since that can generate a lot of wasted disk -// space if the same key space is being repeatedly overwritten. -static const int kMaxMemCompactLevel = 2; - -// Approximate gap in bytes between samples of data read during iteration. -static const int kReadBytesPeriod = 1048576; - -} // namespace config - -class InternalKey; - -// Value types encoded as the last component of internal keys. -// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk -// data structures. -enum ValueType { - kTypeDeletion = 0x0, - kTypeValue = 0x1 -}; -// kValueTypeForSeek defines the ValueType that should be passed when -// constructing a ParsedInternalKey object for seeking to a particular -// sequence number (since we sort sequence numbers in decreasing order -// and the value type is embedded as the low 8 bits in the sequence -// number in internal keys, we need to use the highest-numbered -// ValueType, not the lowest). -static const ValueType kValueTypeForSeek = kTypeValue; - -typedef uint64_t SequenceNumber; - -// We leave eight bits empty at the bottom so a type and sequence# -// can be packed together into 64-bits. -static const SequenceNumber kMaxSequenceNumber = - ((0x1ull << 56) - 1); - -struct ParsedInternalKey { - Slice user_key; - SequenceNumber sequence; - ValueType type; - - ParsedInternalKey() { } // Intentionally left uninitialized (for speed) - ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) - : user_key(u), sequence(seq), type(t) { } - std::string DebugString() const; -}; - -// Return the length of the encoding of "key". -inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { - return key.user_key.size() + 8; -} - -// Append the serialization of "key" to *result. -extern void AppendInternalKey(std::string* result, - const ParsedInternalKey& key); - -// Attempt to parse an internal key from "internal_key". On success, -// stores the parsed data in "*result", and returns true. -// -// On error, returns false, leaves "*result" in an undefined state. -extern bool ParseInternalKey(const Slice& internal_key, - ParsedInternalKey* result); - -// Returns the user key portion of an internal key. -inline Slice ExtractUserKey(const Slice& internal_key) { - assert(internal_key.size() >= 8); - return Slice(internal_key.data(), internal_key.size() - 8); -} - -inline ValueType ExtractValueType(const Slice& internal_key) { - assert(internal_key.size() >= 8); - const size_t n = internal_key.size(); - uint64_t num = DecodeFixed64(internal_key.data() + n - 8); - unsigned char c = num & 0xff; - return static_cast(c); -} - -// A comparator for internal keys that uses a specified comparator for -// the user key portion and breaks ties by decreasing sequence number. -class InternalKeyComparator : public Comparator { - private: - const Comparator* user_comparator_; - public: - explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) { } - virtual const char* Name() const; - virtual int Compare(const Slice& a, const Slice& b) const; - virtual void FindShortestSeparator( - std::string* start, - const Slice& limit) const; - virtual void FindShortSuccessor(std::string* key) const; - - const Comparator* user_comparator() const { return user_comparator_; } - - int Compare(const InternalKey& a, const InternalKey& b) const; -}; - -// Filter policy wrapper that converts from internal keys to user keys -class InternalFilterPolicy : public FilterPolicy { - private: - const FilterPolicy* const user_policy_; - public: - explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) { } - virtual const char* Name() const; - virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; - virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; -}; - -// Modules in this directory should keep internal keys wrapped inside -// the following class instead of plain strings so that we do not -// incorrectly use string comparisons instead of an InternalKeyComparator. -class InternalKey { - private: - std::string rep_; - public: - InternalKey() { } // Leave rep_ as empty to indicate it is invalid - InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { - AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); - } - - void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } - Slice Encode() const { - assert(!rep_.empty()); - return rep_; - } - - Slice user_key() const { return ExtractUserKey(rep_); } - - void SetFrom(const ParsedInternalKey& p) { - rep_.clear(); - AppendInternalKey(&rep_, p); - } - - void Clear() { rep_.clear(); } - - std::string DebugString() const; -}; - -inline int InternalKeyComparator::Compare( - const InternalKey& a, const InternalKey& b) const { - return Compare(a.Encode(), b.Encode()); -} - -inline bool ParseInternalKey(const Slice& internal_key, - ParsedInternalKey* result) { - const size_t n = internal_key.size(); - if (n < 8) return false; - uint64_t num = DecodeFixed64(internal_key.data() + n - 8); - unsigned char c = num & 0xff; - result->sequence = num >> 8; - result->type = static_cast(c); - result->user_key = Slice(internal_key.data(), n - 8); - return (c <= static_cast(kTypeValue)); -} - -// A helper class useful for DBImpl::Get() -class LookupKey { - public: - // Initialize *this for looking up user_key at a snapshot with - // the specified sequence number. - LookupKey(const Slice& user_key, SequenceNumber sequence); - - ~LookupKey(); - - // Return a key suitable for lookup in a MemTable. - Slice memtable_key() const { return Slice(start_, end_ - start_); } - - // Return an internal key (suitable for passing to an internal iterator) - Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } - - // Return the user key - Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } - - private: - // We construct a char array of the form: - // klength varint32 <-- start_ - // userkey char[klength] <-- kstart_ - // tag uint64 - // <-- end_ - // The array is a suitable MemTable key. - // The suffix starting with "userkey" can be used as an InternalKey. - const char* start_; - const char* kstart_; - const char* end_; - char space_[200]; // Avoid allocation for short keys - - // No copying allowed - LookupKey(const LookupKey&); - void operator=(const LookupKey&); -}; - -inline LookupKey::~LookupKey() { - if (start_ != space_) delete[] start_; -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_DBFORMAT_H_ diff --git a/src/leveldb/db/dbformat_test.cc b/src/leveldb/db/dbformat_test.cc deleted file mode 100644 index 5d82f5d313..0000000000 --- a/src/leveldb/db/dbformat_test.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/dbformat.h" -#include "util/logging.h" -#include "util/testharness.h" - -namespace leveldb { - -static std::string IKey(const std::string& user_key, - uint64_t seq, - ValueType vt) { - std::string encoded; - AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt)); - return encoded; -} - -static std::string Shorten(const std::string& s, const std::string& l) { - std::string result = s; - InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l); - return result; -} - -static std::string ShortSuccessor(const std::string& s) { - std::string result = s; - InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result); - return result; -} - -static void TestKey(const std::string& key, - uint64_t seq, - ValueType vt) { - std::string encoded = IKey(key, seq, vt); - - Slice in(encoded); - ParsedInternalKey decoded("", 0, kTypeValue); - - ASSERT_TRUE(ParseInternalKey(in, &decoded)); - ASSERT_EQ(key, decoded.user_key.ToString()); - ASSERT_EQ(seq, decoded.sequence); - ASSERT_EQ(vt, decoded.type); - - ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded)); -} - -class FormatTest { }; - -TEST(FormatTest, InternalKey_EncodeDecode) { - const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" }; - const uint64_t seq[] = { - 1, 2, 3, - (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1, - (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1, - (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1 - }; - for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) { - for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) { - TestKey(keys[k], seq[s], kTypeValue); - TestKey("hello", 1, kTypeDeletion); - } - } -} - -TEST(FormatTest, InternalKeyShortSeparator) { - // When user keys are same - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("foo", 99, kTypeValue))); - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("foo", 101, kTypeValue))); - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("foo", 100, kTypeValue))); - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("foo", 100, kTypeDeletion))); - - // When user keys are misordered - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("bar", 99, kTypeValue))); - - // When user keys are different, but correctly ordered - ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), - Shorten(IKey("foo", 100, kTypeValue), - IKey("hello", 200, kTypeValue))); - - // When start user key is prefix of limit user key - ASSERT_EQ(IKey("foo", 100, kTypeValue), - Shorten(IKey("foo", 100, kTypeValue), - IKey("foobar", 200, kTypeValue))); - - // When limit user key is prefix of start user key - ASSERT_EQ(IKey("foobar", 100, kTypeValue), - Shorten(IKey("foobar", 100, kTypeValue), - IKey("foo", 200, kTypeValue))); -} - -TEST(FormatTest, InternalKeyShortestSuccessor) { - ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek), - ShortSuccessor(IKey("foo", 100, kTypeValue))); - ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue), - ShortSuccessor(IKey("\xff\xff", 100, kTypeValue))); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/dumpfile.cc b/src/leveldb/db/dumpfile.cc deleted file mode 100644 index 61c47c2ff9..0000000000 --- a/src/leveldb/db/dumpfile.cc +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include "db/dbformat.h" -#include "db/filename.h" -#include "db/log_reader.h" -#include "db/version_edit.h" -#include "db/write_batch_internal.h" -#include "leveldb/env.h" -#include "leveldb/iterator.h" -#include "leveldb/options.h" -#include "leveldb/status.h" -#include "leveldb/table.h" -#include "leveldb/write_batch.h" -#include "util/logging.h" - -namespace leveldb { - -namespace { - -bool GuessType(const std::string& fname, FileType* type) { - size_t pos = fname.rfind('/'); - std::string basename; - if (pos == std::string::npos) { - basename = fname; - } else { - basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1); - } - uint64_t ignored; - return ParseFileName(basename, &ignored, type); -} - -// Notified when log reader encounters corruption. -class CorruptionReporter : public log::Reader::Reporter { - public: - WritableFile* dst_; - virtual void Corruption(size_t bytes, const Status& status) { - std::string r = "corruption: "; - AppendNumberTo(&r, bytes); - r += " bytes; "; - r += status.ToString(); - r.push_back('\n'); - dst_->Append(r); - } -}; - -// Print contents of a log file. (*func)() is called on every record. -Status PrintLogContents(Env* env, const std::string& fname, - void (*func)(uint64_t, Slice, WritableFile*), - WritableFile* dst) { - SequentialFile* file; - Status s = env->NewSequentialFile(fname, &file); - if (!s.ok()) { - return s; - } - CorruptionReporter reporter; - reporter.dst_ = dst; - log::Reader reader(file, &reporter, true, 0); - Slice record; - std::string scratch; - while (reader.ReadRecord(&record, &scratch)) { - (*func)(reader.LastRecordOffset(), record, dst); - } - delete file; - return Status::OK(); -} - -// Called on every item found in a WriteBatch. -class WriteBatchItemPrinter : public WriteBatch::Handler { - public: - WritableFile* dst_; - virtual void Put(const Slice& key, const Slice& value) { - std::string r = " put '"; - AppendEscapedStringTo(&r, key); - r += "' '"; - AppendEscapedStringTo(&r, value); - r += "'\n"; - dst_->Append(r); - } - virtual void Delete(const Slice& key) { - std::string r = " del '"; - AppendEscapedStringTo(&r, key); - r += "'\n"; - dst_->Append(r); - } -}; - - -// Called on every log record (each one of which is a WriteBatch) -// found in a kLogFile. -static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) { - std::string r = "--- offset "; - AppendNumberTo(&r, pos); - r += "; "; - if (record.size() < 12) { - r += "log record length "; - AppendNumberTo(&r, record.size()); - r += " is too small\n"; - dst->Append(r); - return; - } - WriteBatch batch; - WriteBatchInternal::SetContents(&batch, record); - r += "sequence "; - AppendNumberTo(&r, WriteBatchInternal::Sequence(&batch)); - r.push_back('\n'); - dst->Append(r); - WriteBatchItemPrinter batch_item_printer; - batch_item_printer.dst_ = dst; - Status s = batch.Iterate(&batch_item_printer); - if (!s.ok()) { - dst->Append(" error: " + s.ToString() + "\n"); - } -} - -Status DumpLog(Env* env, const std::string& fname, WritableFile* dst) { - return PrintLogContents(env, fname, WriteBatchPrinter, dst); -} - -// Called on every log record (each one of which is a WriteBatch) -// found in a kDescriptorFile. -static void VersionEditPrinter(uint64_t pos, Slice record, WritableFile* dst) { - std::string r = "--- offset "; - AppendNumberTo(&r, pos); - r += "; "; - VersionEdit edit; - Status s = edit.DecodeFrom(record); - if (!s.ok()) { - r += s.ToString(); - r.push_back('\n'); - } else { - r += edit.DebugString(); - } - dst->Append(r); -} - -Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) { - return PrintLogContents(env, fname, VersionEditPrinter, dst); -} - -Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) { - uint64_t file_size; - RandomAccessFile* file = NULL; - Table* table = NULL; - Status s = env->GetFileSize(fname, &file_size); - if (s.ok()) { - s = env->NewRandomAccessFile(fname, &file); - } - if (s.ok()) { - // We use the default comparator, which may or may not match the - // comparator used in this database. However this should not cause - // problems since we only use Table operations that do not require - // any comparisons. In particular, we do not call Seek or Prev. - s = Table::Open(Options(), file, file_size, &table); - } - if (!s.ok()) { - delete table; - delete file; - return s; - } - - ReadOptions ro; - ro.fill_cache = false; - Iterator* iter = table->NewIterator(ro); - std::string r; - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - r.clear(); - ParsedInternalKey key; - if (!ParseInternalKey(iter->key(), &key)) { - r = "badkey '"; - AppendEscapedStringTo(&r, iter->key()); - r += "' => '"; - AppendEscapedStringTo(&r, iter->value()); - r += "'\n"; - dst->Append(r); - } else { - r = "'"; - AppendEscapedStringTo(&r, key.user_key); - r += "' @ "; - AppendNumberTo(&r, key.sequence); - r += " : "; - if (key.type == kTypeDeletion) { - r += "del"; - } else if (key.type == kTypeValue) { - r += "val"; - } else { - AppendNumberTo(&r, key.type); - } - r += " => '"; - AppendEscapedStringTo(&r, iter->value()); - r += "'\n"; - dst->Append(r); - } - } - s = iter->status(); - if (!s.ok()) { - dst->Append("iterator error: " + s.ToString() + "\n"); - } - - delete iter; - delete table; - delete file; - return Status::OK(); -} - -} // namespace - -Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) { - FileType ftype; - if (!GuessType(fname, &ftype)) { - return Status::InvalidArgument(fname + ": unknown file type"); - } - switch (ftype) { - case kLogFile: return DumpLog(env, fname, dst); - case kDescriptorFile: return DumpDescriptor(env, fname, dst); - case kTableFile: return DumpTable(env, fname, dst); - default: - break; - } - return Status::InvalidArgument(fname + ": not a dump-able file type"); -} - -} // namespace leveldb diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc deleted file mode 100644 index da32946d99..0000000000 --- a/src/leveldb/db/filename.cc +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include "db/filename.h" -#include "db/dbformat.h" -#include "leveldb/env.h" -#include "util/logging.h" - -namespace leveldb { - -// A utility routine: write "data" to the named file and Sync() it. -extern Status WriteStringToFileSync(Env* env, const Slice& data, - const std::string& fname); - -static std::string MakeFileName(const std::string& name, uint64_t number, - const char* suffix) { - char buf[100]; - snprintf(buf, sizeof(buf), "/%06llu.%s", - static_cast(number), - suffix); - return name + buf; -} - -std::string LogFileName(const std::string& name, uint64_t number) { - assert(number > 0); - return MakeFileName(name, number, "log"); -} - -std::string TableFileName(const std::string& name, uint64_t number) { - assert(number > 0); - return MakeFileName(name, number, "ldb"); -} - -std::string SSTTableFileName(const std::string& name, uint64_t number) { - assert(number > 0); - return MakeFileName(name, number, "sst"); -} - -std::string DescriptorFileName(const std::string& dbname, uint64_t number) { - assert(number > 0); - char buf[100]; - snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", - static_cast(number)); - return dbname + buf; -} - -std::string CurrentFileName(const std::string& dbname) { - return dbname + "/CURRENT"; -} - -std::string LockFileName(const std::string& dbname) { - return dbname + "/LOCK"; -} - -std::string TempFileName(const std::string& dbname, uint64_t number) { - assert(number > 0); - return MakeFileName(dbname, number, "dbtmp"); -} - -std::string InfoLogFileName(const std::string& dbname) { - return dbname + "/LOG"; -} - -// Return the name of the old info log file for "dbname". -std::string OldInfoLogFileName(const std::string& dbname) { - return dbname + "/LOG.old"; -} - - -// Owned filenames have the form: -// dbname/CURRENT -// dbname/LOCK -// dbname/LOG -// dbname/LOG.old -// dbname/MANIFEST-[0-9]+ -// dbname/[0-9]+.(log|sst|ldb) -bool ParseFileName(const std::string& fname, - uint64_t* number, - FileType* type) { - Slice rest(fname); - if (rest == "CURRENT") { - *number = 0; - *type = kCurrentFile; - } else if (rest == "LOCK") { - *number = 0; - *type = kDBLockFile; - } else if (rest == "LOG" || rest == "LOG.old") { - *number = 0; - *type = kInfoLogFile; - } else if (rest.starts_with("MANIFEST-")) { - rest.remove_prefix(strlen("MANIFEST-")); - uint64_t num; - if (!ConsumeDecimalNumber(&rest, &num)) { - return false; - } - if (!rest.empty()) { - return false; - } - *type = kDescriptorFile; - *number = num; - } else { - // Avoid strtoull() to keep filename format independent of the - // current locale - uint64_t num; - if (!ConsumeDecimalNumber(&rest, &num)) { - return false; - } - Slice suffix = rest; - if (suffix == Slice(".log")) { - *type = kLogFile; - } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) { - *type = kTableFile; - } else if (suffix == Slice(".dbtmp")) { - *type = kTempFile; - } else { - return false; - } - *number = num; - } - return true; -} - -Status SetCurrentFile(Env* env, const std::string& dbname, - uint64_t descriptor_number) { - // Remove leading "dbname/" and add newline to manifest file name - std::string manifest = DescriptorFileName(dbname, descriptor_number); - Slice contents = manifest; - assert(contents.starts_with(dbname + "/")); - contents.remove_prefix(dbname.size() + 1); - std::string tmp = TempFileName(dbname, descriptor_number); - Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); - if (s.ok()) { - s = env->RenameFile(tmp, CurrentFileName(dbname)); - } - if (!s.ok()) { - env->DeleteFile(tmp); - } - return s; -} - -} // namespace leveldb diff --git a/src/leveldb/db/filename.h b/src/leveldb/db/filename.h deleted file mode 100644 index 87a752605d..0000000000 --- a/src/leveldb/db/filename.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// File names used by DB code - -#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ -#define STORAGE_LEVELDB_DB_FILENAME_H_ - -#include -#include -#include "leveldb/slice.h" -#include "leveldb/status.h" -#include "port/port.h" - -namespace leveldb { - -class Env; - -enum FileType { - kLogFile, - kDBLockFile, - kTableFile, - kDescriptorFile, - kCurrentFile, - kTempFile, - kInfoLogFile // Either the current one, or an old one -}; - -// Return the name of the log file with the specified number -// in the db named by "dbname". The result will be prefixed with -// "dbname". -extern std::string LogFileName(const std::string& dbname, uint64_t number); - -// Return the name of the sstable with the specified number -// in the db named by "dbname". The result will be prefixed with -// "dbname". -extern std::string TableFileName(const std::string& dbname, uint64_t number); - -// Return the legacy file name for an sstable with the specified number -// in the db named by "dbname". The result will be prefixed with -// "dbname". -extern std::string SSTTableFileName(const std::string& dbname, uint64_t number); - -// Return the name of the descriptor file for the db named by -// "dbname" and the specified incarnation number. The result will be -// prefixed with "dbname". -extern std::string DescriptorFileName(const std::string& dbname, - uint64_t number); - -// Return the name of the current file. This file contains the name -// of the current manifest file. The result will be prefixed with -// "dbname". -extern std::string CurrentFileName(const std::string& dbname); - -// Return the name of the lock file for the db named by -// "dbname". The result will be prefixed with "dbname". -extern std::string LockFileName(const std::string& dbname); - -// Return the name of a temporary file owned by the db named "dbname". -// The result will be prefixed with "dbname". -extern std::string TempFileName(const std::string& dbname, uint64_t number); - -// Return the name of the info log file for "dbname". -extern std::string InfoLogFileName(const std::string& dbname); - -// Return the name of the old info log file for "dbname". -extern std::string OldInfoLogFileName(const std::string& dbname); - -// If filename is a leveldb file, store the type of the file in *type. -// The number encoded in the filename is stored in *number. If the -// filename was successfully parsed, returns true. Else return false. -extern bool ParseFileName(const std::string& filename, - uint64_t* number, - FileType* type); - -// Make the CURRENT file point to the descriptor file with the -// specified number. -extern Status SetCurrentFile(Env* env, const std::string& dbname, - uint64_t descriptor_number); - - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/src/leveldb/db/filename_test.cc b/src/leveldb/db/filename_test.cc deleted file mode 100644 index a32556deaf..0000000000 --- a/src/leveldb/db/filename_test.cc +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/filename.h" - -#include "db/dbformat.h" -#include "port/port.h" -#include "util/logging.h" -#include "util/testharness.h" - -namespace leveldb { - -class FileNameTest { }; - -TEST(FileNameTest, Parse) { - Slice db; - FileType type; - uint64_t number; - - // Successful parses - static struct { - const char* fname; - uint64_t number; - FileType type; - } cases[] = { - { "100.log", 100, kLogFile }, - { "0.log", 0, kLogFile }, - { "0.sst", 0, kTableFile }, - { "0.ldb", 0, kTableFile }, - { "CURRENT", 0, kCurrentFile }, - { "LOCK", 0, kDBLockFile }, - { "MANIFEST-2", 2, kDescriptorFile }, - { "MANIFEST-7", 7, kDescriptorFile }, - { "LOG", 0, kInfoLogFile }, - { "LOG.old", 0, kInfoLogFile }, - { "18446744073709551615.log", 18446744073709551615ull, kLogFile }, - }; - for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { - std::string f = cases[i].fname; - ASSERT_TRUE(ParseFileName(f, &number, &type)) << f; - ASSERT_EQ(cases[i].type, type) << f; - ASSERT_EQ(cases[i].number, number) << f; - } - - // Errors - static const char* errors[] = { - "", - "foo", - "foo-dx-100.log", - ".log", - "", - "manifest", - "CURREN", - "CURRENTX", - "MANIFES", - "MANIFEST", - "MANIFEST-", - "XMANIFEST-3", - "MANIFEST-3x", - "LOC", - "LOCKx", - "LO", - "LOGx", - "18446744073709551616.log", - "184467440737095516150.log", - "100", - "100.", - "100.lop" - }; - for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) { - std::string f = errors[i]; - ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f; - } -} - -TEST(FileNameTest, Construction) { - uint64_t number; - FileType type; - std::string fname; - - fname = CurrentFileName("foo"); - ASSERT_EQ("foo/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(0, number); - ASSERT_EQ(kCurrentFile, type); - - fname = LockFileName("foo"); - ASSERT_EQ("foo/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(0, number); - ASSERT_EQ(kDBLockFile, type); - - fname = LogFileName("foo", 192); - ASSERT_EQ("foo/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(192, number); - ASSERT_EQ(kLogFile, type); - - fname = TableFileName("bar", 200); - ASSERT_EQ("bar/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(200, number); - ASSERT_EQ(kTableFile, type); - - fname = DescriptorFileName("bar", 100); - ASSERT_EQ("bar/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(100, number); - ASSERT_EQ(kDescriptorFile, type); - - fname = TempFileName("tmp", 999); - ASSERT_EQ("tmp/", std::string(fname.data(), 4)); - ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type)); - ASSERT_EQ(999, number); - ASSERT_EQ(kTempFile, type); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/leveldb_main.cc b/src/leveldb/db/leveldb_main.cc deleted file mode 100644 index 9f4b7dd70c..0000000000 --- a/src/leveldb/db/leveldb_main.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include "leveldb/dumpfile.h" -#include "leveldb/env.h" -#include "leveldb/status.h" - -namespace leveldb { -namespace { - -class StdoutPrinter : public WritableFile { - public: - virtual Status Append(const Slice& data) { - fwrite(data.data(), 1, data.size(), stdout); - return Status::OK(); - } - virtual Status Close() { return Status::OK(); } - virtual Status Flush() { return Status::OK(); } - virtual Status Sync() { return Status::OK(); } -}; - -bool HandleDumpCommand(Env* env, char** files, int num) { - StdoutPrinter printer; - bool ok = true; - for (int i = 0; i < num; i++) { - Status s = DumpFile(env, files[i], &printer); - if (!s.ok()) { - fprintf(stderr, "%s\n", s.ToString().c_str()); - ok = false; - } - } - return ok; -} - -} // namespace -} // namespace leveldb - -static void Usage() { - fprintf( - stderr, - "Usage: leveldbutil command...\n" - " dump files... -- dump contents of specified files\n" - ); -} - -int main(int argc, char** argv) { - leveldb::Env* env = leveldb::Env::Default(); - bool ok = true; - if (argc < 2) { - Usage(); - ok = false; - } else { - std::string command = argv[1]; - if (command == "dump") { - ok = leveldb::HandleDumpCommand(env, argv+2, argc-2); - } else { - Usage(); - ok = false; - } - } - return (ok ? 0 : 1); -} diff --git a/src/leveldb/db/log_format.h b/src/leveldb/db/log_format.h deleted file mode 100644 index a8c06efe18..0000000000 --- a/src/leveldb/db/log_format.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Log format information shared by reader and writer. -// See ../doc/log_format.txt for more detail. - -#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ -#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ - -namespace leveldb { -namespace log { - -enum RecordType { - // Zero is reserved for preallocated files - kZeroType = 0, - - kFullType = 1, - - // For fragments - kFirstType = 2, - kMiddleType = 3, - kLastType = 4 -}; -static const int kMaxRecordType = kLastType; - -static const int kBlockSize = 32768; - -// Header is checksum (4 bytes), length (2 bytes), type (1 byte). -static const int kHeaderSize = 4 + 2 + 1; - -} // namespace log -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/src/leveldb/db/log_reader.cc b/src/leveldb/db/log_reader.cc deleted file mode 100644 index e44b66c85b..0000000000 --- a/src/leveldb/db/log_reader.cc +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/log_reader.h" - -#include -#include "leveldb/env.h" -#include "util/coding.h" -#include "util/crc32c.h" - -namespace leveldb { -namespace log { - -Reader::Reporter::~Reporter() { -} - -Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum, - uint64_t initial_offset) - : file_(file), - reporter_(reporter), - checksum_(checksum), - backing_store_(new char[kBlockSize]), - buffer_(), - eof_(false), - last_record_offset_(0), - end_of_buffer_offset_(0), - initial_offset_(initial_offset) { -} - -Reader::~Reader() { - delete[] backing_store_; -} - -bool Reader::SkipToInitialBlock() { - size_t offset_in_block = initial_offset_ % kBlockSize; - uint64_t block_start_location = initial_offset_ - offset_in_block; - - // Don't search a block if we'd be in the trailer - if (offset_in_block > kBlockSize - 6) { - offset_in_block = 0; - block_start_location += kBlockSize; - } - - end_of_buffer_offset_ = block_start_location; - - // Skip to start of first block that can contain the initial record - if (block_start_location > 0) { - Status skip_status = file_->Skip(block_start_location); - if (!skip_status.ok()) { - ReportDrop(block_start_location, skip_status); - return false; - } - } - - return true; -} - -bool Reader::ReadRecord(Slice* record, std::string* scratch) { - if (last_record_offset_ < initial_offset_) { - if (!SkipToInitialBlock()) { - return false; - } - } - - scratch->clear(); - record->clear(); - bool in_fragmented_record = false; - // Record offset of the logical record that we're reading - // 0 is a dummy value to make compilers happy - uint64_t prospective_record_offset = 0; - - Slice fragment; - while (true) { - uint64_t physical_record_offset = end_of_buffer_offset_ - buffer_.size(); - const unsigned int record_type = ReadPhysicalRecord(&fragment); - switch (record_type) { - case kFullType: - if (in_fragmented_record) { - // Handle bug in earlier versions of log::Writer where - // it could emit an empty kFirstType record at the tail end - // of a block followed by a kFullType or kFirstType record - // at the beginning of the next block. - if (scratch->empty()) { - in_fragmented_record = false; - } else { - ReportCorruption(scratch->size(), "partial record without end(1)"); - } - } - prospective_record_offset = physical_record_offset; - scratch->clear(); - *record = fragment; - last_record_offset_ = prospective_record_offset; - return true; - - case kFirstType: - if (in_fragmented_record) { - // Handle bug in earlier versions of log::Writer where - // it could emit an empty kFirstType record at the tail end - // of a block followed by a kFullType or kFirstType record - // at the beginning of the next block. - if (scratch->empty()) { - in_fragmented_record = false; - } else { - ReportCorruption(scratch->size(), "partial record without end(2)"); - } - } - prospective_record_offset = physical_record_offset; - scratch->assign(fragment.data(), fragment.size()); - in_fragmented_record = true; - break; - - case kMiddleType: - if (!in_fragmented_record) { - ReportCorruption(fragment.size(), - "missing start of fragmented record(1)"); - } else { - scratch->append(fragment.data(), fragment.size()); - } - break; - - case kLastType: - if (!in_fragmented_record) { - ReportCorruption(fragment.size(), - "missing start of fragmented record(2)"); - } else { - scratch->append(fragment.data(), fragment.size()); - *record = Slice(*scratch); - last_record_offset_ = prospective_record_offset; - return true; - } - break; - - case kEof: - if (in_fragmented_record) { - // This can be caused by the writer dying immediately after - // writing a physical record but before completing the next; don't - // treat it as a corruption, just ignore the entire logical record. - scratch->clear(); - } - return false; - - case kBadRecord: - if (in_fragmented_record) { - ReportCorruption(scratch->size(), "error in middle of record"); - in_fragmented_record = false; - scratch->clear(); - } - break; - - default: { - char buf[40]; - snprintf(buf, sizeof(buf), "unknown record type %u", record_type); - ReportCorruption( - (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), - buf); - in_fragmented_record = false; - scratch->clear(); - break; - } - } - } - return false; -} - -uint64_t Reader::LastRecordOffset() { - return last_record_offset_; -} - -void Reader::ReportCorruption(uint64_t bytes, const char* reason) { - ReportDrop(bytes, Status::Corruption(reason)); -} - -void Reader::ReportDrop(uint64_t bytes, const Status& reason) { - if (reporter_ != NULL && - end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { - reporter_->Corruption(static_cast(bytes), reason); - } -} - -unsigned int Reader::ReadPhysicalRecord(Slice* result) { - while (true) { - if (buffer_.size() < kHeaderSize) { - if (!eof_) { - // Last read was a full read, so this is a trailer to skip - buffer_.clear(); - Status status = file_->Read(kBlockSize, &buffer_, backing_store_); - end_of_buffer_offset_ += buffer_.size(); - if (!status.ok()) { - buffer_.clear(); - ReportDrop(kBlockSize, status); - eof_ = true; - return kEof; - } else if (buffer_.size() < kBlockSize) { - eof_ = true; - } - continue; - } else { - // Note that if buffer_ is non-empty, we have a truncated header at the - // end of the file, which can be caused by the writer crashing in the - // middle of writing the header. Instead of considering this an error, - // just report EOF. - buffer_.clear(); - return kEof; - } - } - - // Parse the header - const char* header = buffer_.data(); - const uint32_t a = static_cast(header[4]) & 0xff; - const uint32_t b = static_cast(header[5]) & 0xff; - const unsigned int type = header[6]; - const uint32_t length = a | (b << 8); - if (kHeaderSize + length > buffer_.size()) { - size_t drop_size = buffer_.size(); - buffer_.clear(); - if (!eof_) { - ReportCorruption(drop_size, "bad record length"); - return kBadRecord; - } - // If the end of the file has been reached without reading |length| bytes - // of payload, assume the writer died in the middle of writing the record. - // Don't report a corruption. - return kEof; - } - - if (type == kZeroType && length == 0) { - // Skip zero length record without reporting any drops since - // such records are produced by the mmap based writing code in - // env_posix.cc that preallocates file regions. - buffer_.clear(); - return kBadRecord; - } - - // Check crc - if (checksum_) { - uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); - uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); - if (actual_crc != expected_crc) { - // Drop the rest of the buffer since "length" itself may have - // been corrupted and if we trust it, we could find some - // fragment of a real log record that just happens to look - // like a valid log record. - size_t drop_size = buffer_.size(); - buffer_.clear(); - ReportCorruption(drop_size, "checksum mismatch"); - return kBadRecord; - } - } - - buffer_.remove_prefix(kHeaderSize + length); - - // Skip physical record that started before initial_offset_ - if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < - initial_offset_) { - result->clear(); - return kBadRecord; - } - - *result = Slice(header + kHeaderSize, length); - return type; - } -} - -} // namespace log -} // namespace leveldb diff --git a/src/leveldb/db/log_reader.h b/src/leveldb/db/log_reader.h deleted file mode 100644 index 6aff791716..0000000000 --- a/src/leveldb/db/log_reader.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ -#define STORAGE_LEVELDB_DB_LOG_READER_H_ - -#include - -#include "db/log_format.h" -#include "leveldb/slice.h" -#include "leveldb/status.h" - -namespace leveldb { - -class SequentialFile; - -namespace log { - -class Reader { - public: - // Interface for reporting errors. - class Reporter { - public: - virtual ~Reporter(); - - // Some corruption was detected. "size" is the approximate number - // of bytes dropped due to the corruption. - virtual void Corruption(size_t bytes, const Status& status) = 0; - }; - - // Create a reader that will return log records from "*file". - // "*file" must remain live while this Reader is in use. - // - // If "reporter" is non-NULL, it is notified whenever some data is - // dropped due to a detected corruption. "*reporter" must remain - // live while this Reader is in use. - // - // If "checksum" is true, verify checksums if available. - // - // The Reader will start reading at the first record located at physical - // position >= initial_offset within the file. - Reader(SequentialFile* file, Reporter* reporter, bool checksum, - uint64_t initial_offset); - - ~Reader(); - - // Read the next record into *record. Returns true if read - // successfully, false if we hit end of the input. May use - // "*scratch" as temporary storage. The contents filled in *record - // will only be valid until the next mutating operation on this - // reader or the next mutation to *scratch. - bool ReadRecord(Slice* record, std::string* scratch); - - // Returns the physical offset of the last record returned by ReadRecord. - // - // Undefined before the first call to ReadRecord. - uint64_t LastRecordOffset(); - - private: - SequentialFile* const file_; - Reporter* const reporter_; - bool const checksum_; - char* const backing_store_; - Slice buffer_; - bool eof_; // Last Read() indicated EOF by returning < kBlockSize - - // Offset of the last record returned by ReadRecord. - uint64_t last_record_offset_; - // Offset of the first location past the end of buffer_. - uint64_t end_of_buffer_offset_; - - // Offset at which to start looking for the first record to return - uint64_t const initial_offset_; - - // Extend record types with the following special values - enum { - kEof = kMaxRecordType + 1, - // Returned whenever we find an invalid physical record. - // Currently there are three situations in which this happens: - // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) - // * The record is a 0-length record (No drop is reported) - // * The record is below constructor's initial_offset (No drop is reported) - kBadRecord = kMaxRecordType + 2 - }; - - // Skips all blocks that are completely before "initial_offset_". - // - // Returns true on success. Handles reporting. - bool SkipToInitialBlock(); - - // Return type, or one of the preceding special values - unsigned int ReadPhysicalRecord(Slice* result); - - // Reports dropped bytes to the reporter. - // buffer_ must be updated to remove the dropped bytes prior to invocation. - void ReportCorruption(uint64_t bytes, const char* reason); - void ReportDrop(uint64_t bytes, const Status& reason); - - // No copying allowed - Reader(const Reader&); - void operator=(const Reader&); -}; - -} // namespace log -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/src/leveldb/db/log_test.cc b/src/leveldb/db/log_test.cc deleted file mode 100644 index dcf0562652..0000000000 --- a/src/leveldb/db/log_test.cc +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/log_reader.h" -#include "db/log_writer.h" -#include "leveldb/env.h" -#include "util/coding.h" -#include "util/crc32c.h" -#include "util/random.h" -#include "util/testharness.h" - -namespace leveldb { -namespace log { - -// Construct a string of the specified length made out of the supplied -// partial string. -static std::string BigString(const std::string& partial_string, size_t n) { - std::string result; - while (result.size() < n) { - result.append(partial_string); - } - result.resize(n); - return result; -} - -// Construct a string from a number -static std::string NumberString(int n) { - char buf[50]; - snprintf(buf, sizeof(buf), "%d.", n); - return std::string(buf); -} - -// Return a skewed potentially long string -static std::string RandomSkewedString(int i, Random* rnd) { - return BigString(NumberString(i), rnd->Skewed(17)); -} - -class LogTest { - private: - class StringDest : public WritableFile { - public: - std::string contents_; - - virtual Status Close() { return Status::OK(); } - virtual Status Flush() { return Status::OK(); } - virtual Status Sync() { return Status::OK(); } - virtual Status Append(const Slice& slice) { - contents_.append(slice.data(), slice.size()); - return Status::OK(); - } - }; - - class StringSource : public SequentialFile { - public: - Slice contents_; - bool force_error_; - bool returned_partial_; - StringSource() : force_error_(false), returned_partial_(false) { } - - virtual Status Read(size_t n, Slice* result, char* scratch) { - ASSERT_TRUE(!returned_partial_) << "must not Read() after eof/error"; - - if (force_error_) { - force_error_ = false; - returned_partial_ = true; - return Status::Corruption("read error"); - } - - if (contents_.size() < n) { - n = contents_.size(); - returned_partial_ = true; - } - *result = Slice(contents_.data(), n); - contents_.remove_prefix(n); - return Status::OK(); - } - - virtual Status Skip(uint64_t n) { - if (n > contents_.size()) { - contents_.clear(); - return Status::NotFound("in-memory file skipepd past end"); - } - - contents_.remove_prefix(n); - - return Status::OK(); - } - }; - - class ReportCollector : public Reader::Reporter { - public: - size_t dropped_bytes_; - std::string message_; - - ReportCollector() : dropped_bytes_(0) { } - virtual void Corruption(size_t bytes, const Status& status) { - dropped_bytes_ += bytes; - message_.append(status.ToString()); - } - }; - - StringDest dest_; - StringSource source_; - ReportCollector report_; - bool reading_; - Writer writer_; - Reader reader_; - - // Record metadata for testing initial offset functionality - static size_t initial_offset_record_sizes_[]; - static uint64_t initial_offset_last_record_offsets_[]; - - public: - LogTest() : reading_(false), - writer_(&dest_), - reader_(&source_, &report_, true/*checksum*/, - 0/*initial_offset*/) { - } - - void Write(const std::string& msg) { - ASSERT_TRUE(!reading_) << "Write() after starting to read"; - writer_.AddRecord(Slice(msg)); - } - - size_t WrittenBytes() const { - return dest_.contents_.size(); - } - - std::string Read() { - if (!reading_) { - reading_ = true; - source_.contents_ = Slice(dest_.contents_); - } - std::string scratch; - Slice record; - if (reader_.ReadRecord(&record, &scratch)) { - return record.ToString(); - } else { - return "EOF"; - } - } - - void IncrementByte(int offset, int delta) { - dest_.contents_[offset] += delta; - } - - void SetByte(int offset, char new_byte) { - dest_.contents_[offset] = new_byte; - } - - void ShrinkSize(int bytes) { - dest_.contents_.resize(dest_.contents_.size() - bytes); - } - - void FixChecksum(int header_offset, int len) { - // Compute crc of type/len/data - uint32_t crc = crc32c::Value(&dest_.contents_[header_offset+6], 1 + len); - crc = crc32c::Mask(crc); - EncodeFixed32(&dest_.contents_[header_offset], crc); - } - - void ForceError() { - source_.force_error_ = true; - } - - size_t DroppedBytes() const { - return report_.dropped_bytes_; - } - - std::string ReportMessage() const { - return report_.message_; - } - - // Returns OK iff recorded error message contains "msg" - std::string MatchError(const std::string& msg) const { - if (report_.message_.find(msg) == std::string::npos) { - return report_.message_; - } else { - return "OK"; - } - } - - void WriteInitialOffsetLog() { - for (int i = 0; i < 4; i++) { - std::string record(initial_offset_record_sizes_[i], - static_cast('a' + i)); - Write(record); - } - } - - void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end) { - WriteInitialOffsetLog(); - reading_ = true; - source_.contents_ = Slice(dest_.contents_); - Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/, - WrittenBytes() + offset_past_end); - Slice record; - std::string scratch; - ASSERT_TRUE(!offset_reader->ReadRecord(&record, &scratch)); - delete offset_reader; - } - - void CheckInitialOffsetRecord(uint64_t initial_offset, - int expected_record_offset) { - WriteInitialOffsetLog(); - reading_ = true; - source_.contents_ = Slice(dest_.contents_); - Reader* offset_reader = new Reader(&source_, &report_, true/*checksum*/, - initial_offset); - Slice record; - std::string scratch; - ASSERT_TRUE(offset_reader->ReadRecord(&record, &scratch)); - ASSERT_EQ(initial_offset_record_sizes_[expected_record_offset], - record.size()); - ASSERT_EQ(initial_offset_last_record_offsets_[expected_record_offset], - offset_reader->LastRecordOffset()); - ASSERT_EQ((char)('a' + expected_record_offset), record.data()[0]); - delete offset_reader; - } - -}; - -size_t LogTest::initial_offset_record_sizes_[] = - {10000, // Two sizable records in first block - 10000, - 2 * log::kBlockSize - 1000, // Span three blocks - 1}; - -uint64_t LogTest::initial_offset_last_record_offsets_[] = - {0, - kHeaderSize + 10000, - 2 * (kHeaderSize + 10000), - 2 * (kHeaderSize + 10000) + - (2 * log::kBlockSize - 1000) + 3 * kHeaderSize}; - - -TEST(LogTest, Empty) { - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, ReadWrite) { - Write("foo"); - Write("bar"); - Write(""); - Write("xxxx"); - ASSERT_EQ("foo", Read()); - ASSERT_EQ("bar", Read()); - ASSERT_EQ("", Read()); - ASSERT_EQ("xxxx", Read()); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ("EOF", Read()); // Make sure reads at eof work -} - -TEST(LogTest, ManyBlocks) { - for (int i = 0; i < 100000; i++) { - Write(NumberString(i)); - } - for (int i = 0; i < 100000; i++) { - ASSERT_EQ(NumberString(i), Read()); - } - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, Fragmentation) { - Write("small"); - Write(BigString("medium", 50000)); - Write(BigString("large", 100000)); - ASSERT_EQ("small", Read()); - ASSERT_EQ(BigString("medium", 50000), Read()); - ASSERT_EQ(BigString("large", 100000), Read()); - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, MarginalTrailer) { - // Make a trailer that is exactly the same length as an empty record. - const int n = kBlockSize - 2*kHeaderSize; - Write(BigString("foo", n)); - ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes()); - Write(""); - Write("bar"); - ASSERT_EQ(BigString("foo", n), Read()); - ASSERT_EQ("", Read()); - ASSERT_EQ("bar", Read()); - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, MarginalTrailer2) { - // Make a trailer that is exactly the same length as an empty record. - const int n = kBlockSize - 2*kHeaderSize; - Write(BigString("foo", n)); - ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes()); - Write("bar"); - ASSERT_EQ(BigString("foo", n), Read()); - ASSERT_EQ("bar", Read()); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(0, DroppedBytes()); - ASSERT_EQ("", ReportMessage()); -} - -TEST(LogTest, ShortTrailer) { - const int n = kBlockSize - 2*kHeaderSize + 4; - Write(BigString("foo", n)); - ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes()); - Write(""); - Write("bar"); - ASSERT_EQ(BigString("foo", n), Read()); - ASSERT_EQ("", Read()); - ASSERT_EQ("bar", Read()); - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, AlignedEof) { - const int n = kBlockSize - 2*kHeaderSize + 4; - Write(BigString("foo", n)); - ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes()); - ASSERT_EQ(BigString("foo", n), Read()); - ASSERT_EQ("EOF", Read()); -} - -TEST(LogTest, RandomRead) { - const int N = 500; - Random write_rnd(301); - for (int i = 0; i < N; i++) { - Write(RandomSkewedString(i, &write_rnd)); - } - Random read_rnd(301); - for (int i = 0; i < N; i++) { - ASSERT_EQ(RandomSkewedString(i, &read_rnd), Read()); - } - ASSERT_EQ("EOF", Read()); -} - -// Tests of all the error paths in log_reader.cc follow: - -TEST(LogTest, ReadError) { - Write("foo"); - ForceError(); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(kBlockSize, DroppedBytes()); - ASSERT_EQ("OK", MatchError("read error")); -} - -TEST(LogTest, BadRecordType) { - Write("foo"); - // Type is stored in header[6] - IncrementByte(6, 100); - FixChecksum(0, 3); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3, DroppedBytes()); - ASSERT_EQ("OK", MatchError("unknown record type")); -} - -TEST(LogTest, TruncatedTrailingRecordIsIgnored) { - Write("foo"); - ShrinkSize(4); // Drop all payload as well as a header byte - ASSERT_EQ("EOF", Read()); - // Truncated last record is ignored, not treated as an error. - ASSERT_EQ(0, DroppedBytes()); - ASSERT_EQ("", ReportMessage()); -} - -TEST(LogTest, BadLength) { - const int kPayloadSize = kBlockSize - kHeaderSize; - Write(BigString("bar", kPayloadSize)); - Write("foo"); - // Least significant size byte is stored in header[4]. - IncrementByte(4, 1); - ASSERT_EQ("foo", Read()); - ASSERT_EQ(kBlockSize, DroppedBytes()); - ASSERT_EQ("OK", MatchError("bad record length")); -} - -TEST(LogTest, BadLengthAtEndIsIgnored) { - Write("foo"); - ShrinkSize(1); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(0, DroppedBytes()); - ASSERT_EQ("", ReportMessage()); -} - -TEST(LogTest, ChecksumMismatch) { - Write("foo"); - IncrementByte(0, 10); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(10, DroppedBytes()); - ASSERT_EQ("OK", MatchError("checksum mismatch")); -} - -TEST(LogTest, UnexpectedMiddleType) { - Write("foo"); - SetByte(6, kMiddleType); - FixChecksum(0, 3); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3, DroppedBytes()); - ASSERT_EQ("OK", MatchError("missing start")); -} - -TEST(LogTest, UnexpectedLastType) { - Write("foo"); - SetByte(6, kLastType); - FixChecksum(0, 3); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3, DroppedBytes()); - ASSERT_EQ("OK", MatchError("missing start")); -} - -TEST(LogTest, UnexpectedFullType) { - Write("foo"); - Write("bar"); - SetByte(6, kFirstType); - FixChecksum(0, 3); - ASSERT_EQ("bar", Read()); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3, DroppedBytes()); - ASSERT_EQ("OK", MatchError("partial record without end")); -} - -TEST(LogTest, UnexpectedFirstType) { - Write("foo"); - Write(BigString("bar", 100000)); - SetByte(6, kFirstType); - FixChecksum(0, 3); - ASSERT_EQ(BigString("bar", 100000), Read()); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ(3, DroppedBytes()); - ASSERT_EQ("OK", MatchError("partial record without end")); -} - -TEST(LogTest, MissingLastIsIgnored) { - Write(BigString("bar", kBlockSize)); - // Remove the LAST block, including header. - ShrinkSize(14); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ("", ReportMessage()); - ASSERT_EQ(0, DroppedBytes()); -} - -TEST(LogTest, PartialLastIsIgnored) { - Write(BigString("bar", kBlockSize)); - // Cause a bad record length in the LAST block. - ShrinkSize(1); - ASSERT_EQ("EOF", Read()); - ASSERT_EQ("", ReportMessage()); - ASSERT_EQ(0, DroppedBytes()); -} - -TEST(LogTest, ErrorJoinsRecords) { - // Consider two fragmented records: - // first(R1) last(R1) first(R2) last(R2) - // where the middle two fragments disappear. We do not want - // first(R1),last(R2) to get joined and returned as a valid record. - - // Write records that span two blocks - Write(BigString("foo", kBlockSize)); - Write(BigString("bar", kBlockSize)); - Write("correct"); - - // Wipe the middle block - for (int offset = kBlockSize; offset < 2*kBlockSize; offset++) { - SetByte(offset, 'x'); - } - - ASSERT_EQ("correct", Read()); - ASSERT_EQ("EOF", Read()); - const size_t dropped = DroppedBytes(); - ASSERT_LE(dropped, 2*kBlockSize + 100); - ASSERT_GE(dropped, 2*kBlockSize); -} - -TEST(LogTest, ReadStart) { - CheckInitialOffsetRecord(0, 0); -} - -TEST(LogTest, ReadSecondOneOff) { - CheckInitialOffsetRecord(1, 1); -} - -TEST(LogTest, ReadSecondTenThousand) { - CheckInitialOffsetRecord(10000, 1); -} - -TEST(LogTest, ReadSecondStart) { - CheckInitialOffsetRecord(10007, 1); -} - -TEST(LogTest, ReadThirdOneOff) { - CheckInitialOffsetRecord(10008, 2); -} - -TEST(LogTest, ReadThirdStart) { - CheckInitialOffsetRecord(20014, 2); -} - -TEST(LogTest, ReadFourthOneOff) { - CheckInitialOffsetRecord(20015, 3); -} - -TEST(LogTest, ReadFourthFirstBlockTrailer) { - CheckInitialOffsetRecord(log::kBlockSize - 4, 3); -} - -TEST(LogTest, ReadFourthMiddleBlock) { - CheckInitialOffsetRecord(log::kBlockSize + 1, 3); -} - -TEST(LogTest, ReadFourthLastBlock) { - CheckInitialOffsetRecord(2 * log::kBlockSize + 1, 3); -} - -TEST(LogTest, ReadFourthStart) { - CheckInitialOffsetRecord( - 2 * (kHeaderSize + 1000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize, - 3); -} - -TEST(LogTest, ReadEnd) { - CheckOffsetPastEndReturnsNoRecords(0); -} - -TEST(LogTest, ReadPastEnd) { - CheckOffsetPastEndReturnsNoRecords(5); -} - -} // namespace log -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/log_writer.cc b/src/leveldb/db/log_writer.cc deleted file mode 100644 index 2da99ac088..0000000000 --- a/src/leveldb/db/log_writer.cc +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/log_writer.h" - -#include -#include "leveldb/env.h" -#include "util/coding.h" -#include "util/crc32c.h" - -namespace leveldb { -namespace log { - -Writer::Writer(WritableFile* dest) - : dest_(dest), - block_offset_(0) { - for (int i = 0; i <= kMaxRecordType; i++) { - char t = static_cast(i); - type_crc_[i] = crc32c::Value(&t, 1); - } -} - -Writer::~Writer() { -} - -Status Writer::AddRecord(const Slice& slice) { - const char* ptr = slice.data(); - size_t left = slice.size(); - - // Fragment the record if necessary and emit it. Note that if slice - // is empty, we still want to iterate once to emit a single - // zero-length record - Status s; - bool begin = true; - do { - const int leftover = kBlockSize - block_offset_; - assert(leftover >= 0); - if (leftover < kHeaderSize) { - // Switch to a new block - if (leftover > 0) { - // Fill the trailer (literal below relies on kHeaderSize being 7) - assert(kHeaderSize == 7); - dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); - } - block_offset_ = 0; - } - - // Invariant: we never leave < kHeaderSize bytes in a block. - assert(kBlockSize - block_offset_ - kHeaderSize >= 0); - - const size_t avail = kBlockSize - block_offset_ - kHeaderSize; - const size_t fragment_length = (left < avail) ? left : avail; - - RecordType type; - const bool end = (left == fragment_length); - if (begin && end) { - type = kFullType; - } else if (begin) { - type = kFirstType; - } else if (end) { - type = kLastType; - } else { - type = kMiddleType; - } - - s = EmitPhysicalRecord(type, ptr, fragment_length); - ptr += fragment_length; - left -= fragment_length; - begin = false; - } while (s.ok() && left > 0); - return s; -} - -Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) { - assert(n <= 0xffff); // Must fit in two bytes - assert(block_offset_ + kHeaderSize + n <= kBlockSize); - - // Format the header - char buf[kHeaderSize]; - buf[4] = static_cast(n & 0xff); - buf[5] = static_cast(n >> 8); - buf[6] = static_cast(t); - - // Compute the crc of the record type and the payload. - uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n); - crc = crc32c::Mask(crc); // Adjust for storage - EncodeFixed32(buf, crc); - - // Write the header and the payload - Status s = dest_->Append(Slice(buf, kHeaderSize)); - if (s.ok()) { - s = dest_->Append(Slice(ptr, n)); - if (s.ok()) { - s = dest_->Flush(); - } - } - block_offset_ += kHeaderSize + n; - return s; -} - -} // namespace log -} // namespace leveldb diff --git a/src/leveldb/db/log_writer.h b/src/leveldb/db/log_writer.h deleted file mode 100644 index a3a954d967..0000000000 --- a/src/leveldb/db/log_writer.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ -#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ - -#include -#include "db/log_format.h" -#include "leveldb/slice.h" -#include "leveldb/status.h" - -namespace leveldb { - -class WritableFile; - -namespace log { - -class Writer { - public: - // Create a writer that will append data to "*dest". - // "*dest" must be initially empty. - // "*dest" must remain live while this Writer is in use. - explicit Writer(WritableFile* dest); - ~Writer(); - - Status AddRecord(const Slice& slice); - - private: - WritableFile* dest_; - int block_offset_; // Current offset in block - - // crc32c values for all supported record types. These are - // pre-computed to reduce the overhead of computing the crc of the - // record type stored in the header. - uint32_t type_crc_[kMaxRecordType + 1]; - - Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); - - // No copying allowed - Writer(const Writer&); - void operator=(const Writer&); -}; - -} // namespace log -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/src/leveldb/db/memtable.cc b/src/leveldb/db/memtable.cc deleted file mode 100644 index bfec0a7e7a..0000000000 --- a/src/leveldb/db/memtable.cc +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/memtable.h" -#include "db/dbformat.h" -#include "leveldb/comparator.h" -#include "leveldb/env.h" -#include "leveldb/iterator.h" -#include "util/coding.h" - -namespace leveldb { - -static Slice GetLengthPrefixedSlice(const char* data) { - uint32_t len; - const char* p = data; - p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted - return Slice(p, len); -} - -MemTable::MemTable(const InternalKeyComparator& cmp) - : comparator_(cmp), - refs_(0), - table_(comparator_, &arena_) { -} - -MemTable::~MemTable() { - assert(refs_ == 0); -} - -size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } - -int MemTable::KeyComparator::operator()(const char* aptr, const char* bptr) - const { - // Internal keys are encoded as length-prefixed strings. - Slice a = GetLengthPrefixedSlice(aptr); - Slice b = GetLengthPrefixedSlice(bptr); - return comparator.Compare(a, b); -} - -// Encode a suitable internal key target for "target" and return it. -// Uses *scratch as scratch space, and the returned pointer will point -// into this scratch space. -static const char* EncodeKey(std::string* scratch, const Slice& target) { - scratch->clear(); - PutVarint32(scratch, target.size()); - scratch->append(target.data(), target.size()); - return scratch->data(); -} - -class MemTableIterator: public Iterator { - public: - explicit MemTableIterator(MemTable::Table* table) : iter_(table) { } - - virtual bool Valid() const { return iter_.Valid(); } - virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } - virtual void SeekToFirst() { iter_.SeekToFirst(); } - virtual void SeekToLast() { iter_.SeekToLast(); } - virtual void Next() { iter_.Next(); } - virtual void Prev() { iter_.Prev(); } - virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } - virtual Slice value() const { - Slice key_slice = GetLengthPrefixedSlice(iter_.key()); - return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); - } - - virtual Status status() const { return Status::OK(); } - - private: - MemTable::Table::Iterator iter_; - std::string tmp_; // For passing to EncodeKey - - // No copying allowed - MemTableIterator(const MemTableIterator&); - void operator=(const MemTableIterator&); -}; - -Iterator* MemTable::NewIterator() { - return new MemTableIterator(&table_); -} - -void MemTable::Add(SequenceNumber s, ValueType type, - const Slice& key, - const Slice& value) { - // Format of an entry is concatenation of: - // key_size : varint32 of internal_key.size() - // key bytes : char[internal_key.size()] - // value_size : varint32 of value.size() - // value bytes : char[value.size()] - size_t key_size = key.size(); - size_t val_size = value.size(); - size_t internal_key_size = key_size + 8; - const size_t encoded_len = - VarintLength(internal_key_size) + internal_key_size + - VarintLength(val_size) + val_size; - char* buf = arena_.Allocate(encoded_len); - char* p = EncodeVarint32(buf, internal_key_size); - memcpy(p, key.data(), key_size); - p += key_size; - EncodeFixed64(p, (s << 8) | type); - p += 8; - p = EncodeVarint32(p, val_size); - memcpy(p, value.data(), val_size); - assert((p + val_size) - buf == encoded_len); - table_.Insert(buf); -} - -bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { - Slice memkey = key.memtable_key(); - Table::Iterator iter(&table_); - iter.Seek(memkey.data()); - if (iter.Valid()) { - // entry format is: - // klength varint32 - // userkey char[klength] - // tag uint64 - // vlength varint32 - // value char[vlength] - // Check that it belongs to same user key. We do not check the - // sequence number since the Seek() call above should have skipped - // all entries with overly large sequence numbers. - const char* entry = iter.key(); - uint32_t key_length; - const char* key_ptr = GetVarint32Ptr(entry, entry+5, &key_length); - if (comparator_.comparator.user_comparator()->Compare( - Slice(key_ptr, key_length - 8), - key.user_key()) == 0) { - // Correct user key - const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); - switch (static_cast(tag & 0xff)) { - case kTypeValue: { - Slice v = GetLengthPrefixedSlice(key_ptr + key_length); - value->assign(v.data(), v.size()); - return true; - } - case kTypeDeletion: - *s = Status::NotFound(Slice()); - return true; - } - } - } - return false; -} - -} // namespace leveldb diff --git a/src/leveldb/db/memtable.h b/src/leveldb/db/memtable.h deleted file mode 100644 index 92e90bb099..0000000000 --- a/src/leveldb/db/memtable.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ -#define STORAGE_LEVELDB_DB_MEMTABLE_H_ - -#include -#include "leveldb/db.h" -#include "db/dbformat.h" -#include "db/skiplist.h" -#include "util/arena.h" - -namespace leveldb { - -class InternalKeyComparator; -class Mutex; -class MemTableIterator; - -class MemTable { - public: - // MemTables are reference counted. The initial reference count - // is zero and the caller must call Ref() at least once. - explicit MemTable(const InternalKeyComparator& comparator); - - // Increase reference count. - void Ref() { ++refs_; } - - // Drop reference count. Delete if no more references exist. - void Unref() { - --refs_; - assert(refs_ >= 0); - if (refs_ <= 0) { - delete this; - } - } - - // Returns an estimate of the number of bytes of data in use by this - // data structure. - // - // REQUIRES: external synchronization to prevent simultaneous - // operations on the same MemTable. - size_t ApproximateMemoryUsage(); - - // Return an iterator that yields the contents of the memtable. - // - // The caller must ensure that the underlying MemTable remains live - // while the returned iterator is live. The keys returned by this - // iterator are internal keys encoded by AppendInternalKey in the - // db/format.{h,cc} module. - Iterator* NewIterator(); - - // Add an entry into memtable that maps key to value at the - // specified sequence number and with the specified type. - // Typically value will be empty if type==kTypeDeletion. - void Add(SequenceNumber seq, ValueType type, - const Slice& key, - const Slice& value); - - // If memtable contains a value for key, store it in *value and return true. - // If memtable contains a deletion for key, store a NotFound() error - // in *status and return true. - // Else, return false. - bool Get(const LookupKey& key, std::string* value, Status* s); - - private: - ~MemTable(); // Private since only Unref() should be used to delete it - - struct KeyComparator { - const InternalKeyComparator comparator; - explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { } - int operator()(const char* a, const char* b) const; - }; - friend class MemTableIterator; - friend class MemTableBackwardIterator; - - typedef SkipList Table; - - KeyComparator comparator_; - int refs_; - Arena arena_; - Table table_; - - // No copying allowed - MemTable(const MemTable&); - void operator=(const MemTable&); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/src/leveldb/db/repair.cc b/src/leveldb/db/repair.cc deleted file mode 100644 index 4cd4bb047f..0000000000 --- a/src/leveldb/db/repair.cc +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// We recover the contents of the descriptor from the other files we find. -// (1) Any log files are first converted to tables -// (2) We scan every table to compute -// (a) smallest/largest for the table -// (b) largest sequence number in the table -// (3) We generate descriptor contents: -// - log number is set to zero -// - next-file-number is set to 1 + largest file number we found -// - last-sequence-number is set to largest sequence# found across -// all tables (see 2c) -// - compaction pointers are cleared -// - every table file is added at level 0 -// -// Possible optimization 1: -// (a) Compute total size and use to pick appropriate max-level M -// (b) Sort tables by largest sequence# in the table -// (c) For each table: if it overlaps earlier table, place in level-0, -// else place in level-M. -// Possible optimization 2: -// Store per-table metadata (smallest, largest, largest-seq#, ...) -// in the table's meta section to speed up ScanTable. - -#include "db/builder.h" -#include "db/db_impl.h" -#include "db/dbformat.h" -#include "db/filename.h" -#include "db/log_reader.h" -#include "db/log_writer.h" -#include "db/memtable.h" -#include "db/table_cache.h" -#include "db/version_edit.h" -#include "db/write_batch_internal.h" -#include "leveldb/comparator.h" -#include "leveldb/db.h" -#include "leveldb/env.h" - -namespace leveldb { - -namespace { - -class Repairer { - public: - Repairer(const std::string& dbname, const Options& options) - : dbname_(dbname), - env_(options.env), - icmp_(options.comparator), - ipolicy_(options.filter_policy), - options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), - owns_info_log_(options_.info_log != options.info_log), - owns_cache_(options_.block_cache != options.block_cache), - next_file_number_(1) { - // TableCache can be small since we expect each table to be opened once. - table_cache_ = new TableCache(dbname_, &options_, 10); - } - - ~Repairer() { - delete table_cache_; - if (owns_info_log_) { - delete options_.info_log; - } - if (owns_cache_) { - delete options_.block_cache; - } - } - - Status Run() { - Status status = FindFiles(); - if (status.ok()) { - ConvertLogFilesToTables(); - ExtractMetaData(); - status = WriteDescriptor(); - } - if (status.ok()) { - unsigned long long bytes = 0; - for (size_t i = 0; i < tables_.size(); i++) { - bytes += tables_[i].meta.file_size; - } - Log(options_.info_log, - "**** Repaired leveldb %s; " - "recovered %d files; %llu bytes. " - "Some data may have been lost. " - "****", - dbname_.c_str(), - static_cast(tables_.size()), - bytes); - } - return status; - } - - private: - struct TableInfo { - FileMetaData meta; - SequenceNumber max_sequence; - }; - - std::string const dbname_; - Env* const env_; - InternalKeyComparator const icmp_; - InternalFilterPolicy const ipolicy_; - Options const options_; - bool owns_info_log_; - bool owns_cache_; - TableCache* table_cache_; - VersionEdit edit_; - - std::vector manifests_; - std::vector table_numbers_; - std::vector logs_; - std::vector tables_; - uint64_t next_file_number_; - - Status FindFiles() { - std::vector filenames; - Status status = env_->GetChildren(dbname_, &filenames); - if (!status.ok()) { - return status; - } - if (filenames.empty()) { - return Status::IOError(dbname_, "repair found no files"); - } - - uint64_t number; - FileType type; - for (size_t i = 0; i < filenames.size(); i++) { - if (ParseFileName(filenames[i], &number, &type)) { - if (type == kDescriptorFile) { - manifests_.push_back(filenames[i]); - } else { - if (number + 1 > next_file_number_) { - next_file_number_ = number + 1; - } - if (type == kLogFile) { - logs_.push_back(number); - } else if (type == kTableFile) { - table_numbers_.push_back(number); - } else { - // Ignore other files - } - } - } - } - return status; - } - - void ConvertLogFilesToTables() { - for (size_t i = 0; i < logs_.size(); i++) { - std::string logname = LogFileName(dbname_, logs_[i]); - Status status = ConvertLogToTable(logs_[i]); - if (!status.ok()) { - Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", - (unsigned long long) logs_[i], - status.ToString().c_str()); - } - ArchiveFile(logname); - } - } - - Status ConvertLogToTable(uint64_t log) { - struct LogReporter : public log::Reader::Reporter { - Env* env; - Logger* info_log; - uint64_t lognum; - virtual void Corruption(size_t bytes, const Status& s) { - // We print error messages for corruption, but continue repairing. - Log(info_log, "Log #%llu: dropping %d bytes; %s", - (unsigned long long) lognum, - static_cast(bytes), - s.ToString().c_str()); - } - }; - - // Open the log file - std::string logname = LogFileName(dbname_, log); - SequentialFile* lfile; - Status status = env_->NewSequentialFile(logname, &lfile); - if (!status.ok()) { - return status; - } - - // Create the log reader. - LogReporter reporter; - reporter.env = env_; - reporter.info_log = options_.info_log; - reporter.lognum = log; - // We intentionally make log::Reader do checksumming so that - // corruptions cause entire commits to be skipped instead of - // propagating bad information (like overly large sequence - // numbers). - log::Reader reader(lfile, &reporter, false/*do not checksum*/, - 0/*initial_offset*/); - - // Read all the records and add to a memtable - std::string scratch; - Slice record; - WriteBatch batch; - MemTable* mem = new MemTable(icmp_); - mem->Ref(); - int counter = 0; - while (reader.ReadRecord(&record, &scratch)) { - if (record.size() < 12) { - reporter.Corruption( - record.size(), Status::Corruption("log record too small")); - continue; - } - WriteBatchInternal::SetContents(&batch, record); - status = WriteBatchInternal::InsertInto(&batch, mem); - if (status.ok()) { - counter += WriteBatchInternal::Count(&batch); - } else { - Log(options_.info_log, "Log #%llu: ignoring %s", - (unsigned long long) log, - status.ToString().c_str()); - status = Status::OK(); // Keep going with rest of file - } - } - delete lfile; - - // Do not record a version edit for this conversion to a Table - // since ExtractMetaData() will also generate edits. - FileMetaData meta; - meta.number = next_file_number_++; - Iterator* iter = mem->NewIterator(); - status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); - delete iter; - mem->Unref(); - mem = NULL; - if (status.ok()) { - if (meta.file_size > 0) { - table_numbers_.push_back(meta.number); - } - } - Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", - (unsigned long long) log, - counter, - (unsigned long long) meta.number, - status.ToString().c_str()); - return status; - } - - void ExtractMetaData() { - for (size_t i = 0; i < table_numbers_.size(); i++) { - ScanTable(table_numbers_[i]); - } - } - - Iterator* NewTableIterator(const FileMetaData& meta) { - // Same as compaction iterators: if paranoid_checks are on, turn - // on checksum verification. - ReadOptions r; - r.verify_checksums = options_.paranoid_checks; - return table_cache_->NewIterator(r, meta.number, meta.file_size); - } - - void ScanTable(uint64_t number) { - TableInfo t; - t.meta.number = number; - std::string fname = TableFileName(dbname_, number); - Status status = env_->GetFileSize(fname, &t.meta.file_size); - if (!status.ok()) { - // Try alternate file name. - fname = SSTTableFileName(dbname_, number); - Status s2 = env_->GetFileSize(fname, &t.meta.file_size); - if (s2.ok()) { - status = Status::OK(); - } - } - if (!status.ok()) { - ArchiveFile(TableFileName(dbname_, number)); - ArchiveFile(SSTTableFileName(dbname_, number)); - Log(options_.info_log, "Table #%llu: dropped: %s", - (unsigned long long) t.meta.number, - status.ToString().c_str()); - return; - } - - // Extract metadata by scanning through table. - int counter = 0; - Iterator* iter = NewTableIterator(t.meta); - bool empty = true; - ParsedInternalKey parsed; - t.max_sequence = 0; - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - Slice key = iter->key(); - if (!ParseInternalKey(key, &parsed)) { - Log(options_.info_log, "Table #%llu: unparsable key %s", - (unsigned long long) t.meta.number, - EscapeString(key).c_str()); - continue; - } - - counter++; - if (empty) { - empty = false; - t.meta.smallest.DecodeFrom(key); - } - t.meta.largest.DecodeFrom(key); - if (parsed.sequence > t.max_sequence) { - t.max_sequence = parsed.sequence; - } - } - if (!iter->status().ok()) { - status = iter->status(); - } - delete iter; - Log(options_.info_log, "Table #%llu: %d entries %s", - (unsigned long long) t.meta.number, - counter, - status.ToString().c_str()); - - if (status.ok()) { - tables_.push_back(t); - } else { - RepairTable(fname, t); // RepairTable archives input file. - } - } - - void RepairTable(const std::string& src, TableInfo t) { - // We will copy src contents to a new table and then rename the - // new table over the source. - - // Create builder. - std::string copy = TableFileName(dbname_, next_file_number_++); - WritableFile* file; - Status s = env_->NewWritableFile(copy, &file); - if (!s.ok()) { - return; - } - TableBuilder* builder = new TableBuilder(options_, file); - - // Copy data. - Iterator* iter = NewTableIterator(t.meta); - int counter = 0; - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - builder->Add(iter->key(), iter->value()); - counter++; - } - delete iter; - - ArchiveFile(src); - if (counter == 0) { - builder->Abandon(); // Nothing to save - } else { - s = builder->Finish(); - if (s.ok()) { - t.meta.file_size = builder->FileSize(); - } - } - delete builder; - builder = NULL; - - if (s.ok()) { - s = file->Close(); - } - delete file; - file = NULL; - - if (counter > 0 && s.ok()) { - std::string orig = TableFileName(dbname_, t.meta.number); - s = env_->RenameFile(copy, orig); - if (s.ok()) { - Log(options_.info_log, "Table #%llu: %d entries repaired", - (unsigned long long) t.meta.number, counter); - tables_.push_back(t); - } - } - if (!s.ok()) { - env_->DeleteFile(copy); - } - } - - Status WriteDescriptor() { - std::string tmp = TempFileName(dbname_, 1); - WritableFile* file; - Status status = env_->NewWritableFile(tmp, &file); - if (!status.ok()) { - return status; - } - - SequenceNumber max_sequence = 0; - for (size_t i = 0; i < tables_.size(); i++) { - if (max_sequence < tables_[i].max_sequence) { - max_sequence = tables_[i].max_sequence; - } - } - - edit_.SetComparatorName(icmp_.user_comparator()->Name()); - edit_.SetLogNumber(0); - edit_.SetNextFile(next_file_number_); - edit_.SetLastSequence(max_sequence); - - for (size_t i = 0; i < tables_.size(); i++) { - // TODO(opt): separate out into multiple levels - const TableInfo& t = tables_[i]; - edit_.AddFile(0, t.meta.number, t.meta.file_size, - t.meta.smallest, t.meta.largest); - } - - //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); - { - log::Writer log(file); - std::string record; - edit_.EncodeTo(&record); - status = log.AddRecord(record); - } - if (status.ok()) { - status = file->Close(); - } - delete file; - file = NULL; - - if (!status.ok()) { - env_->DeleteFile(tmp); - } else { - // Discard older manifests - for (size_t i = 0; i < manifests_.size(); i++) { - ArchiveFile(dbname_ + "/" + manifests_[i]); - } - - // Install new manifest - status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); - if (status.ok()) { - status = SetCurrentFile(env_, dbname_, 1); - } else { - env_->DeleteFile(tmp); - } - } - return status; - } - - void ArchiveFile(const std::string& fname) { - // Move into another directory. E.g., for - // dir/foo - // rename to - // dir/lost/foo - const char* slash = strrchr(fname.c_str(), '/'); - std::string new_dir; - if (slash != NULL) { - new_dir.assign(fname.data(), slash - fname.data()); - } - new_dir.append("/lost"); - env_->CreateDir(new_dir); // Ignore error - std::string new_file = new_dir; - new_file.append("/"); - new_file.append((slash == NULL) ? fname.c_str() : slash + 1); - Status s = env_->RenameFile(fname, new_file); - Log(options_.info_log, "Archiving %s: %s\n", - fname.c_str(), s.ToString().c_str()); - } -}; -} // namespace - -Status RepairDB(const std::string& dbname, const Options& options) { - Repairer repairer(dbname, options); - return repairer.Run(); -} - -} // namespace leveldb diff --git a/src/leveldb/db/skiplist.h b/src/leveldb/db/skiplist.h deleted file mode 100644 index ed8b092203..0000000000 --- a/src/leveldb/db/skiplist.h +++ /dev/null @@ -1,384 +0,0 @@ -#ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_ -#define STORAGE_LEVELDB_DB_SKIPLIST_H_ - -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Thread safety -// ------------- -// -// Writes require external synchronization, most likely a mutex. -// Reads require a guarantee that the SkipList will not be destroyed -// while the read is in progress. Apart from that, reads progress -// without any internal locking or synchronization. -// -// Invariants: -// -// (1) Allocated nodes are never deleted until the SkipList is -// destroyed. This is trivially guaranteed by the code since we -// never delete any skip list nodes. -// -// (2) The contents of a Node except for the next/prev pointers are -// immutable after the Node has been linked into the SkipList. -// Only Insert() modifies the list, and it is careful to initialize -// a node and use release-stores to publish the nodes in one or -// more lists. -// -// ... prev vs. next pointer ordering ... - -#include -#include -#include "port/port.h" -#include "util/arena.h" -#include "util/random.h" - -namespace leveldb { - -class Arena; - -template -class SkipList { - private: - struct Node; - - public: - // Create a new SkipList object that will use "cmp" for comparing keys, - // and will allocate memory using "*arena". Objects allocated in the arena - // must remain allocated for the lifetime of the skiplist object. - explicit SkipList(Comparator cmp, Arena* arena); - - // Insert key into the list. - // REQUIRES: nothing that compares equal to key is currently in the list. - void Insert(const Key& key); - - // Returns true iff an entry that compares equal to key is in the list. - bool Contains(const Key& key) const; - - // Iteration over the contents of a skip list - class Iterator { - public: - // Initialize an iterator over the specified list. - // The returned iterator is not valid. - explicit Iterator(const SkipList* list); - - // Returns true iff the iterator is positioned at a valid node. - bool Valid() const; - - // Returns the key at the current position. - // REQUIRES: Valid() - const Key& key() const; - - // Advances to the next position. - // REQUIRES: Valid() - void Next(); - - // Advances to the previous position. - // REQUIRES: Valid() - void Prev(); - - // Advance to the first entry with a key >= target - void Seek(const Key& target); - - // Position at the first entry in list. - // Final state of iterator is Valid() iff list is not empty. - void SeekToFirst(); - - // Position at the last entry in list. - // Final state of iterator is Valid() iff list is not empty. - void SeekToLast(); - - private: - const SkipList* list_; - Node* node_; - // Intentionally copyable - }; - - private: - enum { kMaxHeight = 12 }; - - // Immutable after construction - Comparator const compare_; - Arena* const arena_; // Arena used for allocations of nodes - - Node* const head_; - - // Modified only by Insert(). Read racily by readers, but stale - // values are ok. - port::AtomicPointer max_height_; // Height of the entire list - - inline int GetMaxHeight() const { - return static_cast( - reinterpret_cast(max_height_.NoBarrier_Load())); - } - - // Read/written only by Insert(). - Random rnd_; - - Node* NewNode(const Key& key, int height); - int RandomHeight(); - bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } - - // Return true if key is greater than the data stored in "n" - bool KeyIsAfterNode(const Key& key, Node* n) const; - - // Return the earliest node that comes at or after key. - // Return NULL if there is no such node. - // - // If prev is non-NULL, fills prev[level] with pointer to previous - // node at "level" for every level in [0..max_height_-1]. - Node* FindGreaterOrEqual(const Key& key, Node** prev) const; - - // Return the latest node with a key < key. - // Return head_ if there is no such node. - Node* FindLessThan(const Key& key) const; - - // Return the last node in the list. - // Return head_ if list is empty. - Node* FindLast() const; - - // No copying allowed - SkipList(const SkipList&); - void operator=(const SkipList&); -}; - -// Implementation details follow -template -struct SkipList::Node { - explicit Node(const Key& k) : key(k) { } - - Key const key; - - // Accessors/mutators for links. Wrapped in methods so we can - // add the appropriate barriers as necessary. - Node* Next(int n) { - assert(n >= 0); - // Use an 'acquire load' so that we observe a fully initialized - // version of the returned Node. - return reinterpret_cast(next_[n].Acquire_Load()); - } - void SetNext(int n, Node* x) { - assert(n >= 0); - // Use a 'release store' so that anybody who reads through this - // pointer observes a fully initialized version of the inserted node. - next_[n].Release_Store(x); - } - - // No-barrier variants that can be safely used in a few locations. - Node* NoBarrier_Next(int n) { - assert(n >= 0); - return reinterpret_cast(next_[n].NoBarrier_Load()); - } - void NoBarrier_SetNext(int n, Node* x) { - assert(n >= 0); - next_[n].NoBarrier_Store(x); - } - - private: - // Array of length equal to the node height. next_[0] is lowest level link. - port::AtomicPointer next_[1]; -}; - -template -typename SkipList::Node* -SkipList::NewNode(const Key& key, int height) { - char* mem = arena_->AllocateAligned( - sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1)); - return new (mem) Node(key); -} - -template -inline SkipList::Iterator::Iterator(const SkipList* list) { - list_ = list; - node_ = NULL; -} - -template -inline bool SkipList::Iterator::Valid() const { - return node_ != NULL; -} - -template -inline const Key& SkipList::Iterator::key() const { - assert(Valid()); - return node_->key; -} - -template -inline void SkipList::Iterator::Next() { - assert(Valid()); - node_ = node_->Next(0); -} - -template -inline void SkipList::Iterator::Prev() { - // Instead of using explicit "prev" links, we just search for the - // last node that falls before key. - assert(Valid()); - node_ = list_->FindLessThan(node_->key); - if (node_ == list_->head_) { - node_ = NULL; - } -} - -template -inline void SkipList::Iterator::Seek(const Key& target) { - node_ = list_->FindGreaterOrEqual(target, NULL); -} - -template -inline void SkipList::Iterator::SeekToFirst() { - node_ = list_->head_->Next(0); -} - -template -inline void SkipList::Iterator::SeekToLast() { - node_ = list_->FindLast(); - if (node_ == list_->head_) { - node_ = NULL; - } -} - -template -int SkipList::RandomHeight() { - // Increase height with probability 1 in kBranching - static const unsigned int kBranching = 4; - int height = 1; - while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { - height++; - } - assert(height > 0); - assert(height <= kMaxHeight); - return height; -} - -template -bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { - // NULL n is considered infinite - return (n != NULL) && (compare_(n->key, key) < 0); -} - -template -typename SkipList::Node* SkipList::FindGreaterOrEqual(const Key& key, Node** prev) - const { - Node* x = head_; - int level = GetMaxHeight() - 1; - while (true) { - Node* next = x->Next(level); - if (KeyIsAfterNode(key, next)) { - // Keep searching in this list - x = next; - } else { - if (prev != NULL) prev[level] = x; - if (level == 0) { - return next; - } else { - // Switch to next list - level--; - } - } - } -} - -template -typename SkipList::Node* -SkipList::FindLessThan(const Key& key) const { - Node* x = head_; - int level = GetMaxHeight() - 1; - while (true) { - assert(x == head_ || compare_(x->key, key) < 0); - Node* next = x->Next(level); - if (next == NULL || compare_(next->key, key) >= 0) { - if (level == 0) { - return x; - } else { - // Switch to next list - level--; - } - } else { - x = next; - } - } -} - -template -typename SkipList::Node* SkipList::FindLast() - const { - Node* x = head_; - int level = GetMaxHeight() - 1; - while (true) { - Node* next = x->Next(level); - if (next == NULL) { - if (level == 0) { - return x; - } else { - // Switch to next list - level--; - } - } else { - x = next; - } - } -} - -template -SkipList::SkipList(Comparator cmp, Arena* arena) - : compare_(cmp), - arena_(arena), - head_(NewNode(0 /* any key will do */, kMaxHeight)), - max_height_(reinterpret_cast(1)), - rnd_(0xdeadbeef) { - for (int i = 0; i < kMaxHeight; i++) { - head_->SetNext(i, NULL); - } -} - -template -void SkipList::Insert(const Key& key) { - // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() - // here since Insert() is externally synchronized. - Node* prev[kMaxHeight]; - Node* x = FindGreaterOrEqual(key, prev); - - // Our data structure does not allow duplicate insertion - assert(x == NULL || !Equal(key, x->key)); - - int height = RandomHeight(); - if (height > GetMaxHeight()) { - for (int i = GetMaxHeight(); i < height; i++) { - prev[i] = head_; - } - //fprintf(stderr, "Change height from %d to %d\n", max_height_, height); - - // It is ok to mutate max_height_ without any synchronization - // with concurrent readers. A concurrent reader that observes - // the new value of max_height_ will see either the old value of - // new level pointers from head_ (NULL), or a new value set in - // the loop below. In the former case the reader will - // immediately drop to the next level since NULL sorts after all - // keys. In the latter case the reader will use the new node. - max_height_.NoBarrier_Store(reinterpret_cast(height)); - } - - x = NewNode(key, height); - for (int i = 0; i < height; i++) { - // NoBarrier_SetNext() suffices since we will add a barrier when - // we publish a pointer to "x" in prev[i]. - x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); - prev[i]->SetNext(i, x); - } -} - -template -bool SkipList::Contains(const Key& key) const { - Node* x = FindGreaterOrEqual(key, NULL); - if (x != NULL && Equal(key, x->key)) { - return true; - } else { - return false; - } -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_ diff --git a/src/leveldb/db/skiplist_test.cc b/src/leveldb/db/skiplist_test.cc deleted file mode 100644 index c78f4b4fb1..0000000000 --- a/src/leveldb/db/skiplist_test.cc +++ /dev/null @@ -1,378 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/skiplist.h" -#include -#include "leveldb/env.h" -#include "util/arena.h" -#include "util/hash.h" -#include "util/random.h" -#include "util/testharness.h" - -namespace leveldb { - -typedef uint64_t Key; - -struct Comparator { - int operator()(const Key& a, const Key& b) const { - if (a < b) { - return -1; - } else if (a > b) { - return +1; - } else { - return 0; - } - } -}; - -class SkipTest { }; - -TEST(SkipTest, Empty) { - Arena arena; - Comparator cmp; - SkipList list(cmp, &arena); - ASSERT_TRUE(!list.Contains(10)); - - SkipList::Iterator iter(&list); - ASSERT_TRUE(!iter.Valid()); - iter.SeekToFirst(); - ASSERT_TRUE(!iter.Valid()); - iter.Seek(100); - ASSERT_TRUE(!iter.Valid()); - iter.SeekToLast(); - ASSERT_TRUE(!iter.Valid()); -} - -TEST(SkipTest, InsertAndLookup) { - const int N = 2000; - const int R = 5000; - Random rnd(1000); - std::set keys; - Arena arena; - Comparator cmp; - SkipList list(cmp, &arena); - for (int i = 0; i < N; i++) { - Key key = rnd.Next() % R; - if (keys.insert(key).second) { - list.Insert(key); - } - } - - for (int i = 0; i < R; i++) { - if (list.Contains(i)) { - ASSERT_EQ(keys.count(i), 1); - } else { - ASSERT_EQ(keys.count(i), 0); - } - } - - // Simple iterator tests - { - SkipList::Iterator iter(&list); - ASSERT_TRUE(!iter.Valid()); - - iter.Seek(0); - ASSERT_TRUE(iter.Valid()); - ASSERT_EQ(*(keys.begin()), iter.key()); - - iter.SeekToFirst(); - ASSERT_TRUE(iter.Valid()); - ASSERT_EQ(*(keys.begin()), iter.key()); - - iter.SeekToLast(); - ASSERT_TRUE(iter.Valid()); - ASSERT_EQ(*(keys.rbegin()), iter.key()); - } - - // Forward iteration test - for (int i = 0; i < R; i++) { - SkipList::Iterator iter(&list); - iter.Seek(i); - - // Compare against model iterator - std::set::iterator model_iter = keys.lower_bound(i); - for (int j = 0; j < 3; j++) { - if (model_iter == keys.end()) { - ASSERT_TRUE(!iter.Valid()); - break; - } else { - ASSERT_TRUE(iter.Valid()); - ASSERT_EQ(*model_iter, iter.key()); - ++model_iter; - iter.Next(); - } - } - } - - // Backward iteration test - { - SkipList::Iterator iter(&list); - iter.SeekToLast(); - - // Compare against model iterator - for (std::set::reverse_iterator model_iter = keys.rbegin(); - model_iter != keys.rend(); - ++model_iter) { - ASSERT_TRUE(iter.Valid()); - ASSERT_EQ(*model_iter, iter.key()); - iter.Prev(); - } - ASSERT_TRUE(!iter.Valid()); - } -} - -// We want to make sure that with a single writer and multiple -// concurrent readers (with no synchronization other than when a -// reader's iterator is created), the reader always observes all the -// data that was present in the skip list when the iterator was -// constructor. Because insertions are happening concurrently, we may -// also observe new values that were inserted since the iterator was -// constructed, but we should never miss any values that were present -// at iterator construction time. -// -// We generate multi-part keys: -// -// where: -// key is in range [0..K-1] -// gen is a generation number for key -// hash is hash(key,gen) -// -// The insertion code picks a random key, sets gen to be 1 + the last -// generation number inserted for that key, and sets hash to Hash(key,gen). -// -// At the beginning of a read, we snapshot the last inserted -// generation number for each key. We then iterate, including random -// calls to Next() and Seek(). For every key we encounter, we -// check that it is either expected given the initial snapshot or has -// been concurrently added since the iterator started. -class ConcurrentTest { - private: - static const uint32_t K = 4; - - static uint64_t key(Key key) { return (key >> 40); } - static uint64_t gen(Key key) { return (key >> 8) & 0xffffffffu; } - static uint64_t hash(Key key) { return key & 0xff; } - - static uint64_t HashNumbers(uint64_t k, uint64_t g) { - uint64_t data[2] = { k, g }; - return Hash(reinterpret_cast(data), sizeof(data), 0); - } - - static Key MakeKey(uint64_t k, uint64_t g) { - assert(sizeof(Key) == sizeof(uint64_t)); - assert(k <= K); // We sometimes pass K to seek to the end of the skiplist - assert(g <= 0xffffffffu); - return ((k << 40) | (g << 8) | (HashNumbers(k, g) & 0xff)); - } - - static bool IsValidKey(Key k) { - return hash(k) == (HashNumbers(key(k), gen(k)) & 0xff); - } - - static Key RandomTarget(Random* rnd) { - switch (rnd->Next() % 10) { - case 0: - // Seek to beginning - return MakeKey(0, 0); - case 1: - // Seek to end - return MakeKey(K, 0); - default: - // Seek to middle - return MakeKey(rnd->Next() % K, 0); - } - } - - // Per-key generation - struct State { - port::AtomicPointer generation[K]; - void Set(int k, intptr_t v) { - generation[k].Release_Store(reinterpret_cast(v)); - } - intptr_t Get(int k) { - return reinterpret_cast(generation[k].Acquire_Load()); - } - - State() { - for (int k = 0; k < K; k++) { - Set(k, 0); - } - } - }; - - // Current state of the test - State current_; - - Arena arena_; - - // SkipList is not protected by mu_. We just use a single writer - // thread to modify it. - SkipList list_; - - public: - ConcurrentTest() : list_(Comparator(), &arena_) { } - - // REQUIRES: External synchronization - void WriteStep(Random* rnd) { - const uint32_t k = rnd->Next() % K; - const intptr_t g = current_.Get(k) + 1; - const Key key = MakeKey(k, g); - list_.Insert(key); - current_.Set(k, g); - } - - void ReadStep(Random* rnd) { - // Remember the initial committed state of the skiplist. - State initial_state; - for (int k = 0; k < K; k++) { - initial_state.Set(k, current_.Get(k)); - } - - Key pos = RandomTarget(rnd); - SkipList::Iterator iter(&list_); - iter.Seek(pos); - while (true) { - Key current; - if (!iter.Valid()) { - current = MakeKey(K, 0); - } else { - current = iter.key(); - ASSERT_TRUE(IsValidKey(current)) << current; - } - ASSERT_LE(pos, current) << "should not go backwards"; - - // Verify that everything in [pos,current) was not present in - // initial_state. - while (pos < current) { - ASSERT_LT(key(pos), K) << pos; - - // Note that generation 0 is never inserted, so it is ok if - // <*,0,*> is missing. - ASSERT_TRUE((gen(pos) == 0) || - (gen(pos) > initial_state.Get(key(pos))) - ) << "key: " << key(pos) - << "; gen: " << gen(pos) - << "; initgen: " - << initial_state.Get(key(pos)); - - // Advance to next key in the valid key space - if (key(pos) < key(current)) { - pos = MakeKey(key(pos) + 1, 0); - } else { - pos = MakeKey(key(pos), gen(pos) + 1); - } - } - - if (!iter.Valid()) { - break; - } - - if (rnd->Next() % 2) { - iter.Next(); - pos = MakeKey(key(pos), gen(pos) + 1); - } else { - Key new_target = RandomTarget(rnd); - if (new_target > pos) { - pos = new_target; - iter.Seek(new_target); - } - } - } - } -}; -const uint32_t ConcurrentTest::K; - -// Simple test that does single-threaded testing of the ConcurrentTest -// scaffolding. -TEST(SkipTest, ConcurrentWithoutThreads) { - ConcurrentTest test; - Random rnd(test::RandomSeed()); - for (int i = 0; i < 10000; i++) { - test.ReadStep(&rnd); - test.WriteStep(&rnd); - } -} - -class TestState { - public: - ConcurrentTest t_; - int seed_; - port::AtomicPointer quit_flag_; - - enum ReaderState { - STARTING, - RUNNING, - DONE - }; - - explicit TestState(int s) - : seed_(s), - quit_flag_(NULL), - state_(STARTING), - state_cv_(&mu_) {} - - void Wait(ReaderState s) { - mu_.Lock(); - while (state_ != s) { - state_cv_.Wait(); - } - mu_.Unlock(); - } - - void Change(ReaderState s) { - mu_.Lock(); - state_ = s; - state_cv_.Signal(); - mu_.Unlock(); - } - - private: - port::Mutex mu_; - ReaderState state_; - port::CondVar state_cv_; -}; - -static void ConcurrentReader(void* arg) { - TestState* state = reinterpret_cast(arg); - Random rnd(state->seed_); - int64_t reads = 0; - state->Change(TestState::RUNNING); - while (!state->quit_flag_.Acquire_Load()) { - state->t_.ReadStep(&rnd); - ++reads; - } - state->Change(TestState::DONE); -} - -static void RunConcurrent(int run) { - const int seed = test::RandomSeed() + (run * 100); - Random rnd(seed); - const int N = 1000; - const int kSize = 1000; - for (int i = 0; i < N; i++) { - if ((i % 100) == 0) { - fprintf(stderr, "Run %d of %d\n", i, N); - } - TestState state(seed + 1); - Env::Default()->Schedule(ConcurrentReader, &state); - state.Wait(TestState::RUNNING); - for (int i = 0; i < kSize; i++) { - state.t_.WriteStep(&rnd); - } - state.quit_flag_.Release_Store(&state); // Any non-NULL arg will do - state.Wait(TestState::DONE); - } -} - -TEST(SkipTest, Concurrent1) { RunConcurrent(1); } -TEST(SkipTest, Concurrent2) { RunConcurrent(2); } -TEST(SkipTest, Concurrent3) { RunConcurrent(3); } -TEST(SkipTest, Concurrent4) { RunConcurrent(4); } -TEST(SkipTest, Concurrent5) { RunConcurrent(5); } - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/snapshot.h b/src/leveldb/db/snapshot.h deleted file mode 100644 index e7f8fd2c37..0000000000 --- a/src/leveldb/db/snapshot.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ -#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ - -#include "leveldb/db.h" - -namespace leveldb { - -class SnapshotList; - -// Snapshots are kept in a doubly-linked list in the DB. -// Each SnapshotImpl corresponds to a particular sequence number. -class SnapshotImpl : public Snapshot { - public: - SequenceNumber number_; // const after creation - - private: - friend class SnapshotList; - - // SnapshotImpl is kept in a doubly-linked circular list - SnapshotImpl* prev_; - SnapshotImpl* next_; - - SnapshotList* list_; // just for sanity checks -}; - -class SnapshotList { - public: - SnapshotList() { - list_.prev_ = &list_; - list_.next_ = &list_; - } - - bool empty() const { return list_.next_ == &list_; } - SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; } - SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; } - - const SnapshotImpl* New(SequenceNumber seq) { - SnapshotImpl* s = new SnapshotImpl; - s->number_ = seq; - s->list_ = this; - s->next_ = &list_; - s->prev_ = list_.prev_; - s->prev_->next_ = s; - s->next_->prev_ = s; - return s; - } - - void Delete(const SnapshotImpl* s) { - assert(s->list_ == this); - s->prev_->next_ = s->next_; - s->next_->prev_ = s->prev_; - delete s; - } - - private: - // Dummy head of doubly-linked list of snapshots - SnapshotImpl list_; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/src/leveldb/db/table_cache.cc b/src/leveldb/db/table_cache.cc deleted file mode 100644 index e3d82cd3ea..0000000000 --- a/src/leveldb/db/table_cache.cc +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/table_cache.h" - -#include "db/filename.h" -#include "leveldb/env.h" -#include "leveldb/table.h" -#include "util/coding.h" - -namespace leveldb { - -struct TableAndFile { - RandomAccessFile* file; - Table* table; -}; - -static void DeleteEntry(const Slice& key, void* value) { - TableAndFile* tf = reinterpret_cast(value); - delete tf->table; - delete tf->file; - delete tf; -} - -static void UnrefEntry(void* arg1, void* arg2) { - Cache* cache = reinterpret_cast(arg1); - Cache::Handle* h = reinterpret_cast(arg2); - cache->Release(h); -} - -TableCache::TableCache(const std::string& dbname, - const Options* options, - int entries) - : env_(options->env), - dbname_(dbname), - options_(options), - cache_(NewLRUCache(entries)) { -} - -TableCache::~TableCache() { - delete cache_; -} - -Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, - Cache::Handle** handle) { - Status s; - char buf[sizeof(file_number)]; - EncodeFixed64(buf, file_number); - Slice key(buf, sizeof(buf)); - *handle = cache_->Lookup(key); - if (*handle == NULL) { - std::string fname = TableFileName(dbname_, file_number); - RandomAccessFile* file = NULL; - Table* table = NULL; - s = env_->NewRandomAccessFile(fname, &file); - if (!s.ok()) { - std::string old_fname = SSTTableFileName(dbname_, file_number); - if (env_->NewRandomAccessFile(old_fname, &file).ok()) { - s = Status::OK(); - } - } - if (s.ok()) { - s = Table::Open(*options_, file, file_size, &table); - } - - if (!s.ok()) { - assert(table == NULL); - delete file; - // We do not cache error results so that if the error is transient, - // or somebody repairs the file, we recover automatically. - } else { - TableAndFile* tf = new TableAndFile; - tf->file = file; - tf->table = table; - *handle = cache_->Insert(key, tf, 1, &DeleteEntry); - } - } - return s; -} - -Iterator* TableCache::NewIterator(const ReadOptions& options, - uint64_t file_number, - uint64_t file_size, - Table** tableptr) { - if (tableptr != NULL) { - *tableptr = NULL; - } - - Cache::Handle* handle = NULL; - Status s = FindTable(file_number, file_size, &handle); - if (!s.ok()) { - return NewErrorIterator(s); - } - - Table* table = reinterpret_cast(cache_->Value(handle))->table; - Iterator* result = table->NewIterator(options); - result->RegisterCleanup(&UnrefEntry, cache_, handle); - if (tableptr != NULL) { - *tableptr = table; - } - return result; -} - -Status TableCache::Get(const ReadOptions& options, - uint64_t file_number, - uint64_t file_size, - const Slice& k, - void* arg, - void (*saver)(void*, const Slice&, const Slice&)) { - Cache::Handle* handle = NULL; - Status s = FindTable(file_number, file_size, &handle); - if (s.ok()) { - Table* t = reinterpret_cast(cache_->Value(handle))->table; - s = t->InternalGet(options, k, arg, saver); - cache_->Release(handle); - } - return s; -} - -void TableCache::Evict(uint64_t file_number) { - char buf[sizeof(file_number)]; - EncodeFixed64(buf, file_number); - cache_->Erase(Slice(buf, sizeof(buf))); -} - -} // namespace leveldb diff --git a/src/leveldb/db/table_cache.h b/src/leveldb/db/table_cache.h deleted file mode 100644 index 8cf4aaf12d..0000000000 --- a/src/leveldb/db/table_cache.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Thread-safe (provides internal synchronization) - -#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ -#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ - -#include -#include -#include "db/dbformat.h" -#include "leveldb/cache.h" -#include "leveldb/table.h" -#include "port/port.h" - -namespace leveldb { - -class Env; - -class TableCache { - public: - TableCache(const std::string& dbname, const Options* options, int entries); - ~TableCache(); - - // Return an iterator for the specified file number (the corresponding - // file length must be exactly "file_size" bytes). If "tableptr" is - // non-NULL, also sets "*tableptr" to point to the Table object - // underlying the returned iterator, or NULL if no Table object underlies - // the returned iterator. The returned "*tableptr" object is owned by - // the cache and should not be deleted, and is valid for as long as the - // returned iterator is live. - Iterator* NewIterator(const ReadOptions& options, - uint64_t file_number, - uint64_t file_size, - Table** tableptr = NULL); - - // If a seek to internal key "k" in specified file finds an entry, - // call (*handle_result)(arg, found_key, found_value). - Status Get(const ReadOptions& options, - uint64_t file_number, - uint64_t file_size, - const Slice& k, - void* arg, - void (*handle_result)(void*, const Slice&, const Slice&)); - - // Evict any entry for the specified file number - void Evict(uint64_t file_number); - - private: - Env* const env_; - const std::string dbname_; - const Options* options_; - Cache* cache_; - - Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/src/leveldb/db/version_edit.cc b/src/leveldb/db/version_edit.cc deleted file mode 100644 index f10a2d58b2..0000000000 --- a/src/leveldb/db/version_edit.cc +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/version_edit.h" - -#include "db/version_set.h" -#include "util/coding.h" - -namespace leveldb { - -// Tag numbers for serialized VersionEdit. These numbers are written to -// disk and should not be changed. -enum Tag { - kComparator = 1, - kLogNumber = 2, - kNextFileNumber = 3, - kLastSequence = 4, - kCompactPointer = 5, - kDeletedFile = 6, - kNewFile = 7, - // 8 was used for large value refs - kPrevLogNumber = 9 -}; - -void VersionEdit::Clear() { - comparator_.clear(); - log_number_ = 0; - prev_log_number_ = 0; - last_sequence_ = 0; - next_file_number_ = 0; - has_comparator_ = false; - has_log_number_ = false; - has_prev_log_number_ = false; - has_next_file_number_ = false; - has_last_sequence_ = false; - deleted_files_.clear(); - new_files_.clear(); -} - -void VersionEdit::EncodeTo(std::string* dst) const { - if (has_comparator_) { - PutVarint32(dst, kComparator); - PutLengthPrefixedSlice(dst, comparator_); - } - if (has_log_number_) { - PutVarint32(dst, kLogNumber); - PutVarint64(dst, log_number_); - } - if (has_prev_log_number_) { - PutVarint32(dst, kPrevLogNumber); - PutVarint64(dst, prev_log_number_); - } - if (has_next_file_number_) { - PutVarint32(dst, kNextFileNumber); - PutVarint64(dst, next_file_number_); - } - if (has_last_sequence_) { - PutVarint32(dst, kLastSequence); - PutVarint64(dst, last_sequence_); - } - - for (size_t i = 0; i < compact_pointers_.size(); i++) { - PutVarint32(dst, kCompactPointer); - PutVarint32(dst, compact_pointers_[i].first); // level - PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); - } - - for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); - iter != deleted_files_.end(); - ++iter) { - PutVarint32(dst, kDeletedFile); - PutVarint32(dst, iter->first); // level - PutVarint64(dst, iter->second); // file number - } - - for (size_t i = 0; i < new_files_.size(); i++) { - const FileMetaData& f = new_files_[i].second; - PutVarint32(dst, kNewFile); - PutVarint32(dst, new_files_[i].first); // level - PutVarint64(dst, f.number); - PutVarint64(dst, f.file_size); - PutLengthPrefixedSlice(dst, f.smallest.Encode()); - PutLengthPrefixedSlice(dst, f.largest.Encode()); - } -} - -static bool GetInternalKey(Slice* input, InternalKey* dst) { - Slice str; - if (GetLengthPrefixedSlice(input, &str)) { - dst->DecodeFrom(str); - return true; - } else { - return false; - } -} - -static bool GetLevel(Slice* input, int* level) { - uint32_t v; - if (GetVarint32(input, &v) && - v < config::kNumLevels) { - *level = v; - return true; - } else { - return false; - } -} - -Status VersionEdit::DecodeFrom(const Slice& src) { - Clear(); - Slice input = src; - const char* msg = NULL; - uint32_t tag; - - // Temporary storage for parsing - int level; - uint64_t number; - FileMetaData f; - Slice str; - InternalKey key; - - while (msg == NULL && GetVarint32(&input, &tag)) { - switch (tag) { - case kComparator: - if (GetLengthPrefixedSlice(&input, &str)) { - comparator_ = str.ToString(); - has_comparator_ = true; - } else { - msg = "comparator name"; - } - break; - - case kLogNumber: - if (GetVarint64(&input, &log_number_)) { - has_log_number_ = true; - } else { - msg = "log number"; - } - break; - - case kPrevLogNumber: - if (GetVarint64(&input, &prev_log_number_)) { - has_prev_log_number_ = true; - } else { - msg = "previous log number"; - } - break; - - case kNextFileNumber: - if (GetVarint64(&input, &next_file_number_)) { - has_next_file_number_ = true; - } else { - msg = "next file number"; - } - break; - - case kLastSequence: - if (GetVarint64(&input, &last_sequence_)) { - has_last_sequence_ = true; - } else { - msg = "last sequence number"; - } - break; - - case kCompactPointer: - if (GetLevel(&input, &level) && - GetInternalKey(&input, &key)) { - compact_pointers_.push_back(std::make_pair(level, key)); - } else { - msg = "compaction pointer"; - } - break; - - case kDeletedFile: - if (GetLevel(&input, &level) && - GetVarint64(&input, &number)) { - deleted_files_.insert(std::make_pair(level, number)); - } else { - msg = "deleted file"; - } - break; - - case kNewFile: - if (GetLevel(&input, &level) && - GetVarint64(&input, &f.number) && - GetVarint64(&input, &f.file_size) && - GetInternalKey(&input, &f.smallest) && - GetInternalKey(&input, &f.largest)) { - new_files_.push_back(std::make_pair(level, f)); - } else { - msg = "new-file entry"; - } - break; - - default: - msg = "unknown tag"; - break; - } - } - - if (msg == NULL && !input.empty()) { - msg = "invalid tag"; - } - - Status result; - if (msg != NULL) { - result = Status::Corruption("VersionEdit", msg); - } - return result; -} - -std::string VersionEdit::DebugString() const { - std::string r; - r.append("VersionEdit {"); - if (has_comparator_) { - r.append("\n Comparator: "); - r.append(comparator_); - } - if (has_log_number_) { - r.append("\n LogNumber: "); - AppendNumberTo(&r, log_number_); - } - if (has_prev_log_number_) { - r.append("\n PrevLogNumber: "); - AppendNumberTo(&r, prev_log_number_); - } - if (has_next_file_number_) { - r.append("\n NextFile: "); - AppendNumberTo(&r, next_file_number_); - } - if (has_last_sequence_) { - r.append("\n LastSeq: "); - AppendNumberTo(&r, last_sequence_); - } - for (size_t i = 0; i < compact_pointers_.size(); i++) { - r.append("\n CompactPointer: "); - AppendNumberTo(&r, compact_pointers_[i].first); - r.append(" "); - r.append(compact_pointers_[i].second.DebugString()); - } - for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); - iter != deleted_files_.end(); - ++iter) { - r.append("\n DeleteFile: "); - AppendNumberTo(&r, iter->first); - r.append(" "); - AppendNumberTo(&r, iter->second); - } - for (size_t i = 0; i < new_files_.size(); i++) { - const FileMetaData& f = new_files_[i].second; - r.append("\n AddFile: "); - AppendNumberTo(&r, new_files_[i].first); - r.append(" "); - AppendNumberTo(&r, f.number); - r.append(" "); - AppendNumberTo(&r, f.file_size); - r.append(" "); - r.append(f.smallest.DebugString()); - r.append(" .. "); - r.append(f.largest.DebugString()); - } - r.append("\n}\n"); - return r; -} - -} // namespace leveldb diff --git a/src/leveldb/db/version_edit.h b/src/leveldb/db/version_edit.h deleted file mode 100644 index eaef77b327..0000000000 --- a/src/leveldb/db/version_edit.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ -#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ - -#include -#include -#include -#include "db/dbformat.h" - -namespace leveldb { - -class VersionSet; - -struct FileMetaData { - int refs; - int allowed_seeks; // Seeks allowed until compaction - uint64_t number; - uint64_t file_size; // File size in bytes - InternalKey smallest; // Smallest internal key served by table - InternalKey largest; // Largest internal key served by table - - FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) { } -}; - -class VersionEdit { - public: - VersionEdit() { Clear(); } - ~VersionEdit() { } - - void Clear(); - - void SetComparatorName(const Slice& name) { - has_comparator_ = true; - comparator_ = name.ToString(); - } - void SetLogNumber(uint64_t num) { - has_log_number_ = true; - log_number_ = num; - } - void SetPrevLogNumber(uint64_t num) { - has_prev_log_number_ = true; - prev_log_number_ = num; - } - void SetNextFile(uint64_t num) { - has_next_file_number_ = true; - next_file_number_ = num; - } - void SetLastSequence(SequenceNumber seq) { - has_last_sequence_ = true; - last_sequence_ = seq; - } - void SetCompactPointer(int level, const InternalKey& key) { - compact_pointers_.push_back(std::make_pair(level, key)); - } - - // Add the specified file at the specified number. - // REQUIRES: This version has not been saved (see VersionSet::SaveTo) - // REQUIRES: "smallest" and "largest" are smallest and largest keys in file - void AddFile(int level, uint64_t file, - uint64_t file_size, - const InternalKey& smallest, - const InternalKey& largest) { - FileMetaData f; - f.number = file; - f.file_size = file_size; - f.smallest = smallest; - f.largest = largest; - new_files_.push_back(std::make_pair(level, f)); - } - - // Delete the specified "file" from the specified "level". - void DeleteFile(int level, uint64_t file) { - deleted_files_.insert(std::make_pair(level, file)); - } - - void EncodeTo(std::string* dst) const; - Status DecodeFrom(const Slice& src); - - std::string DebugString() const; - - private: - friend class VersionSet; - - typedef std::set< std::pair > DeletedFileSet; - - std::string comparator_; - uint64_t log_number_; - uint64_t prev_log_number_; - uint64_t next_file_number_; - SequenceNumber last_sequence_; - bool has_comparator_; - bool has_log_number_; - bool has_prev_log_number_; - bool has_next_file_number_; - bool has_last_sequence_; - - std::vector< std::pair > compact_pointers_; - DeletedFileSet deleted_files_; - std::vector< std::pair > new_files_; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/src/leveldb/db/version_edit_test.cc b/src/leveldb/db/version_edit_test.cc deleted file mode 100644 index 280310b49d..0000000000 --- a/src/leveldb/db/version_edit_test.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/version_edit.h" -#include "util/testharness.h" - -namespace leveldb { - -static void TestEncodeDecode(const VersionEdit& edit) { - std::string encoded, encoded2; - edit.EncodeTo(&encoded); - VersionEdit parsed; - Status s = parsed.DecodeFrom(encoded); - ASSERT_TRUE(s.ok()) << s.ToString(); - parsed.EncodeTo(&encoded2); - ASSERT_EQ(encoded, encoded2); -} - -class VersionEditTest { }; - -TEST(VersionEditTest, EncodeDecode) { - static const uint64_t kBig = 1ull << 50; - - VersionEdit edit; - for (int i = 0; i < 4; i++) { - TestEncodeDecode(edit); - edit.AddFile(3, kBig + 300 + i, kBig + 400 + i, - InternalKey("foo", kBig + 500 + i, kTypeValue), - InternalKey("zoo", kBig + 600 + i, kTypeDeletion)); - edit.DeleteFile(4, kBig + 700 + i); - edit.SetCompactPointer(i, InternalKey("x", kBig + 900 + i, kTypeValue)); - } - - edit.SetComparatorName("foo"); - edit.SetLogNumber(kBig + 100); - edit.SetNextFile(kBig + 200); - edit.SetLastSequence(kBig + 1000); - TestEncodeDecode(edit); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc deleted file mode 100644 index aa83df55e4..0000000000 --- a/src/leveldb/db/version_set.cc +++ /dev/null @@ -1,1484 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/version_set.h" - -#include -#include -#include "db/filename.h" -#include "db/log_reader.h" -#include "db/log_writer.h" -#include "db/memtable.h" -#include "db/table_cache.h" -#include "leveldb/env.h" -#include "leveldb/table_builder.h" -#include "table/merger.h" -#include "table/two_level_iterator.h" -#include "util/coding.h" -#include "util/logging.h" - -namespace leveldb { - -static const int kTargetFileSize = 2 * 1048576; - -// Maximum bytes of overlaps in grandparent (i.e., level+2) before we -// stop building a single file in a level->level+1 compaction. -static const int64_t kMaxGrandParentOverlapBytes = 10 * kTargetFileSize; - -// Maximum number of bytes in all compacted files. We avoid expanding -// the lower level file set of a compaction if it would make the -// total compaction cover more than this many bytes. -static const int64_t kExpandedCompactionByteSizeLimit = 25 * kTargetFileSize; - -static double MaxBytesForLevel(int level) { - // Note: the result for level zero is not really used since we set - // the level-0 compaction threshold based on number of files. - double result = 10 * 1048576.0; // Result for both level-0 and level-1 - while (level > 1) { - result *= 10; - level--; - } - return result; -} - -static uint64_t MaxFileSizeForLevel(int level) { - return kTargetFileSize; // We could vary per level to reduce number of files? -} - -static int64_t TotalFileSize(const std::vector& files) { - int64_t sum = 0; - for (size_t i = 0; i < files.size(); i++) { - sum += files[i]->file_size; - } - return sum; -} - -Version::~Version() { - assert(refs_ == 0); - - // Remove from linked list - prev_->next_ = next_; - next_->prev_ = prev_; - - // Drop references to files - for (int level = 0; level < config::kNumLevels; level++) { - for (size_t i = 0; i < files_[level].size(); i++) { - FileMetaData* f = files_[level][i]; - assert(f->refs > 0); - f->refs--; - if (f->refs <= 0) { - delete f; - } - } - } -} - -int FindFile(const InternalKeyComparator& icmp, - const std::vector& files, - const Slice& key) { - uint32_t left = 0; - uint32_t right = files.size(); - while (left < right) { - uint32_t mid = (left + right) / 2; - const FileMetaData* f = files[mid]; - if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { - // Key at "mid.largest" is < "target". Therefore all - // files at or before "mid" are uninteresting. - left = mid + 1; - } else { - // Key at "mid.largest" is >= "target". Therefore all files - // after "mid" are uninteresting. - right = mid; - } - } - return right; -} - -static bool AfterFile(const Comparator* ucmp, - const Slice* user_key, const FileMetaData* f) { - // NULL user_key occurs before all keys and is therefore never after *f - return (user_key != NULL && - ucmp->Compare(*user_key, f->largest.user_key()) > 0); -} - -static bool BeforeFile(const Comparator* ucmp, - const Slice* user_key, const FileMetaData* f) { - // NULL user_key occurs after all keys and is therefore never before *f - return (user_key != NULL && - ucmp->Compare(*user_key, f->smallest.user_key()) < 0); -} - -bool SomeFileOverlapsRange( - const InternalKeyComparator& icmp, - bool disjoint_sorted_files, - const std::vector& files, - const Slice* smallest_user_key, - const Slice* largest_user_key) { - const Comparator* ucmp = icmp.user_comparator(); - if (!disjoint_sorted_files) { - // Need to check against all files - for (size_t i = 0; i < files.size(); i++) { - const FileMetaData* f = files[i]; - if (AfterFile(ucmp, smallest_user_key, f) || - BeforeFile(ucmp, largest_user_key, f)) { - // No overlap - } else { - return true; // Overlap - } - } - return false; - } - - // Binary search over file list - uint32_t index = 0; - if (smallest_user_key != NULL) { - // Find the earliest possible internal key for smallest_user_key - InternalKey small(*smallest_user_key, kMaxSequenceNumber,kValueTypeForSeek); - index = FindFile(icmp, files, small.Encode()); - } - - if (index >= files.size()) { - // beginning of range is after all files, so no overlap. - return false; - } - - return !BeforeFile(ucmp, largest_user_key, files[index]); -} - -// An internal iterator. For a given version/level pair, yields -// information about the files in the level. For a given entry, key() -// is the largest key that occurs in the file, and value() is an -// 16-byte value containing the file number and file size, both -// encoded using EncodeFixed64. -class Version::LevelFileNumIterator : public Iterator { - public: - LevelFileNumIterator(const InternalKeyComparator& icmp, - const std::vector* flist) - : icmp_(icmp), - flist_(flist), - index_(flist->size()) { // Marks as invalid - } - virtual bool Valid() const { - return index_ < flist_->size(); - } - virtual void Seek(const Slice& target) { - index_ = FindFile(icmp_, *flist_, target); - } - virtual void SeekToFirst() { index_ = 0; } - virtual void SeekToLast() { - index_ = flist_->empty() ? 0 : flist_->size() - 1; - } - virtual void Next() { - assert(Valid()); - index_++; - } - virtual void Prev() { - assert(Valid()); - if (index_ == 0) { - index_ = flist_->size(); // Marks as invalid - } else { - index_--; - } - } - Slice key() const { - assert(Valid()); - return (*flist_)[index_]->largest.Encode(); - } - Slice value() const { - assert(Valid()); - EncodeFixed64(value_buf_, (*flist_)[index_]->number); - EncodeFixed64(value_buf_+8, (*flist_)[index_]->file_size); - return Slice(value_buf_, sizeof(value_buf_)); - } - virtual Status status() const { return Status::OK(); } - private: - const InternalKeyComparator icmp_; - const std::vector* const flist_; - uint32_t index_; - - // Backing store for value(). Holds the file number and size. - mutable char value_buf_[16]; -}; - -static Iterator* GetFileIterator(void* arg, - const ReadOptions& options, - const Slice& file_value) { - TableCache* cache = reinterpret_cast(arg); - if (file_value.size() != 16) { - return NewErrorIterator( - Status::Corruption("FileReader invoked with unexpected value")); - } else { - return cache->NewIterator(options, - DecodeFixed64(file_value.data()), - DecodeFixed64(file_value.data() + 8)); - } -} - -Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, - int level) const { - return NewTwoLevelIterator( - new LevelFileNumIterator(vset_->icmp_, &files_[level]), - &GetFileIterator, vset_->table_cache_, options); -} - -void Version::AddIterators(const ReadOptions& options, - std::vector* iters) { - // Merge all level zero files together since they may overlap - for (size_t i = 0; i < files_[0].size(); i++) { - iters->push_back( - vset_->table_cache_->NewIterator( - options, files_[0][i]->number, files_[0][i]->file_size)); - } - - // For levels > 0, we can use a concatenating iterator that sequentially - // walks through the non-overlapping files in the level, opening them - // lazily. - for (int level = 1; level < config::kNumLevels; level++) { - if (!files_[level].empty()) { - iters->push_back(NewConcatenatingIterator(options, level)); - } - } -} - -// Callback from TableCache::Get() -namespace { -enum SaverState { - kNotFound, - kFound, - kDeleted, - kCorrupt, -}; -struct Saver { - SaverState state; - const Comparator* ucmp; - Slice user_key; - std::string* value; -}; -} -static void SaveValue(void* arg, const Slice& ikey, const Slice& v) { - Saver* s = reinterpret_cast(arg); - ParsedInternalKey parsed_key; - if (!ParseInternalKey(ikey, &parsed_key)) { - s->state = kCorrupt; - } else { - if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { - s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; - if (s->state == kFound) { - s->value->assign(v.data(), v.size()); - } - } - } -} - -static bool NewestFirst(FileMetaData* a, FileMetaData* b) { - return a->number > b->number; -} - -void Version::ForEachOverlapping(Slice user_key, Slice internal_key, - void* arg, - bool (*func)(void*, int, FileMetaData*)) { - // TODO(sanjay): Change Version::Get() to use this function. - const Comparator* ucmp = vset_->icmp_.user_comparator(); - - // Search level-0 in order from newest to oldest. - std::vector tmp; - tmp.reserve(files_[0].size()); - for (uint32_t i = 0; i < files_[0].size(); i++) { - FileMetaData* f = files_[0][i]; - if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && - ucmp->Compare(user_key, f->largest.user_key()) <= 0) { - tmp.push_back(f); - } - } - if (!tmp.empty()) { - std::sort(tmp.begin(), tmp.end(), NewestFirst); - for (uint32_t i = 0; i < tmp.size(); i++) { - if (!(*func)(arg, 0, tmp[i])) { - return; - } - } - } - - // Search other levels. - for (int level = 1; level < config::kNumLevels; level++) { - size_t num_files = files_[level].size(); - if (num_files == 0) continue; - - // Binary search to find earliest index whose largest key >= internal_key. - uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); - if (index < num_files) { - FileMetaData* f = files_[level][index]; - if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { - // All of "f" is past any data for user_key - } else { - if (!(*func)(arg, level, f)) { - return; - } - } - } - } -} - -Status Version::Get(const ReadOptions& options, - const LookupKey& k, - std::string* value, - GetStats* stats) { - Slice ikey = k.internal_key(); - Slice user_key = k.user_key(); - const Comparator* ucmp = vset_->icmp_.user_comparator(); - Status s; - - stats->seek_file = NULL; - stats->seek_file_level = -1; - FileMetaData* last_file_read = NULL; - int last_file_read_level = -1; - - // We can search level-by-level since entries never hop across - // levels. Therefore we are guaranteed that if we find data - // in an smaller level, later levels are irrelevant. - std::vector tmp; - FileMetaData* tmp2; - for (int level = 0; level < config::kNumLevels; level++) { - size_t num_files = files_[level].size(); - if (num_files == 0) continue; - - // Get the list of files to search in this level - FileMetaData* const* files = &files_[level][0]; - if (level == 0) { - // Level-0 files may overlap each other. Find all files that - // overlap user_key and process them in order from newest to oldest. - tmp.reserve(num_files); - for (uint32_t i = 0; i < num_files; i++) { - FileMetaData* f = files[i]; - if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && - ucmp->Compare(user_key, f->largest.user_key()) <= 0) { - tmp.push_back(f); - } - } - if (tmp.empty()) continue; - - std::sort(tmp.begin(), tmp.end(), NewestFirst); - files = &tmp[0]; - num_files = tmp.size(); - } else { - // Binary search to find earliest index whose largest key >= ikey. - uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); - if (index >= num_files) { - files = NULL; - num_files = 0; - } else { - tmp2 = files[index]; - if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { - // All of "tmp2" is past any data for user_key - files = NULL; - num_files = 0; - } else { - files = &tmp2; - num_files = 1; - } - } - } - - for (uint32_t i = 0; i < num_files; ++i) { - if (last_file_read != NULL && stats->seek_file == NULL) { - // We have had more than one seek for this read. Charge the 1st file. - stats->seek_file = last_file_read; - stats->seek_file_level = last_file_read_level; - } - - FileMetaData* f = files[i]; - last_file_read = f; - last_file_read_level = level; - - Saver saver; - saver.state = kNotFound; - saver.ucmp = ucmp; - saver.user_key = user_key; - saver.value = value; - s = vset_->table_cache_->Get(options, f->number, f->file_size, - ikey, &saver, SaveValue); - if (!s.ok()) { - return s; - } - switch (saver.state) { - case kNotFound: - break; // Keep searching in other files - case kFound: - return s; - case kDeleted: - s = Status::NotFound(Slice()); // Use empty error message for speed - return s; - case kCorrupt: - s = Status::Corruption("corrupted key for ", user_key); - return s; - } - } - } - - return Status::NotFound(Slice()); // Use an empty error message for speed -} - -bool Version::UpdateStats(const GetStats& stats) { - FileMetaData* f = stats.seek_file; - if (f != NULL) { - f->allowed_seeks--; - if (f->allowed_seeks <= 0 && file_to_compact_ == NULL) { - file_to_compact_ = f; - file_to_compact_level_ = stats.seek_file_level; - return true; - } - } - return false; -} - -bool Version::RecordReadSample(Slice internal_key) { - ParsedInternalKey ikey; - if (!ParseInternalKey(internal_key, &ikey)) { - return false; - } - - struct State { - GetStats stats; // Holds first matching file - int matches; - - static bool Match(void* arg, int level, FileMetaData* f) { - State* state = reinterpret_cast(arg); - state->matches++; - if (state->matches == 1) { - // Remember first match. - state->stats.seek_file = f; - state->stats.seek_file_level = level; - } - // We can stop iterating once we have a second match. - return state->matches < 2; - } - }; - - State state; - state.matches = 0; - ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match); - - // Must have at least two matches since we want to merge across - // files. But what if we have a single file that contains many - // overwrites and deletions? Should we have another mechanism for - // finding such files? - if (state.matches >= 2) { - // 1MB cost is about 1 seek (see comment in Builder::Apply). - return UpdateStats(state.stats); - } - return false; -} - -void Version::Ref() { - ++refs_; -} - -void Version::Unref() { - assert(this != &vset_->dummy_versions_); - assert(refs_ >= 1); - --refs_; - if (refs_ == 0) { - delete this; - } -} - -bool Version::OverlapInLevel(int level, - const Slice* smallest_user_key, - const Slice* largest_user_key) { - return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], - smallest_user_key, largest_user_key); -} - -int Version::PickLevelForMemTableOutput( - const Slice& smallest_user_key, - const Slice& largest_user_key) { - int level = 0; - if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { - // Push to next level if there is no overlap in next level, - // and the #bytes overlapping in the level after that are limited. - InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); - InternalKey limit(largest_user_key, 0, static_cast(0)); - std::vector overlaps; - while (level < config::kMaxMemCompactLevel) { - if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { - break; - } - if (level + 2 < config::kNumLevels) { - // Check that file does not overlap too many grandparent bytes. - GetOverlappingInputs(level + 2, &start, &limit, &overlaps); - const int64_t sum = TotalFileSize(overlaps); - if (sum > kMaxGrandParentOverlapBytes) { - break; - } - } - level++; - } - } - return level; -} - -// Store in "*inputs" all files in "level" that overlap [begin,end] -void Version::GetOverlappingInputs( - int level, - const InternalKey* begin, - const InternalKey* end, - std::vector* inputs) { - assert(level >= 0); - assert(level < config::kNumLevels); - inputs->clear(); - Slice user_begin, user_end; - if (begin != NULL) { - user_begin = begin->user_key(); - } - if (end != NULL) { - user_end = end->user_key(); - } - const Comparator* user_cmp = vset_->icmp_.user_comparator(); - for (size_t i = 0; i < files_[level].size(); ) { - FileMetaData* f = files_[level][i++]; - const Slice file_start = f->smallest.user_key(); - const Slice file_limit = f->largest.user_key(); - if (begin != NULL && user_cmp->Compare(file_limit, user_begin) < 0) { - // "f" is completely before specified range; skip it - } else if (end != NULL && user_cmp->Compare(file_start, user_end) > 0) { - // "f" is completely after specified range; skip it - } else { - inputs->push_back(f); - if (level == 0) { - // Level-0 files may overlap each other. So check if the newly - // added file has expanded the range. If so, restart search. - if (begin != NULL && user_cmp->Compare(file_start, user_begin) < 0) { - user_begin = file_start; - inputs->clear(); - i = 0; - } else if (end != NULL && user_cmp->Compare(file_limit, user_end) > 0) { - user_end = file_limit; - inputs->clear(); - i = 0; - } - } - } - } -} - -std::string Version::DebugString() const { - std::string r; - for (int level = 0; level < config::kNumLevels; level++) { - // E.g., - // --- level 1 --- - // 17:123['a' .. 'd'] - // 20:43['e' .. 'g'] - r.append("--- level "); - AppendNumberTo(&r, level); - r.append(" ---\n"); - const std::vector& files = files_[level]; - for (size_t i = 0; i < files.size(); i++) { - r.push_back(' '); - AppendNumberTo(&r, files[i]->number); - r.push_back(':'); - AppendNumberTo(&r, files[i]->file_size); - r.append("["); - r.append(files[i]->smallest.DebugString()); - r.append(" .. "); - r.append(files[i]->largest.DebugString()); - r.append("]\n"); - } - } - return r; -} - -// A helper class so we can efficiently apply a whole sequence -// of edits to a particular state without creating intermediate -// Versions that contain full copies of the intermediate state. -class VersionSet::Builder { - private: - // Helper to sort by v->files_[file_number].smallest - struct BySmallestKey { - const InternalKeyComparator* internal_comparator; - - bool operator()(FileMetaData* f1, FileMetaData* f2) const { - int r = internal_comparator->Compare(f1->smallest, f2->smallest); - if (r != 0) { - return (r < 0); - } else { - // Break ties by file number - return (f1->number < f2->number); - } - } - }; - - typedef std::set FileSet; - struct LevelState { - std::set deleted_files; - FileSet* added_files; - }; - - VersionSet* vset_; - Version* base_; - LevelState levels_[config::kNumLevels]; - - public: - // Initialize a builder with the files from *base and other info from *vset - Builder(VersionSet* vset, Version* base) - : vset_(vset), - base_(base) { - base_->Ref(); - BySmallestKey cmp; - cmp.internal_comparator = &vset_->icmp_; - for (int level = 0; level < config::kNumLevels; level++) { - levels_[level].added_files = new FileSet(cmp); - } - } - - ~Builder() { - for (int level = 0; level < config::kNumLevels; level++) { - const FileSet* added = levels_[level].added_files; - std::vector to_unref; - to_unref.reserve(added->size()); - for (FileSet::const_iterator it = added->begin(); - it != added->end(); ++it) { - to_unref.push_back(*it); - } - delete added; - for (uint32_t i = 0; i < to_unref.size(); i++) { - FileMetaData* f = to_unref[i]; - f->refs--; - if (f->refs <= 0) { - delete f; - } - } - } - base_->Unref(); - } - - // Apply all of the edits in *edit to the current state. - void Apply(VersionEdit* edit) { - // Update compaction pointers - for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { - const int level = edit->compact_pointers_[i].first; - vset_->compact_pointer_[level] = - edit->compact_pointers_[i].second.Encode().ToString(); - } - - // Delete files - const VersionEdit::DeletedFileSet& del = edit->deleted_files_; - for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); - iter != del.end(); - ++iter) { - const int level = iter->first; - const uint64_t number = iter->second; - levels_[level].deleted_files.insert(number); - } - - // Add new files - for (size_t i = 0; i < edit->new_files_.size(); i++) { - const int level = edit->new_files_[i].first; - FileMetaData* f = new FileMetaData(edit->new_files_[i].second); - f->refs = 1; - - // We arrange to automatically compact this file after - // a certain number of seeks. Let's assume: - // (1) One seek costs 10ms - // (2) Writing or reading 1MB costs 10ms (100MB/s) - // (3) A compaction of 1MB does 25MB of IO: - // 1MB read from this level - // 10-12MB read from next level (boundaries may be misaligned) - // 10-12MB written to next level - // This implies that 25 seeks cost the same as the compaction - // of 1MB of data. I.e., one seek costs approximately the - // same as the compaction of 40KB of data. We are a little - // conservative and allow approximately one seek for every 16KB - // of data before triggering a compaction. - f->allowed_seeks = (f->file_size / 16384); - if (f->allowed_seeks < 100) f->allowed_seeks = 100; - - levels_[level].deleted_files.erase(f->number); - levels_[level].added_files->insert(f); - } - } - - // Save the current state in *v. - void SaveTo(Version* v) { - BySmallestKey cmp; - cmp.internal_comparator = &vset_->icmp_; - for (int level = 0; level < config::kNumLevels; level++) { - // Merge the set of added files with the set of pre-existing files. - // Drop any deleted files. Store the result in *v. - const std::vector& base_files = base_->files_[level]; - std::vector::const_iterator base_iter = base_files.begin(); - std::vector::const_iterator base_end = base_files.end(); - const FileSet* added = levels_[level].added_files; - v->files_[level].reserve(base_files.size() + added->size()); - for (FileSet::const_iterator added_iter = added->begin(); - added_iter != added->end(); - ++added_iter) { - // Add all smaller files listed in base_ - for (std::vector::const_iterator bpos - = std::upper_bound(base_iter, base_end, *added_iter, cmp); - base_iter != bpos; - ++base_iter) { - MaybeAddFile(v, level, *base_iter); - } - - MaybeAddFile(v, level, *added_iter); - } - - // Add remaining base files - for (; base_iter != base_end; ++base_iter) { - MaybeAddFile(v, level, *base_iter); - } - -#ifndef NDEBUG - // Make sure there is no overlap in levels > 0 - if (level > 0) { - for (uint32_t i = 1; i < v->files_[level].size(); i++) { - const InternalKey& prev_end = v->files_[level][i-1]->largest; - const InternalKey& this_begin = v->files_[level][i]->smallest; - if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { - fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", - prev_end.DebugString().c_str(), - this_begin.DebugString().c_str()); - abort(); - } - } - } -#endif - } - } - - void MaybeAddFile(Version* v, int level, FileMetaData* f) { - if (levels_[level].deleted_files.count(f->number) > 0) { - // File is deleted: do nothing - } else { - std::vector* files = &v->files_[level]; - if (level > 0 && !files->empty()) { - // Must not overlap - assert(vset_->icmp_.Compare((*files)[files->size()-1]->largest, - f->smallest) < 0); - } - f->refs++; - files->push_back(f); - } - } -}; - -VersionSet::VersionSet(const std::string& dbname, - const Options* options, - TableCache* table_cache, - const InternalKeyComparator* cmp) - : env_(options->env), - dbname_(dbname), - options_(options), - table_cache_(table_cache), - icmp_(*cmp), - next_file_number_(2), - manifest_file_number_(0), // Filled by Recover() - last_sequence_(0), - log_number_(0), - prev_log_number_(0), - descriptor_file_(NULL), - descriptor_log_(NULL), - dummy_versions_(this), - current_(NULL) { - AppendVersion(new Version(this)); -} - -VersionSet::~VersionSet() { - current_->Unref(); - assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty - delete descriptor_log_; - delete descriptor_file_; -} - -void VersionSet::AppendVersion(Version* v) { - // Make "v" current - assert(v->refs_ == 0); - assert(v != current_); - if (current_ != NULL) { - current_->Unref(); - } - current_ = v; - v->Ref(); - - // Append to linked list - v->prev_ = dummy_versions_.prev_; - v->next_ = &dummy_versions_; - v->prev_->next_ = v; - v->next_->prev_ = v; -} - -Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) { - if (edit->has_log_number_) { - assert(edit->log_number_ >= log_number_); - assert(edit->log_number_ < next_file_number_); - } else { - edit->SetLogNumber(log_number_); - } - - if (!edit->has_prev_log_number_) { - edit->SetPrevLogNumber(prev_log_number_); - } - - edit->SetNextFile(next_file_number_); - edit->SetLastSequence(last_sequence_); - - Version* v = new Version(this); - { - Builder builder(this, current_); - builder.Apply(edit); - builder.SaveTo(v); - } - Finalize(v); - - // Initialize new descriptor log file if necessary by creating - // a temporary file that contains a snapshot of the current version. - std::string new_manifest_file; - Status s; - if (descriptor_log_ == NULL) { - // No reason to unlock *mu here since we only hit this path in the - // first call to LogAndApply (when opening the database). - assert(descriptor_file_ == NULL); - new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); - edit->SetNextFile(next_file_number_); - s = env_->NewWritableFile(new_manifest_file, &descriptor_file_); - if (s.ok()) { - descriptor_log_ = new log::Writer(descriptor_file_); - s = WriteSnapshot(descriptor_log_); - } - } - - // Unlock during expensive MANIFEST log write - { - mu->Unlock(); - - // Write new record to MANIFEST log - if (s.ok()) { - std::string record; - edit->EncodeTo(&record); - s = descriptor_log_->AddRecord(record); - if (s.ok()) { - s = descriptor_file_->Sync(); - } - if (!s.ok()) { - Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); - } - } - - // If we just created a new descriptor file, install it by writing a - // new CURRENT file that points to it. - if (s.ok() && !new_manifest_file.empty()) { - s = SetCurrentFile(env_, dbname_, manifest_file_number_); - } - - mu->Lock(); - } - - // Install the new version - if (s.ok()) { - AppendVersion(v); - log_number_ = edit->log_number_; - prev_log_number_ = edit->prev_log_number_; - } else { - delete v; - if (!new_manifest_file.empty()) { - delete descriptor_log_; - delete descriptor_file_; - descriptor_log_ = NULL; - descriptor_file_ = NULL; - env_->DeleteFile(new_manifest_file); - } - } - - return s; -} - -Status VersionSet::Recover() { - struct LogReporter : public log::Reader::Reporter { - Status* status; - virtual void Corruption(size_t bytes, const Status& s) { - if (this->status->ok()) *this->status = s; - } - }; - - // Read "CURRENT" file, which contains a pointer to the current manifest file - std::string current; - Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); - if (!s.ok()) { - return s; - } - if (current.empty() || current[current.size()-1] != '\n') { - return Status::Corruption("CURRENT file does not end with newline"); - } - current.resize(current.size() - 1); - - std::string dscname = dbname_ + "/" + current; - SequentialFile* file; - s = env_->NewSequentialFile(dscname, &file); - if (!s.ok()) { - return s; - } - - bool have_log_number = false; - bool have_prev_log_number = false; - bool have_next_file = false; - bool have_last_sequence = false; - uint64_t next_file = 0; - uint64_t last_sequence = 0; - uint64_t log_number = 0; - uint64_t prev_log_number = 0; - Builder builder(this, current_); - - { - LogReporter reporter; - reporter.status = &s; - log::Reader reader(file, &reporter, true/*checksum*/, 0/*initial_offset*/); - Slice record; - std::string scratch; - while (reader.ReadRecord(&record, &scratch) && s.ok()) { - VersionEdit edit; - s = edit.DecodeFrom(record); - if (s.ok()) { - if (edit.has_comparator_ && - edit.comparator_ != icmp_.user_comparator()->Name()) { - s = Status::InvalidArgument( - edit.comparator_ + " does not match existing comparator ", - icmp_.user_comparator()->Name()); - } - } - - if (s.ok()) { - builder.Apply(&edit); - } - - if (edit.has_log_number_) { - log_number = edit.log_number_; - have_log_number = true; - } - - if (edit.has_prev_log_number_) { - prev_log_number = edit.prev_log_number_; - have_prev_log_number = true; - } - - if (edit.has_next_file_number_) { - next_file = edit.next_file_number_; - have_next_file = true; - } - - if (edit.has_last_sequence_) { - last_sequence = edit.last_sequence_; - have_last_sequence = true; - } - } - } - delete file; - file = NULL; - - if (s.ok()) { - if (!have_next_file) { - s = Status::Corruption("no meta-nextfile entry in descriptor"); - } else if (!have_log_number) { - s = Status::Corruption("no meta-lognumber entry in descriptor"); - } else if (!have_last_sequence) { - s = Status::Corruption("no last-sequence-number entry in descriptor"); - } - - if (!have_prev_log_number) { - prev_log_number = 0; - } - - MarkFileNumberUsed(prev_log_number); - MarkFileNumberUsed(log_number); - } - - if (s.ok()) { - Version* v = new Version(this); - builder.SaveTo(v); - // Install recovered version - Finalize(v); - AppendVersion(v); - manifest_file_number_ = next_file; - next_file_number_ = next_file + 1; - last_sequence_ = last_sequence; - log_number_ = log_number; - prev_log_number_ = prev_log_number; - } - - return s; -} - -void VersionSet::MarkFileNumberUsed(uint64_t number) { - if (next_file_number_ <= number) { - next_file_number_ = number + 1; - } -} - -void VersionSet::Finalize(Version* v) { - // Precomputed best level for next compaction - int best_level = -1; - double best_score = -1; - - for (int level = 0; level < config::kNumLevels-1; level++) { - double score; - if (level == 0) { - // We treat level-0 specially by bounding the number of files - // instead of number of bytes for two reasons: - // - // (1) With larger write-buffer sizes, it is nice not to do too - // many level-0 compactions. - // - // (2) The files in level-0 are merged on every read and - // therefore we wish to avoid too many files when the individual - // file size is small (perhaps because of a small write-buffer - // setting, or very high compression ratios, or lots of - // overwrites/deletions). - score = v->files_[level].size() / - static_cast(config::kL0_CompactionTrigger); - } else { - // Compute the ratio of current size to size limit. - const uint64_t level_bytes = TotalFileSize(v->files_[level]); - score = static_cast(level_bytes) / MaxBytesForLevel(level); - } - - if (score > best_score) { - best_level = level; - best_score = score; - } - } - - v->compaction_level_ = best_level; - v->compaction_score_ = best_score; -} - -Status VersionSet::WriteSnapshot(log::Writer* log) { - // TODO: Break up into multiple records to reduce memory usage on recovery? - - // Save metadata - VersionEdit edit; - edit.SetComparatorName(icmp_.user_comparator()->Name()); - - // Save compaction pointers - for (int level = 0; level < config::kNumLevels; level++) { - if (!compact_pointer_[level].empty()) { - InternalKey key; - key.DecodeFrom(compact_pointer_[level]); - edit.SetCompactPointer(level, key); - } - } - - // Save files - for (int level = 0; level < config::kNumLevels; level++) { - const std::vector& files = current_->files_[level]; - for (size_t i = 0; i < files.size(); i++) { - const FileMetaData* f = files[i]; - edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); - } - } - - std::string record; - edit.EncodeTo(&record); - return log->AddRecord(record); -} - -int VersionSet::NumLevelFiles(int level) const { - assert(level >= 0); - assert(level < config::kNumLevels); - return current_->files_[level].size(); -} - -const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { - // Update code if kNumLevels changes - assert(config::kNumLevels == 7); - snprintf(scratch->buffer, sizeof(scratch->buffer), - "files[ %d %d %d %d %d %d %d ]", - int(current_->files_[0].size()), - int(current_->files_[1].size()), - int(current_->files_[2].size()), - int(current_->files_[3].size()), - int(current_->files_[4].size()), - int(current_->files_[5].size()), - int(current_->files_[6].size())); - return scratch->buffer; -} - -uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { - uint64_t result = 0; - for (int level = 0; level < config::kNumLevels; level++) { - const std::vector& files = v->files_[level]; - for (size_t i = 0; i < files.size(); i++) { - if (icmp_.Compare(files[i]->largest, ikey) <= 0) { - // Entire file is before "ikey", so just add the file size - result += files[i]->file_size; - } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { - // Entire file is after "ikey", so ignore - if (level > 0) { - // Files other than level 0 are sorted by meta->smallest, so - // no further files in this level will contain data for - // "ikey". - break; - } - } else { - // "ikey" falls in the range for this table. Add the - // approximate offset of "ikey" within the table. - Table* tableptr; - Iterator* iter = table_cache_->NewIterator( - ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); - if (tableptr != NULL) { - result += tableptr->ApproximateOffsetOf(ikey.Encode()); - } - delete iter; - } - } - } - return result; -} - -void VersionSet::AddLiveFiles(std::set* live) { - for (Version* v = dummy_versions_.next_; - v != &dummy_versions_; - v = v->next_) { - for (int level = 0; level < config::kNumLevels; level++) { - const std::vector& files = v->files_[level]; - for (size_t i = 0; i < files.size(); i++) { - live->insert(files[i]->number); - } - } - } -} - -int64_t VersionSet::NumLevelBytes(int level) const { - assert(level >= 0); - assert(level < config::kNumLevels); - return TotalFileSize(current_->files_[level]); -} - -int64_t VersionSet::MaxNextLevelOverlappingBytes() { - int64_t result = 0; - std::vector overlaps; - for (int level = 1; level < config::kNumLevels - 1; level++) { - for (size_t i = 0; i < current_->files_[level].size(); i++) { - const FileMetaData* f = current_->files_[level][i]; - current_->GetOverlappingInputs(level+1, &f->smallest, &f->largest, - &overlaps); - const int64_t sum = TotalFileSize(overlaps); - if (sum > result) { - result = sum; - } - } - } - return result; -} - -// Stores the minimal range that covers all entries in inputs in -// *smallest, *largest. -// REQUIRES: inputs is not empty -void VersionSet::GetRange(const std::vector& inputs, - InternalKey* smallest, - InternalKey* largest) { - assert(!inputs.empty()); - smallest->Clear(); - largest->Clear(); - for (size_t i = 0; i < inputs.size(); i++) { - FileMetaData* f = inputs[i]; - if (i == 0) { - *smallest = f->smallest; - *largest = f->largest; - } else { - if (icmp_.Compare(f->smallest, *smallest) < 0) { - *smallest = f->smallest; - } - if (icmp_.Compare(f->largest, *largest) > 0) { - *largest = f->largest; - } - } - } -} - -// Stores the minimal range that covers all entries in inputs1 and inputs2 -// in *smallest, *largest. -// REQUIRES: inputs is not empty -void VersionSet::GetRange2(const std::vector& inputs1, - const std::vector& inputs2, - InternalKey* smallest, - InternalKey* largest) { - std::vector all = inputs1; - all.insert(all.end(), inputs2.begin(), inputs2.end()); - GetRange(all, smallest, largest); -} - -Iterator* VersionSet::MakeInputIterator(Compaction* c) { - ReadOptions options; - options.verify_checksums = options_->paranoid_checks; - options.fill_cache = false; - - // Level-0 files have to be merged together. For other levels, - // we will make a concatenating iterator per level. - // TODO(opt): use concatenating iterator for level-0 if there is no overlap - const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); - Iterator** list = new Iterator*[space]; - int num = 0; - for (int which = 0; which < 2; which++) { - if (!c->inputs_[which].empty()) { - if (c->level() + which == 0) { - const std::vector& files = c->inputs_[which]; - for (size_t i = 0; i < files.size(); i++) { - list[num++] = table_cache_->NewIterator( - options, files[i]->number, files[i]->file_size); - } - } else { - // Create concatenating iterator for the files from this level - list[num++] = NewTwoLevelIterator( - new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), - &GetFileIterator, table_cache_, options); - } - } - } - assert(num <= space); - Iterator* result = NewMergingIterator(&icmp_, list, num); - delete[] list; - return result; -} - -Compaction* VersionSet::PickCompaction() { - Compaction* c; - int level; - - // We prefer compactions triggered by too much data in a level over - // the compactions triggered by seeks. - const bool size_compaction = (current_->compaction_score_ >= 1); - const bool seek_compaction = (current_->file_to_compact_ != NULL); - if (size_compaction) { - level = current_->compaction_level_; - assert(level >= 0); - assert(level+1 < config::kNumLevels); - c = new Compaction(level); - - // Pick the first file that comes after compact_pointer_[level] - for (size_t i = 0; i < current_->files_[level].size(); i++) { - FileMetaData* f = current_->files_[level][i]; - if (compact_pointer_[level].empty() || - icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) { - c->inputs_[0].push_back(f); - break; - } - } - if (c->inputs_[0].empty()) { - // Wrap-around to the beginning of the key space - c->inputs_[0].push_back(current_->files_[level][0]); - } - } else if (seek_compaction) { - level = current_->file_to_compact_level_; - c = new Compaction(level); - c->inputs_[0].push_back(current_->file_to_compact_); - } else { - return NULL; - } - - c->input_version_ = current_; - c->input_version_->Ref(); - - // Files in level 0 may overlap each other, so pick up all overlapping ones - if (level == 0) { - InternalKey smallest, largest; - GetRange(c->inputs_[0], &smallest, &largest); - // Note that the next call will discard the file we placed in - // c->inputs_[0] earlier and replace it with an overlapping set - // which will include the picked file. - current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); - assert(!c->inputs_[0].empty()); - } - - SetupOtherInputs(c); - - return c; -} - -void VersionSet::SetupOtherInputs(Compaction* c) { - const int level = c->level(); - InternalKey smallest, largest; - GetRange(c->inputs_[0], &smallest, &largest); - - current_->GetOverlappingInputs(level+1, &smallest, &largest, &c->inputs_[1]); - - // Get entire range covered by compaction - InternalKey all_start, all_limit; - GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); - - // See if we can grow the number of inputs in "level" without - // changing the number of "level+1" files we pick up. - if (!c->inputs_[1].empty()) { - std::vector expanded0; - current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0); - const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); - const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); - const int64_t expanded0_size = TotalFileSize(expanded0); - if (expanded0.size() > c->inputs_[0].size() && - inputs1_size + expanded0_size < kExpandedCompactionByteSizeLimit) { - InternalKey new_start, new_limit; - GetRange(expanded0, &new_start, &new_limit); - std::vector expanded1; - current_->GetOverlappingInputs(level+1, &new_start, &new_limit, - &expanded1); - if (expanded1.size() == c->inputs_[1].size()) { - Log(options_->info_log, - "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", - level, - int(c->inputs_[0].size()), - int(c->inputs_[1].size()), - long(inputs0_size), long(inputs1_size), - int(expanded0.size()), - int(expanded1.size()), - long(expanded0_size), long(inputs1_size)); - smallest = new_start; - largest = new_limit; - c->inputs_[0] = expanded0; - c->inputs_[1] = expanded1; - GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); - } - } - } - - // Compute the set of grandparent files that overlap this compaction - // (parent == level+1; grandparent == level+2) - if (level + 2 < config::kNumLevels) { - current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, - &c->grandparents_); - } - - if (false) { - Log(options_->info_log, "Compacting %d '%s' .. '%s'", - level, - smallest.DebugString().c_str(), - largest.DebugString().c_str()); - } - - // Update the place where we will do the next compaction for this level. - // We update this immediately instead of waiting for the VersionEdit - // to be applied so that if the compaction fails, we will try a different - // key range next time. - compact_pointer_[level] = largest.Encode().ToString(); - c->edit_.SetCompactPointer(level, largest); -} - -Compaction* VersionSet::CompactRange( - int level, - const InternalKey* begin, - const InternalKey* end) { - std::vector inputs; - current_->GetOverlappingInputs(level, begin, end, &inputs); - if (inputs.empty()) { - return NULL; - } - - // Avoid compacting too much in one shot in case the range is large. - // But we cannot do this for level-0 since level-0 files can overlap - // and we must not pick one file and drop another older file if the - // two files overlap. - if (level > 0) { - const uint64_t limit = MaxFileSizeForLevel(level); - uint64_t total = 0; - for (size_t i = 0; i < inputs.size(); i++) { - uint64_t s = inputs[i]->file_size; - total += s; - if (total >= limit) { - inputs.resize(i + 1); - break; - } - } - } - - Compaction* c = new Compaction(level); - c->input_version_ = current_; - c->input_version_->Ref(); - c->inputs_[0] = inputs; - SetupOtherInputs(c); - return c; -} - -Compaction::Compaction(int level) - : level_(level), - max_output_file_size_(MaxFileSizeForLevel(level)), - input_version_(NULL), - grandparent_index_(0), - seen_key_(false), - overlapped_bytes_(0) { - for (int i = 0; i < config::kNumLevels; i++) { - level_ptrs_[i] = 0; - } -} - -Compaction::~Compaction() { - if (input_version_ != NULL) { - input_version_->Unref(); - } -} - -bool Compaction::IsTrivialMove() const { - // Avoid a move if there is lots of overlapping grandparent data. - // Otherwise, the move could create a parent file that will require - // a very expensive merge later on. - return (num_input_files(0) == 1 && - num_input_files(1) == 0 && - TotalFileSize(grandparents_) <= kMaxGrandParentOverlapBytes); -} - -void Compaction::AddInputDeletions(VersionEdit* edit) { - for (int which = 0; which < 2; which++) { - for (size_t i = 0; i < inputs_[which].size(); i++) { - edit->DeleteFile(level_ + which, inputs_[which][i]->number); - } - } -} - -bool Compaction::IsBaseLevelForKey(const Slice& user_key) { - // Maybe use binary search to find right entry instead of linear search? - const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); - for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) { - const std::vector& files = input_version_->files_[lvl]; - for (; level_ptrs_[lvl] < files.size(); ) { - FileMetaData* f = files[level_ptrs_[lvl]]; - if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { - // We've advanced far enough - if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { - // Key falls in this file's range, so definitely not base level - return false; - } - break; - } - level_ptrs_[lvl]++; - } - } - return true; -} - -bool Compaction::ShouldStopBefore(const Slice& internal_key) { - // Scan to find earliest grandparent file that contains key. - const InternalKeyComparator* icmp = &input_version_->vset_->icmp_; - while (grandparent_index_ < grandparents_.size() && - icmp->Compare(internal_key, - grandparents_[grandparent_index_]->largest.Encode()) > 0) { - if (seen_key_) { - overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; - } - grandparent_index_++; - } - seen_key_ = true; - - if (overlapped_bytes_ > kMaxGrandParentOverlapBytes) { - // Too much overlap for current output; start new output - overlapped_bytes_ = 0; - return true; - } else { - return false; - } -} - -void Compaction::ReleaseInputs() { - if (input_version_ != NULL) { - input_version_->Unref(); - input_version_ = NULL; - } -} - -} // namespace leveldb diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h deleted file mode 100644 index 8dc14b8e01..0000000000 --- a/src/leveldb/db/version_set.h +++ /dev/null @@ -1,396 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// The representation of a DBImpl consists of a set of Versions. The -// newest version is called "current". Older versions may be kept -// around to provide a consistent view to live iterators. -// -// Each Version keeps track of a set of Table files per level. The -// entire set of versions is maintained in a VersionSet. -// -// Version,VersionSet are thread-compatible, but require external -// synchronization on all accesses. - -#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ -#define STORAGE_LEVELDB_DB_VERSION_SET_H_ - -#include -#include -#include -#include "db/dbformat.h" -#include "db/version_edit.h" -#include "port/port.h" -#include "port/thread_annotations.h" - -namespace leveldb { - -namespace log { class Writer; } - -class Compaction; -class Iterator; -class MemTable; -class TableBuilder; -class TableCache; -class Version; -class VersionSet; -class WritableFile; - -// Return the smallest index i such that files[i]->largest >= key. -// Return files.size() if there is no such file. -// REQUIRES: "files" contains a sorted list of non-overlapping files. -extern int FindFile(const InternalKeyComparator& icmp, - const std::vector& files, - const Slice& key); - -// Returns true iff some file in "files" overlaps the user key range -// [*smallest,*largest]. -// smallest==NULL represents a key smaller than all keys in the DB. -// largest==NULL represents a key largest than all keys in the DB. -// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges -// in sorted order. -extern bool SomeFileOverlapsRange( - const InternalKeyComparator& icmp, - bool disjoint_sorted_files, - const std::vector& files, - const Slice* smallest_user_key, - const Slice* largest_user_key); - -class Version { - public: - // Append to *iters a sequence of iterators that will - // yield the contents of this Version when merged together. - // REQUIRES: This version has been saved (see VersionSet::SaveTo) - void AddIterators(const ReadOptions&, std::vector* iters); - - // Lookup the value for key. If found, store it in *val and - // return OK. Else return a non-OK status. Fills *stats. - // REQUIRES: lock is not held - struct GetStats { - FileMetaData* seek_file; - int seek_file_level; - }; - Status Get(const ReadOptions&, const LookupKey& key, std::string* val, - GetStats* stats); - - // Adds "stats" into the current state. Returns true if a new - // compaction may need to be triggered, false otherwise. - // REQUIRES: lock is held - bool UpdateStats(const GetStats& stats); - - // Record a sample of bytes read at the specified internal key. - // Samples are taken approximately once every config::kReadBytesPeriod - // bytes. Returns true if a new compaction may need to be triggered. - // REQUIRES: lock is held - bool RecordReadSample(Slice key); - - // Reference count management (so Versions do not disappear out from - // under live iterators) - void Ref(); - void Unref(); - - void GetOverlappingInputs( - int level, - const InternalKey* begin, // NULL means before all keys - const InternalKey* end, // NULL means after all keys - std::vector* inputs); - - // Returns true iff some file in the specified level overlaps - // some part of [*smallest_user_key,*largest_user_key]. - // smallest_user_key==NULL represents a key smaller than all keys in the DB. - // largest_user_key==NULL represents a key largest than all keys in the DB. - bool OverlapInLevel(int level, - const Slice* smallest_user_key, - const Slice* largest_user_key); - - // Return the level at which we should place a new memtable compaction - // result that covers the range [smallest_user_key,largest_user_key]. - int PickLevelForMemTableOutput(const Slice& smallest_user_key, - const Slice& largest_user_key); - - int NumFiles(int level) const { return files_[level].size(); } - - // Return a human readable string that describes this version's contents. - std::string DebugString() const; - - private: - friend class Compaction; - friend class VersionSet; - - class LevelFileNumIterator; - Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; - - // Call func(arg, level, f) for every file that overlaps user_key in - // order from newest to oldest. If an invocation of func returns - // false, makes no more calls. - // - // REQUIRES: user portion of internal_key == user_key. - void ForEachOverlapping(Slice user_key, Slice internal_key, - void* arg, - bool (*func)(void*, int, FileMetaData*)); - - VersionSet* vset_; // VersionSet to which this Version belongs - Version* next_; // Next version in linked list - Version* prev_; // Previous version in linked list - int refs_; // Number of live refs to this version - - // List of files per level - std::vector files_[config::kNumLevels]; - - // Next file to compact based on seek stats. - FileMetaData* file_to_compact_; - int file_to_compact_level_; - - // Level that should be compacted next and its compaction score. - // Score < 1 means compaction is not strictly needed. These fields - // are initialized by Finalize(). - double compaction_score_; - int compaction_level_; - - explicit Version(VersionSet* vset) - : vset_(vset), next_(this), prev_(this), refs_(0), - file_to_compact_(NULL), - file_to_compact_level_(-1), - compaction_score_(-1), - compaction_level_(-1) { - } - - ~Version(); - - // No copying allowed - Version(const Version&); - void operator=(const Version&); -}; - -class VersionSet { - public: - VersionSet(const std::string& dbname, - const Options* options, - TableCache* table_cache, - const InternalKeyComparator*); - ~VersionSet(); - - // Apply *edit to the current version to form a new descriptor that - // is both saved to persistent state and installed as the new - // current version. Will release *mu while actually writing to the file. - // REQUIRES: *mu is held on entry. - // REQUIRES: no other thread concurrently calls LogAndApply() - Status LogAndApply(VersionEdit* edit, port::Mutex* mu) - EXCLUSIVE_LOCKS_REQUIRED(mu); - - // Recover the last saved descriptor from persistent storage. - Status Recover(); - - // Return the current version. - Version* current() const { return current_; } - - // Return the current manifest file number - uint64_t ManifestFileNumber() const { return manifest_file_number_; } - - // Allocate and return a new file number - uint64_t NewFileNumber() { return next_file_number_++; } - - // Arrange to reuse "file_number" unless a newer file number has - // already been allocated. - // REQUIRES: "file_number" was returned by a call to NewFileNumber(). - void ReuseFileNumber(uint64_t file_number) { - if (next_file_number_ == file_number + 1) { - next_file_number_ = file_number; - } - } - - // Return the number of Table files at the specified level. - int NumLevelFiles(int level) const; - - // Return the combined file size of all files at the specified level. - int64_t NumLevelBytes(int level) const; - - // Return the last sequence number. - uint64_t LastSequence() const { return last_sequence_; } - - // Set the last sequence number to s. - void SetLastSequence(uint64_t s) { - assert(s >= last_sequence_); - last_sequence_ = s; - } - - // Mark the specified file number as used. - void MarkFileNumberUsed(uint64_t number); - - // Return the current log file number. - uint64_t LogNumber() const { return log_number_; } - - // Return the log file number for the log file that is currently - // being compacted, or zero if there is no such log file. - uint64_t PrevLogNumber() const { return prev_log_number_; } - - // Pick level and inputs for a new compaction. - // Returns NULL if there is no compaction to be done. - // Otherwise returns a pointer to a heap-allocated object that - // describes the compaction. Caller should delete the result. - Compaction* PickCompaction(); - - // Return a compaction object for compacting the range [begin,end] in - // the specified level. Returns NULL if there is nothing in that - // level that overlaps the specified range. Caller should delete - // the result. - Compaction* CompactRange( - int level, - const InternalKey* begin, - const InternalKey* end); - - // Return the maximum overlapping data (in bytes) at next level for any - // file at a level >= 1. - int64_t MaxNextLevelOverlappingBytes(); - - // Create an iterator that reads over the compaction inputs for "*c". - // The caller should delete the iterator when no longer needed. - Iterator* MakeInputIterator(Compaction* c); - - // Returns true iff some level needs a compaction. - bool NeedsCompaction() const { - Version* v = current_; - return (v->compaction_score_ >= 1) || (v->file_to_compact_ != NULL); - } - - // Add all files listed in any live version to *live. - // May also mutate some internal state. - void AddLiveFiles(std::set* live); - - // Return the approximate offset in the database of the data for - // "key" as of version "v". - uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); - - // Return a human-readable short (single-line) summary of the number - // of files per level. Uses *scratch as backing store. - struct LevelSummaryStorage { - char buffer[100]; - }; - const char* LevelSummary(LevelSummaryStorage* scratch) const; - - private: - class Builder; - - friend class Compaction; - friend class Version; - - void Finalize(Version* v); - - void GetRange(const std::vector& inputs, - InternalKey* smallest, - InternalKey* largest); - - void GetRange2(const std::vector& inputs1, - const std::vector& inputs2, - InternalKey* smallest, - InternalKey* largest); - - void SetupOtherInputs(Compaction* c); - - // Save current contents to *log - Status WriteSnapshot(log::Writer* log); - - void AppendVersion(Version* v); - - Env* const env_; - const std::string dbname_; - const Options* const options_; - TableCache* const table_cache_; - const InternalKeyComparator icmp_; - uint64_t next_file_number_; - uint64_t manifest_file_number_; - uint64_t last_sequence_; - uint64_t log_number_; - uint64_t prev_log_number_; // 0 or backing store for memtable being compacted - - // Opened lazily - WritableFile* descriptor_file_; - log::Writer* descriptor_log_; - Version dummy_versions_; // Head of circular doubly-linked list of versions. - Version* current_; // == dummy_versions_.prev_ - - // Per-level key at which the next compaction at that level should start. - // Either an empty string, or a valid InternalKey. - std::string compact_pointer_[config::kNumLevels]; - - // No copying allowed - VersionSet(const VersionSet&); - void operator=(const VersionSet&); -}; - -// A Compaction encapsulates information about a compaction. -class Compaction { - public: - ~Compaction(); - - // Return the level that is being compacted. Inputs from "level" - // and "level+1" will be merged to produce a set of "level+1" files. - int level() const { return level_; } - - // Return the object that holds the edits to the descriptor done - // by this compaction. - VersionEdit* edit() { return &edit_; } - - // "which" must be either 0 or 1 - int num_input_files(int which) const { return inputs_[which].size(); } - - // Return the ith input file at "level()+which" ("which" must be 0 or 1). - FileMetaData* input(int which, int i) const { return inputs_[which][i]; } - - // Maximum size of files to build during this compaction. - uint64_t MaxOutputFileSize() const { return max_output_file_size_; } - - // Is this a trivial compaction that can be implemented by just - // moving a single input file to the next level (no merging or splitting) - bool IsTrivialMove() const; - - // Add all inputs to this compaction as delete operations to *edit. - void AddInputDeletions(VersionEdit* edit); - - // Returns true if the information we have available guarantees that - // the compaction is producing data in "level+1" for which no data exists - // in levels greater than "level+1". - bool IsBaseLevelForKey(const Slice& user_key); - - // Returns true iff we should stop building the current output - // before processing "internal_key". - bool ShouldStopBefore(const Slice& internal_key); - - // Release the input version for the compaction, once the compaction - // is successful. - void ReleaseInputs(); - - private: - friend class Version; - friend class VersionSet; - - explicit Compaction(int level); - - int level_; - uint64_t max_output_file_size_; - Version* input_version_; - VersionEdit edit_; - - // Each compaction reads inputs from "level_" and "level_+1" - std::vector inputs_[2]; // The two sets of inputs - - // State used to check for number of of overlapping grandparent files - // (parent == level_ + 1, grandparent == level_ + 2) - std::vector grandparents_; - size_t grandparent_index_; // Index in grandparent_starts_ - bool seen_key_; // Some output key has been seen - int64_t overlapped_bytes_; // Bytes of overlap between current output - // and grandparent files - - // State for implementing IsBaseLevelForKey - - // level_ptrs_ holds indices into input_version_->levels_: our state - // is that we are positioned at one of the file ranges for each - // higher level than the ones involved in this compaction (i.e. for - // all L >= level_ + 2). - size_t level_ptrs_[config::kNumLevels]; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/src/leveldb/db/version_set_test.cc b/src/leveldb/db/version_set_test.cc deleted file mode 100644 index 501e34d133..0000000000 --- a/src/leveldb/db/version_set_test.cc +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "db/version_set.h" -#include "util/logging.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -class FindFileTest { - public: - std::vector files_; - bool disjoint_sorted_files_; - - FindFileTest() : disjoint_sorted_files_(true) { } - - ~FindFileTest() { - for (int i = 0; i < files_.size(); i++) { - delete files_[i]; - } - } - - void Add(const char* smallest, const char* largest, - SequenceNumber smallest_seq = 100, - SequenceNumber largest_seq = 100) { - FileMetaData* f = new FileMetaData; - f->number = files_.size() + 1; - f->smallest = InternalKey(smallest, smallest_seq, kTypeValue); - f->largest = InternalKey(largest, largest_seq, kTypeValue); - files_.push_back(f); - } - - int Find(const char* key) { - InternalKey target(key, 100, kTypeValue); - InternalKeyComparator cmp(BytewiseComparator()); - return FindFile(cmp, files_, target.Encode()); - } - - bool Overlaps(const char* smallest, const char* largest) { - InternalKeyComparator cmp(BytewiseComparator()); - Slice s(smallest != NULL ? smallest : ""); - Slice l(largest != NULL ? largest : ""); - return SomeFileOverlapsRange(cmp, disjoint_sorted_files_, files_, - (smallest != NULL ? &s : NULL), - (largest != NULL ? &l : NULL)); - } -}; - -TEST(FindFileTest, Empty) { - ASSERT_EQ(0, Find("foo")); - ASSERT_TRUE(! Overlaps("a", "z")); - ASSERT_TRUE(! Overlaps(NULL, "z")); - ASSERT_TRUE(! Overlaps("a", NULL)); - ASSERT_TRUE(! Overlaps(NULL, NULL)); -} - -TEST(FindFileTest, Single) { - Add("p", "q"); - ASSERT_EQ(0, Find("a")); - ASSERT_EQ(0, Find("p")); - ASSERT_EQ(0, Find("p1")); - ASSERT_EQ(0, Find("q")); - ASSERT_EQ(1, Find("q1")); - ASSERT_EQ(1, Find("z")); - - ASSERT_TRUE(! Overlaps("a", "b")); - ASSERT_TRUE(! Overlaps("z1", "z2")); - ASSERT_TRUE(Overlaps("a", "p")); - ASSERT_TRUE(Overlaps("a", "q")); - ASSERT_TRUE(Overlaps("a", "z")); - ASSERT_TRUE(Overlaps("p", "p1")); - ASSERT_TRUE(Overlaps("p", "q")); - ASSERT_TRUE(Overlaps("p", "z")); - ASSERT_TRUE(Overlaps("p1", "p2")); - ASSERT_TRUE(Overlaps("p1", "z")); - ASSERT_TRUE(Overlaps("q", "q")); - ASSERT_TRUE(Overlaps("q", "q1")); - - ASSERT_TRUE(! Overlaps(NULL, "j")); - ASSERT_TRUE(! Overlaps("r", NULL)); - ASSERT_TRUE(Overlaps(NULL, "p")); - ASSERT_TRUE(Overlaps(NULL, "p1")); - ASSERT_TRUE(Overlaps("q", NULL)); - ASSERT_TRUE(Overlaps(NULL, NULL)); -} - - -TEST(FindFileTest, Multiple) { - Add("150", "200"); - Add("200", "250"); - Add("300", "350"); - Add("400", "450"); - ASSERT_EQ(0, Find("100")); - ASSERT_EQ(0, Find("150")); - ASSERT_EQ(0, Find("151")); - ASSERT_EQ(0, Find("199")); - ASSERT_EQ(0, Find("200")); - ASSERT_EQ(1, Find("201")); - ASSERT_EQ(1, Find("249")); - ASSERT_EQ(1, Find("250")); - ASSERT_EQ(2, Find("251")); - ASSERT_EQ(2, Find("299")); - ASSERT_EQ(2, Find("300")); - ASSERT_EQ(2, Find("349")); - ASSERT_EQ(2, Find("350")); - ASSERT_EQ(3, Find("351")); - ASSERT_EQ(3, Find("400")); - ASSERT_EQ(3, Find("450")); - ASSERT_EQ(4, Find("451")); - - ASSERT_TRUE(! Overlaps("100", "149")); - ASSERT_TRUE(! Overlaps("251", "299")); - ASSERT_TRUE(! Overlaps("451", "500")); - ASSERT_TRUE(! Overlaps("351", "399")); - - ASSERT_TRUE(Overlaps("100", "150")); - ASSERT_TRUE(Overlaps("100", "200")); - ASSERT_TRUE(Overlaps("100", "300")); - ASSERT_TRUE(Overlaps("100", "400")); - ASSERT_TRUE(Overlaps("100", "500")); - ASSERT_TRUE(Overlaps("375", "400")); - ASSERT_TRUE(Overlaps("450", "450")); - ASSERT_TRUE(Overlaps("450", "500")); -} - -TEST(FindFileTest, MultipleNullBoundaries) { - Add("150", "200"); - Add("200", "250"); - Add("300", "350"); - Add("400", "450"); - ASSERT_TRUE(! Overlaps(NULL, "149")); - ASSERT_TRUE(! Overlaps("451", NULL)); - ASSERT_TRUE(Overlaps(NULL, NULL)); - ASSERT_TRUE(Overlaps(NULL, "150")); - ASSERT_TRUE(Overlaps(NULL, "199")); - ASSERT_TRUE(Overlaps(NULL, "200")); - ASSERT_TRUE(Overlaps(NULL, "201")); - ASSERT_TRUE(Overlaps(NULL, "400")); - ASSERT_TRUE(Overlaps(NULL, "800")); - ASSERT_TRUE(Overlaps("100", NULL)); - ASSERT_TRUE(Overlaps("200", NULL)); - ASSERT_TRUE(Overlaps("449", NULL)); - ASSERT_TRUE(Overlaps("450", NULL)); -} - -TEST(FindFileTest, OverlapSequenceChecks) { - Add("200", "200", 5000, 3000); - ASSERT_TRUE(! Overlaps("199", "199")); - ASSERT_TRUE(! Overlaps("201", "300")); - ASSERT_TRUE(Overlaps("200", "200")); - ASSERT_TRUE(Overlaps("190", "200")); - ASSERT_TRUE(Overlaps("200", "210")); -} - -TEST(FindFileTest, OverlappingFiles) { - Add("150", "600"); - Add("400", "500"); - disjoint_sorted_files_ = false; - ASSERT_TRUE(! Overlaps("100", "149")); - ASSERT_TRUE(! Overlaps("601", "700")); - ASSERT_TRUE(Overlaps("100", "150")); - ASSERT_TRUE(Overlaps("100", "200")); - ASSERT_TRUE(Overlaps("100", "300")); - ASSERT_TRUE(Overlaps("100", "400")); - ASSERT_TRUE(Overlaps("100", "500")); - ASSERT_TRUE(Overlaps("375", "400")); - ASSERT_TRUE(Overlaps("450", "450")); - ASSERT_TRUE(Overlaps("450", "500")); - ASSERT_TRUE(Overlaps("450", "700")); - ASSERT_TRUE(Overlaps("600", "700")); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/db/write_batch.cc b/src/leveldb/db/write_batch.cc deleted file mode 100644 index 33f4a4257e..0000000000 --- a/src/leveldb/db/write_batch.cc +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// WriteBatch::rep_ := -// sequence: fixed64 -// count: fixed32 -// data: record[count] -// record := -// kTypeValue varstring varstring | -// kTypeDeletion varstring -// varstring := -// len: varint32 -// data: uint8[len] - -#include "leveldb/write_batch.h" - -#include "leveldb/db.h" -#include "db/dbformat.h" -#include "db/memtable.h" -#include "db/write_batch_internal.h" -#include "util/coding.h" - -namespace leveldb { - -// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. -static const size_t kHeader = 12; - -WriteBatch::WriteBatch() { - Clear(); -} - -WriteBatch::~WriteBatch() { } - -WriteBatch::Handler::~Handler() { } - -void WriteBatch::Clear() { - rep_.clear(); - rep_.resize(kHeader); -} - -Status WriteBatch::Iterate(Handler* handler) const { - Slice input(rep_); - if (input.size() < kHeader) { - return Status::Corruption("malformed WriteBatch (too small)"); - } - - input.remove_prefix(kHeader); - Slice key, value; - int found = 0; - while (!input.empty()) { - found++; - char tag = input[0]; - input.remove_prefix(1); - switch (tag) { - case kTypeValue: - if (GetLengthPrefixedSlice(&input, &key) && - GetLengthPrefixedSlice(&input, &value)) { - handler->Put(key, value); - } else { - return Status::Corruption("bad WriteBatch Put"); - } - break; - case kTypeDeletion: - if (GetLengthPrefixedSlice(&input, &key)) { - handler->Delete(key); - } else { - return Status::Corruption("bad WriteBatch Delete"); - } - break; - default: - return Status::Corruption("unknown WriteBatch tag"); - } - } - if (found != WriteBatchInternal::Count(this)) { - return Status::Corruption("WriteBatch has wrong count"); - } else { - return Status::OK(); - } -} - -int WriteBatchInternal::Count(const WriteBatch* b) { - return DecodeFixed32(b->rep_.data() + 8); -} - -void WriteBatchInternal::SetCount(WriteBatch* b, int n) { - EncodeFixed32(&b->rep_[8], n); -} - -SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { - return SequenceNumber(DecodeFixed64(b->rep_.data())); -} - -void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { - EncodeFixed64(&b->rep_[0], seq); -} - -void WriteBatch::Put(const Slice& key, const Slice& value) { - WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); - rep_.push_back(static_cast(kTypeValue)); - PutLengthPrefixedSlice(&rep_, key); - PutLengthPrefixedSlice(&rep_, value); -} - -void WriteBatch::Delete(const Slice& key) { - WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); - rep_.push_back(static_cast(kTypeDeletion)); - PutLengthPrefixedSlice(&rep_, key); -} - -namespace { -class MemTableInserter : public WriteBatch::Handler { - public: - SequenceNumber sequence_; - MemTable* mem_; - - virtual void Put(const Slice& key, const Slice& value) { - mem_->Add(sequence_, kTypeValue, key, value); - sequence_++; - } - virtual void Delete(const Slice& key) { - mem_->Add(sequence_, kTypeDeletion, key, Slice()); - sequence_++; - } -}; -} // namespace - -Status WriteBatchInternal::InsertInto(const WriteBatch* b, - MemTable* memtable) { - MemTableInserter inserter; - inserter.sequence_ = WriteBatchInternal::Sequence(b); - inserter.mem_ = memtable; - return b->Iterate(&inserter); -} - -void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { - assert(contents.size() >= kHeader); - b->rep_.assign(contents.data(), contents.size()); -} - -void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { - SetCount(dst, Count(dst) + Count(src)); - assert(src->rep_.size() >= kHeader); - dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); -} - -} // namespace leveldb diff --git a/src/leveldb/db/write_batch_internal.h b/src/leveldb/db/write_batch_internal.h deleted file mode 100644 index 310a3c8912..0000000000 --- a/src/leveldb/db/write_batch_internal.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ -#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ - -#include "leveldb/write_batch.h" - -namespace leveldb { - -class MemTable; - -// WriteBatchInternal provides static methods for manipulating a -// WriteBatch that we don't want in the public WriteBatch interface. -class WriteBatchInternal { - public: - // Return the number of entries in the batch. - static int Count(const WriteBatch* batch); - - // Set the count for the number of entries in the batch. - static void SetCount(WriteBatch* batch, int n); - - // Return the sequence number for the start of this batch. - static SequenceNumber Sequence(const WriteBatch* batch); - - // Store the specified number as the sequence number for the start of - // this batch. - static void SetSequence(WriteBatch* batch, SequenceNumber seq); - - static Slice Contents(const WriteBatch* batch) { - return Slice(batch->rep_); - } - - static size_t ByteSize(const WriteBatch* batch) { - return batch->rep_.size(); - } - - static void SetContents(WriteBatch* batch, const Slice& contents); - - static Status InsertInto(const WriteBatch* batch, MemTable* memtable); - - static void Append(WriteBatch* dst, const WriteBatch* src); -}; - -} // namespace leveldb - - -#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/src/leveldb/db/write_batch_test.cc b/src/leveldb/db/write_batch_test.cc deleted file mode 100644 index 9064e3d85e..0000000000 --- a/src/leveldb/db/write_batch_test.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/db.h" - -#include "db/memtable.h" -#include "db/write_batch_internal.h" -#include "leveldb/env.h" -#include "util/logging.h" -#include "util/testharness.h" - -namespace leveldb { - -static std::string PrintContents(WriteBatch* b) { - InternalKeyComparator cmp(BytewiseComparator()); - MemTable* mem = new MemTable(cmp); - mem->Ref(); - std::string state; - Status s = WriteBatchInternal::InsertInto(b, mem); - int count = 0; - Iterator* iter = mem->NewIterator(); - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - ParsedInternalKey ikey; - ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey)); - switch (ikey.type) { - case kTypeValue: - state.append("Put("); - state.append(ikey.user_key.ToString()); - state.append(", "); - state.append(iter->value().ToString()); - state.append(")"); - count++; - break; - case kTypeDeletion: - state.append("Delete("); - state.append(ikey.user_key.ToString()); - state.append(")"); - count++; - break; - } - state.append("@"); - state.append(NumberToString(ikey.sequence)); - } - delete iter; - if (!s.ok()) { - state.append("ParseError()"); - } else if (count != WriteBatchInternal::Count(b)) { - state.append("CountMismatch()"); - } - mem->Unref(); - return state; -} - -class WriteBatchTest { }; - -TEST(WriteBatchTest, Empty) { - WriteBatch batch; - ASSERT_EQ("", PrintContents(&batch)); - ASSERT_EQ(0, WriteBatchInternal::Count(&batch)); -} - -TEST(WriteBatchTest, Multiple) { - WriteBatch batch; - batch.Put(Slice("foo"), Slice("bar")); - batch.Delete(Slice("box")); - batch.Put(Slice("baz"), Slice("boo")); - WriteBatchInternal::SetSequence(&batch, 100); - ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch)); - ASSERT_EQ(3, WriteBatchInternal::Count(&batch)); - ASSERT_EQ("Put(baz, boo)@102" - "Delete(box)@101" - "Put(foo, bar)@100", - PrintContents(&batch)); -} - -TEST(WriteBatchTest, Corruption) { - WriteBatch batch; - batch.Put(Slice("foo"), Slice("bar")); - batch.Delete(Slice("box")); - WriteBatchInternal::SetSequence(&batch, 200); - Slice contents = WriteBatchInternal::Contents(&batch); - WriteBatchInternal::SetContents(&batch, - Slice(contents.data(),contents.size()-1)); - ASSERT_EQ("Put(foo, bar)@200" - "ParseError()", - PrintContents(&batch)); -} - -TEST(WriteBatchTest, Append) { - WriteBatch b1, b2; - WriteBatchInternal::SetSequence(&b1, 200); - WriteBatchInternal::SetSequence(&b2, 300); - WriteBatchInternal::Append(&b1, &b2); - ASSERT_EQ("", - PrintContents(&b1)); - b2.Put("a", "va"); - WriteBatchInternal::Append(&b1, &b2); - ASSERT_EQ("Put(a, va)@200", - PrintContents(&b1)); - b2.Clear(); - b2.Put("b", "vb"); - WriteBatchInternal::Append(&b1, &b2); - ASSERT_EQ("Put(a, va)@200" - "Put(b, vb)@201", - PrintContents(&b1)); - b2.Delete("foo"); - WriteBatchInternal::Append(&b1, &b2); - ASSERT_EQ("Put(a, va)@200" - "Put(b, vb)@202" - "Put(b, vb)@201" - "Delete(foo)@203", - PrintContents(&b1)); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/doc/bench/db_bench_sqlite3.cc b/src/leveldb/doc/bench/db_bench_sqlite3.cc deleted file mode 100644 index e63aaa8dcc..0000000000 --- a/src/leveldb/doc/bench/db_bench_sqlite3.cc +++ /dev/null @@ -1,718 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include -#include "util/histogram.h" -#include "util/random.h" -#include "util/testutil.h" - -// Comma-separated list of operations to run in the specified order -// Actual benchmarks: -// -// fillseq -- write N values in sequential key order in async mode -// fillseqsync -- write N/100 values in sequential key order in sync mode -// fillseqbatch -- batch write N values in sequential key order in async mode -// fillrandom -- write N values in random key order in async mode -// fillrandsync -- write N/100 values in random key order in sync mode -// fillrandbatch -- batch write N values in sequential key order in async mode -// overwrite -- overwrite N values in random key order in async mode -// fillrand100K -- write N/1000 100K values in random order in async mode -// fillseq100K -- write N/1000 100K values in sequential order in async mode -// readseq -- read N times sequentially -// readrandom -- read N times in random order -// readrand100K -- read N/1000 100K values in sequential order in async mode -static const char* FLAGS_benchmarks = - "fillseq," - "fillseqsync," - "fillseqbatch," - "fillrandom," - "fillrandsync," - "fillrandbatch," - "overwrite," - "overwritebatch," - "readrandom," - "readseq," - "fillrand100K," - "fillseq100K," - "readseq," - "readrand100K," - ; - -// Number of key/values to place in database -static int FLAGS_num = 1000000; - -// Number of read operations to do. If negative, do FLAGS_num reads. -static int FLAGS_reads = -1; - -// Size of each value -static int FLAGS_value_size = 100; - -// Print histogram of operation timings -static bool FLAGS_histogram = false; - -// Arrange to generate values that shrink to this fraction of -// their original size after compression -static double FLAGS_compression_ratio = 0.5; - -// Page size. Default 1 KB. -static int FLAGS_page_size = 1024; - -// Number of pages. -// Default cache size = FLAGS_page_size * FLAGS_num_pages = 4 MB. -static int FLAGS_num_pages = 4096; - -// If true, do not destroy the existing database. If you set this -// flag and also specify a benchmark that wants a fresh database, that -// benchmark will fail. -static bool FLAGS_use_existing_db = false; - -// If true, we allow batch writes to occur -static bool FLAGS_transaction = true; - -// If true, we enable Write-Ahead Logging -static bool FLAGS_WAL_enabled = true; - -// Use the db with the following name. -static const char* FLAGS_db = NULL; - -inline -static void ExecErrorCheck(int status, char *err_msg) { - if (status != SQLITE_OK) { - fprintf(stderr, "SQL error: %s\n", err_msg); - sqlite3_free(err_msg); - exit(1); - } -} - -inline -static void StepErrorCheck(int status) { - if (status != SQLITE_DONE) { - fprintf(stderr, "SQL step error: status = %d\n", status); - exit(1); - } -} - -inline -static void ErrorCheck(int status) { - if (status != SQLITE_OK) { - fprintf(stderr, "sqlite3 error: status = %d\n", status); - exit(1); - } -} - -inline -static void WalCheckpoint(sqlite3* db_) { - // Flush all writes to disk - if (FLAGS_WAL_enabled) { - sqlite3_wal_checkpoint_v2(db_, NULL, SQLITE_CHECKPOINT_FULL, NULL, NULL); - } -} - -namespace leveldb { - -// Helper for quickly generating random data. -namespace { -class RandomGenerator { - private: - std::string data_; - int pos_; - - public: - RandomGenerator() { - // We use a limited amount of data over and over again and ensure - // that it is larger than the compression window (32KB), and also - // large enough to serve all typical value sizes we want to write. - Random rnd(301); - std::string piece; - while (data_.size() < 1048576) { - // Add a short fragment that is as compressible as specified - // by FLAGS_compression_ratio. - test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); - data_.append(piece); - } - pos_ = 0; - } - - Slice Generate(int len) { - if (pos_ + len > data_.size()) { - pos_ = 0; - assert(len < data_.size()); - } - pos_ += len; - return Slice(data_.data() + pos_ - len, len); - } -}; - -static Slice TrimSpace(Slice s) { - int start = 0; - while (start < s.size() && isspace(s[start])) { - start++; - } - int limit = s.size(); - while (limit > start && isspace(s[limit-1])) { - limit--; - } - return Slice(s.data() + start, limit - start); -} - -} // namespace - -class Benchmark { - private: - sqlite3* db_; - int db_num_; - int num_; - int reads_; - double start_; - double last_op_finish_; - int64_t bytes_; - std::string message_; - Histogram hist_; - RandomGenerator gen_; - Random rand_; - - // State kept for progress messages - int done_; - int next_report_; // When to report next - - void PrintHeader() { - const int kKeySize = 16; - PrintEnvironment(); - fprintf(stdout, "Keys: %d bytes each\n", kKeySize); - fprintf(stdout, "Values: %d bytes each\n", FLAGS_value_size); - fprintf(stdout, "Entries: %d\n", num_); - fprintf(stdout, "RawSize: %.1f MB (estimated)\n", - ((static_cast(kKeySize + FLAGS_value_size) * num_) - / 1048576.0)); - PrintWarnings(); - fprintf(stdout, "------------------------------------------------\n"); - } - - void PrintWarnings() { -#if defined(__GNUC__) && !defined(__OPTIMIZE__) - fprintf(stdout, - "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" - ); -#endif -#ifndef NDEBUG - fprintf(stdout, - "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); -#endif - } - - void PrintEnvironment() { - fprintf(stderr, "SQLite: version %s\n", SQLITE_VERSION); - -#if defined(__linux) - time_t now = time(NULL); - fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline - - FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); - if (cpuinfo != NULL) { - char line[1000]; - int num_cpus = 0; - std::string cpu_type; - std::string cache_size; - while (fgets(line, sizeof(line), cpuinfo) != NULL) { - const char* sep = strchr(line, ':'); - if (sep == NULL) { - continue; - } - Slice key = TrimSpace(Slice(line, sep - 1 - line)); - Slice val = TrimSpace(Slice(sep + 1)); - if (key == "model name") { - ++num_cpus; - cpu_type = val.ToString(); - } else if (key == "cache size") { - cache_size = val.ToString(); - } - } - fclose(cpuinfo); - fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); - fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); - } -#endif - } - - void Start() { - start_ = Env::Default()->NowMicros() * 1e-6; - bytes_ = 0; - message_.clear(); - last_op_finish_ = start_; - hist_.Clear(); - done_ = 0; - next_report_ = 100; - } - - void FinishedSingleOp() { - if (FLAGS_histogram) { - double now = Env::Default()->NowMicros() * 1e-6; - double micros = (now - last_op_finish_) * 1e6; - hist_.Add(micros); - if (micros > 20000) { - fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); - fflush(stderr); - } - last_op_finish_ = now; - } - - done_++; - if (done_ >= next_report_) { - if (next_report_ < 1000) next_report_ += 100; - else if (next_report_ < 5000) next_report_ += 500; - else if (next_report_ < 10000) next_report_ += 1000; - else if (next_report_ < 50000) next_report_ += 5000; - else if (next_report_ < 100000) next_report_ += 10000; - else if (next_report_ < 500000) next_report_ += 50000; - else next_report_ += 100000; - fprintf(stderr, "... finished %d ops%30s\r", done_, ""); - fflush(stderr); - } - } - - void Stop(const Slice& name) { - double finish = Env::Default()->NowMicros() * 1e-6; - - // Pretend at least one op was done in case we are running a benchmark - // that does not call FinishedSingleOp(). - if (done_ < 1) done_ = 1; - - if (bytes_ > 0) { - char rate[100]; - snprintf(rate, sizeof(rate), "%6.1f MB/s", - (bytes_ / 1048576.0) / (finish - start_)); - if (!message_.empty()) { - message_ = std::string(rate) + " " + message_; - } else { - message_ = rate; - } - } - - fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", - name.ToString().c_str(), - (finish - start_) * 1e6 / done_, - (message_.empty() ? "" : " "), - message_.c_str()); - if (FLAGS_histogram) { - fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); - } - fflush(stdout); - } - - public: - enum Order { - SEQUENTIAL, - RANDOM - }; - enum DBState { - FRESH, - EXISTING - }; - - Benchmark() - : db_(NULL), - db_num_(0), - num_(FLAGS_num), - reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), - bytes_(0), - rand_(301) { - std::vector files; - std::string test_dir; - Env::Default()->GetTestDirectory(&test_dir); - Env::Default()->GetChildren(test_dir, &files); - if (!FLAGS_use_existing_db) { - for (int i = 0; i < files.size(); i++) { - if (Slice(files[i]).starts_with("dbbench_sqlite3")) { - std::string file_name(test_dir); - file_name += "/"; - file_name += files[i]; - Env::Default()->DeleteFile(file_name.c_str()); - } - } - } - } - - ~Benchmark() { - int status = sqlite3_close(db_); - ErrorCheck(status); - } - - void Run() { - PrintHeader(); - Open(); - - const char* benchmarks = FLAGS_benchmarks; - while (benchmarks != NULL) { - const char* sep = strchr(benchmarks, ','); - Slice name; - if (sep == NULL) { - name = benchmarks; - benchmarks = NULL; - } else { - name = Slice(benchmarks, sep - benchmarks); - benchmarks = sep + 1; - } - - bytes_ = 0; - Start(); - - bool known = true; - bool write_sync = false; - if (name == Slice("fillseq")) { - Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); - WalCheckpoint(db_); - } else if (name == Slice("fillseqbatch")) { - Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1000); - WalCheckpoint(db_); - } else if (name == Slice("fillrandom")) { - Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); - WalCheckpoint(db_); - } else if (name == Slice("fillrandbatch")) { - Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1000); - WalCheckpoint(db_); - } else if (name == Slice("overwrite")) { - Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); - WalCheckpoint(db_); - } else if (name == Slice("overwritebatch")) { - Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1000); - WalCheckpoint(db_); - } else if (name == Slice("fillrandsync")) { - write_sync = true; - Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); - WalCheckpoint(db_); - } else if (name == Slice("fillseqsync")) { - write_sync = true; - Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); - WalCheckpoint(db_); - } else if (name == Slice("fillrand100K")) { - Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); - WalCheckpoint(db_); - } else if (name == Slice("fillseq100K")) { - Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); - WalCheckpoint(db_); - } else if (name == Slice("readseq")) { - ReadSequential(); - } else if (name == Slice("readrandom")) { - Read(RANDOM, 1); - } else if (name == Slice("readrand100K")) { - int n = reads_; - reads_ /= 1000; - Read(RANDOM, 1); - reads_ = n; - } else { - known = false; - if (name != Slice()) { // No error message for empty name - fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); - } - } - if (known) { - Stop(name); - } - } - } - - void Open() { - assert(db_ == NULL); - - int status; - char file_name[100]; - char* err_msg = NULL; - db_num_++; - - // Open database - std::string tmp_dir; - Env::Default()->GetTestDirectory(&tmp_dir); - snprintf(file_name, sizeof(file_name), - "%s/dbbench_sqlite3-%d.db", - tmp_dir.c_str(), - db_num_); - status = sqlite3_open(file_name, &db_); - if (status) { - fprintf(stderr, "open error: %s\n", sqlite3_errmsg(db_)); - exit(1); - } - - // Change SQLite cache size - char cache_size[100]; - snprintf(cache_size, sizeof(cache_size), "PRAGMA cache_size = %d", - FLAGS_num_pages); - status = sqlite3_exec(db_, cache_size, NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - - // FLAGS_page_size is defaulted to 1024 - if (FLAGS_page_size != 1024) { - char page_size[100]; - snprintf(page_size, sizeof(page_size), "PRAGMA page_size = %d", - FLAGS_page_size); - status = sqlite3_exec(db_, page_size, NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - } - - // Change journal mode to WAL if WAL enabled flag is on - if (FLAGS_WAL_enabled) { - std::string WAL_stmt = "PRAGMA journal_mode = WAL"; - - // LevelDB's default cache size is a combined 4 MB - std::string WAL_checkpoint = "PRAGMA wal_autocheckpoint = 4096"; - status = sqlite3_exec(db_, WAL_stmt.c_str(), NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - status = sqlite3_exec(db_, WAL_checkpoint.c_str(), NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - } - - // Change locking mode to exclusive and create tables/index for database - std::string locking_stmt = "PRAGMA locking_mode = EXCLUSIVE"; - std::string create_stmt = - "CREATE TABLE test (key blob, value blob, PRIMARY KEY(key))"; - std::string stmt_array[] = { locking_stmt, create_stmt }; - int stmt_array_length = sizeof(stmt_array) / sizeof(std::string); - for (int i = 0; i < stmt_array_length; i++) { - status = sqlite3_exec(db_, stmt_array[i].c_str(), NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - } - } - - void Write(bool write_sync, Order order, DBState state, - int num_entries, int value_size, int entries_per_batch) { - // Create new database if state == FRESH - if (state == FRESH) { - if (FLAGS_use_existing_db) { - message_ = "skipping (--use_existing_db is true)"; - return; - } - sqlite3_close(db_); - db_ = NULL; - Open(); - Start(); - } - - if (num_entries != num_) { - char msg[100]; - snprintf(msg, sizeof(msg), "(%d ops)", num_entries); - message_ = msg; - } - - char* err_msg = NULL; - int status; - - sqlite3_stmt *replace_stmt, *begin_trans_stmt, *end_trans_stmt; - std::string replace_str = "REPLACE INTO test (key, value) VALUES (?, ?)"; - std::string begin_trans_str = "BEGIN TRANSACTION;"; - std::string end_trans_str = "END TRANSACTION;"; - - // Check for synchronous flag in options - std::string sync_stmt = (write_sync) ? "PRAGMA synchronous = FULL" : - "PRAGMA synchronous = OFF"; - status = sqlite3_exec(db_, sync_stmt.c_str(), NULL, NULL, &err_msg); - ExecErrorCheck(status, err_msg); - - // Preparing sqlite3 statements - status = sqlite3_prepare_v2(db_, replace_str.c_str(), -1, - &replace_stmt, NULL); - ErrorCheck(status); - status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, - &begin_trans_stmt, NULL); - ErrorCheck(status); - status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, - &end_trans_stmt, NULL); - ErrorCheck(status); - - bool transaction = (entries_per_batch > 1); - for (int i = 0; i < num_entries; i += entries_per_batch) { - // Begin write transaction - if (FLAGS_transaction && transaction) { - status = sqlite3_step(begin_trans_stmt); - StepErrorCheck(status); - status = sqlite3_reset(begin_trans_stmt); - ErrorCheck(status); - } - - // Create and execute SQL statements - for (int j = 0; j < entries_per_batch; j++) { - const char* value = gen_.Generate(value_size).data(); - - // Create values for key-value pair - const int k = (order == SEQUENTIAL) ? i + j : - (rand_.Next() % num_entries); - char key[100]; - snprintf(key, sizeof(key), "%016d", k); - - // Bind KV values into replace_stmt - status = sqlite3_bind_blob(replace_stmt, 1, key, 16, SQLITE_STATIC); - ErrorCheck(status); - status = sqlite3_bind_blob(replace_stmt, 2, value, - value_size, SQLITE_STATIC); - ErrorCheck(status); - - // Execute replace_stmt - bytes_ += value_size + strlen(key); - status = sqlite3_step(replace_stmt); - StepErrorCheck(status); - - // Reset SQLite statement for another use - status = sqlite3_clear_bindings(replace_stmt); - ErrorCheck(status); - status = sqlite3_reset(replace_stmt); - ErrorCheck(status); - - FinishedSingleOp(); - } - - // End write transaction - if (FLAGS_transaction && transaction) { - status = sqlite3_step(end_trans_stmt); - StepErrorCheck(status); - status = sqlite3_reset(end_trans_stmt); - ErrorCheck(status); - } - } - - status = sqlite3_finalize(replace_stmt); - ErrorCheck(status); - status = sqlite3_finalize(begin_trans_stmt); - ErrorCheck(status); - status = sqlite3_finalize(end_trans_stmt); - ErrorCheck(status); - } - - void Read(Order order, int entries_per_batch) { - int status; - sqlite3_stmt *read_stmt, *begin_trans_stmt, *end_trans_stmt; - - std::string read_str = "SELECT * FROM test WHERE key = ?"; - std::string begin_trans_str = "BEGIN TRANSACTION;"; - std::string end_trans_str = "END TRANSACTION;"; - - // Preparing sqlite3 statements - status = sqlite3_prepare_v2(db_, begin_trans_str.c_str(), -1, - &begin_trans_stmt, NULL); - ErrorCheck(status); - status = sqlite3_prepare_v2(db_, end_trans_str.c_str(), -1, - &end_trans_stmt, NULL); - ErrorCheck(status); - status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &read_stmt, NULL); - ErrorCheck(status); - - bool transaction = (entries_per_batch > 1); - for (int i = 0; i < reads_; i += entries_per_batch) { - // Begin read transaction - if (FLAGS_transaction && transaction) { - status = sqlite3_step(begin_trans_stmt); - StepErrorCheck(status); - status = sqlite3_reset(begin_trans_stmt); - ErrorCheck(status); - } - - // Create and execute SQL statements - for (int j = 0; j < entries_per_batch; j++) { - // Create key value - char key[100]; - int k = (order == SEQUENTIAL) ? i + j : (rand_.Next() % reads_); - snprintf(key, sizeof(key), "%016d", k); - - // Bind key value into read_stmt - status = sqlite3_bind_blob(read_stmt, 1, key, 16, SQLITE_STATIC); - ErrorCheck(status); - - // Execute read statement - while ((status = sqlite3_step(read_stmt)) == SQLITE_ROW) {} - StepErrorCheck(status); - - // Reset SQLite statement for another use - status = sqlite3_clear_bindings(read_stmt); - ErrorCheck(status); - status = sqlite3_reset(read_stmt); - ErrorCheck(status); - FinishedSingleOp(); - } - - // End read transaction - if (FLAGS_transaction && transaction) { - status = sqlite3_step(end_trans_stmt); - StepErrorCheck(status); - status = sqlite3_reset(end_trans_stmt); - ErrorCheck(status); - } - } - - status = sqlite3_finalize(read_stmt); - ErrorCheck(status); - status = sqlite3_finalize(begin_trans_stmt); - ErrorCheck(status); - status = sqlite3_finalize(end_trans_stmt); - ErrorCheck(status); - } - - void ReadSequential() { - int status; - sqlite3_stmt *pStmt; - std::string read_str = "SELECT * FROM test ORDER BY key"; - - status = sqlite3_prepare_v2(db_, read_str.c_str(), -1, &pStmt, NULL); - ErrorCheck(status); - for (int i = 0; i < reads_ && SQLITE_ROW == sqlite3_step(pStmt); i++) { - bytes_ += sqlite3_column_bytes(pStmt, 1) + sqlite3_column_bytes(pStmt, 2); - FinishedSingleOp(); - } - - status = sqlite3_finalize(pStmt); - ErrorCheck(status); - } - -}; - -} // namespace leveldb - -int main(int argc, char** argv) { - std::string default_db_path; - for (int i = 1; i < argc; i++) { - double d; - int n; - char junk; - if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { - FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); - } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_histogram = n; - } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { - FLAGS_compression_ratio = d; - } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_use_existing_db = n; - } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { - FLAGS_num = n; - } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { - FLAGS_reads = n; - } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { - FLAGS_value_size = n; - } else if (leveldb::Slice(argv[i]) == leveldb::Slice("--no_transaction")) { - FLAGS_transaction = false; - } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { - FLAGS_page_size = n; - } else if (sscanf(argv[i], "--num_pages=%d%c", &n, &junk) == 1) { - FLAGS_num_pages = n; - } else if (sscanf(argv[i], "--WAL_enabled=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_WAL_enabled = n; - } else if (strncmp(argv[i], "--db=", 5) == 0) { - FLAGS_db = argv[i] + 5; - } else { - fprintf(stderr, "Invalid flag '%s'\n", argv[i]); - exit(1); - } - } - - // Choose a location for the test database if none given with --db= - if (FLAGS_db == NULL) { - leveldb::Env::Default()->GetTestDirectory(&default_db_path); - default_db_path += "/dbbench"; - FLAGS_db = default_db_path.c_str(); - } - - leveldb::Benchmark benchmark; - benchmark.Run(); - return 0; -} diff --git a/src/leveldb/doc/bench/db_bench_tree_db.cc b/src/leveldb/doc/bench/db_bench_tree_db.cc deleted file mode 100644 index 4ca381f11f..0000000000 --- a/src/leveldb/doc/bench/db_bench_tree_db.cc +++ /dev/null @@ -1,528 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include -#include "util/histogram.h" -#include "util/random.h" -#include "util/testutil.h" - -// Comma-separated list of operations to run in the specified order -// Actual benchmarks: -// -// fillseq -- write N values in sequential key order in async mode -// fillrandom -- write N values in random key order in async mode -// overwrite -- overwrite N values in random key order in async mode -// fillseqsync -- write N/100 values in sequential key order in sync mode -// fillrandsync -- write N/100 values in random key order in sync mode -// fillrand100K -- write N/1000 100K values in random order in async mode -// fillseq100K -- write N/1000 100K values in seq order in async mode -// readseq -- read N times sequentially -// readseq100K -- read N/1000 100K values in sequential order in async mode -// readrand100K -- read N/1000 100K values in sequential order in async mode -// readrandom -- read N times in random order -static const char* FLAGS_benchmarks = - "fillseq," - "fillseqsync," - "fillrandsync," - "fillrandom," - "overwrite," - "readrandom," - "readseq," - "fillrand100K," - "fillseq100K," - "readseq100K," - "readrand100K," - ; - -// Number of key/values to place in database -static int FLAGS_num = 1000000; - -// Number of read operations to do. If negative, do FLAGS_num reads. -static int FLAGS_reads = -1; - -// Size of each value -static int FLAGS_value_size = 100; - -// Arrange to generate values that shrink to this fraction of -// their original size after compression -static double FLAGS_compression_ratio = 0.5; - -// Print histogram of operation timings -static bool FLAGS_histogram = false; - -// Cache size. Default 4 MB -static int FLAGS_cache_size = 4194304; - -// Page size. Default 1 KB -static int FLAGS_page_size = 1024; - -// If true, do not destroy the existing database. If you set this -// flag and also specify a benchmark that wants a fresh database, that -// benchmark will fail. -static bool FLAGS_use_existing_db = false; - -// Compression flag. If true, compression is on. If false, compression -// is off. -static bool FLAGS_compression = true; - -// Use the db with the following name. -static const char* FLAGS_db = NULL; - -inline -static void DBSynchronize(kyotocabinet::TreeDB* db_) -{ - // Synchronize will flush writes to disk - if (!db_->synchronize()) { - fprintf(stderr, "synchronize error: %s\n", db_->error().name()); - } -} - -namespace leveldb { - -// Helper for quickly generating random data. -namespace { -class RandomGenerator { - private: - std::string data_; - int pos_; - - public: - RandomGenerator() { - // We use a limited amount of data over and over again and ensure - // that it is larger than the compression window (32KB), and also - // large enough to serve all typical value sizes we want to write. - Random rnd(301); - std::string piece; - while (data_.size() < 1048576) { - // Add a short fragment that is as compressible as specified - // by FLAGS_compression_ratio. - test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece); - data_.append(piece); - } - pos_ = 0; - } - - Slice Generate(int len) { - if (pos_ + len > data_.size()) { - pos_ = 0; - assert(len < data_.size()); - } - pos_ += len; - return Slice(data_.data() + pos_ - len, len); - } -}; - -static Slice TrimSpace(Slice s) { - int start = 0; - while (start < s.size() && isspace(s[start])) { - start++; - } - int limit = s.size(); - while (limit > start && isspace(s[limit-1])) { - limit--; - } - return Slice(s.data() + start, limit - start); -} - -} // namespace - -class Benchmark { - private: - kyotocabinet::TreeDB* db_; - int db_num_; - int num_; - int reads_; - double start_; - double last_op_finish_; - int64_t bytes_; - std::string message_; - Histogram hist_; - RandomGenerator gen_; - Random rand_; - kyotocabinet::LZOCompressor comp_; - - // State kept for progress messages - int done_; - int next_report_; // When to report next - - void PrintHeader() { - const int kKeySize = 16; - PrintEnvironment(); - fprintf(stdout, "Keys: %d bytes each\n", kKeySize); - fprintf(stdout, "Values: %d bytes each (%d bytes after compression)\n", - FLAGS_value_size, - static_cast(FLAGS_value_size * FLAGS_compression_ratio + 0.5)); - fprintf(stdout, "Entries: %d\n", num_); - fprintf(stdout, "RawSize: %.1f MB (estimated)\n", - ((static_cast(kKeySize + FLAGS_value_size) * num_) - / 1048576.0)); - fprintf(stdout, "FileSize: %.1f MB (estimated)\n", - (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_) - / 1048576.0)); - PrintWarnings(); - fprintf(stdout, "------------------------------------------------\n"); - } - - void PrintWarnings() { -#if defined(__GNUC__) && !defined(__OPTIMIZE__) - fprintf(stdout, - "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n" - ); -#endif -#ifndef NDEBUG - fprintf(stdout, - "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n"); -#endif - } - - void PrintEnvironment() { - fprintf(stderr, "Kyoto Cabinet: version %s, lib ver %d, lib rev %d\n", - kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV); - -#if defined(__linux) - time_t now = time(NULL); - fprintf(stderr, "Date: %s", ctime(&now)); // ctime() adds newline - - FILE* cpuinfo = fopen("/proc/cpuinfo", "r"); - if (cpuinfo != NULL) { - char line[1000]; - int num_cpus = 0; - std::string cpu_type; - std::string cache_size; - while (fgets(line, sizeof(line), cpuinfo) != NULL) { - const char* sep = strchr(line, ':'); - if (sep == NULL) { - continue; - } - Slice key = TrimSpace(Slice(line, sep - 1 - line)); - Slice val = TrimSpace(Slice(sep + 1)); - if (key == "model name") { - ++num_cpus; - cpu_type = val.ToString(); - } else if (key == "cache size") { - cache_size = val.ToString(); - } - } - fclose(cpuinfo); - fprintf(stderr, "CPU: %d * %s\n", num_cpus, cpu_type.c_str()); - fprintf(stderr, "CPUCache: %s\n", cache_size.c_str()); - } -#endif - } - - void Start() { - start_ = Env::Default()->NowMicros() * 1e-6; - bytes_ = 0; - message_.clear(); - last_op_finish_ = start_; - hist_.Clear(); - done_ = 0; - next_report_ = 100; - } - - void FinishedSingleOp() { - if (FLAGS_histogram) { - double now = Env::Default()->NowMicros() * 1e-6; - double micros = (now - last_op_finish_) * 1e6; - hist_.Add(micros); - if (micros > 20000) { - fprintf(stderr, "long op: %.1f micros%30s\r", micros, ""); - fflush(stderr); - } - last_op_finish_ = now; - } - - done_++; - if (done_ >= next_report_) { - if (next_report_ < 1000) next_report_ += 100; - else if (next_report_ < 5000) next_report_ += 500; - else if (next_report_ < 10000) next_report_ += 1000; - else if (next_report_ < 50000) next_report_ += 5000; - else if (next_report_ < 100000) next_report_ += 10000; - else if (next_report_ < 500000) next_report_ += 50000; - else next_report_ += 100000; - fprintf(stderr, "... finished %d ops%30s\r", done_, ""); - fflush(stderr); - } - } - - void Stop(const Slice& name) { - double finish = Env::Default()->NowMicros() * 1e-6; - - // Pretend at least one op was done in case we are running a benchmark - // that does not call FinishedSingleOp(). - if (done_ < 1) done_ = 1; - - if (bytes_ > 0) { - char rate[100]; - snprintf(rate, sizeof(rate), "%6.1f MB/s", - (bytes_ / 1048576.0) / (finish - start_)); - if (!message_.empty()) { - message_ = std::string(rate) + " " + message_; - } else { - message_ = rate; - } - } - - fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n", - name.ToString().c_str(), - (finish - start_) * 1e6 / done_, - (message_.empty() ? "" : " "), - message_.c_str()); - if (FLAGS_histogram) { - fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str()); - } - fflush(stdout); - } - - public: - enum Order { - SEQUENTIAL, - RANDOM - }; - enum DBState { - FRESH, - EXISTING - }; - - Benchmark() - : db_(NULL), - num_(FLAGS_num), - reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), - bytes_(0), - rand_(301) { - std::vector files; - std::string test_dir; - Env::Default()->GetTestDirectory(&test_dir); - Env::Default()->GetChildren(test_dir.c_str(), &files); - if (!FLAGS_use_existing_db) { - for (int i = 0; i < files.size(); i++) { - if (Slice(files[i]).starts_with("dbbench_polyDB")) { - std::string file_name(test_dir); - file_name += "/"; - file_name += files[i]; - Env::Default()->DeleteFile(file_name.c_str()); - } - } - } - } - - ~Benchmark() { - if (!db_->close()) { - fprintf(stderr, "close error: %s\n", db_->error().name()); - } - } - - void Run() { - PrintHeader(); - Open(false); - - const char* benchmarks = FLAGS_benchmarks; - while (benchmarks != NULL) { - const char* sep = strchr(benchmarks, ','); - Slice name; - if (sep == NULL) { - name = benchmarks; - benchmarks = NULL; - } else { - name = Slice(benchmarks, sep - benchmarks); - benchmarks = sep + 1; - } - - Start(); - - bool known = true; - bool write_sync = false; - if (name == Slice("fillseq")) { - Write(write_sync, SEQUENTIAL, FRESH, num_, FLAGS_value_size, 1); - DBSynchronize(db_); - } else if (name == Slice("fillrandom")) { - Write(write_sync, RANDOM, FRESH, num_, FLAGS_value_size, 1); - DBSynchronize(db_); - } else if (name == Slice("overwrite")) { - Write(write_sync, RANDOM, EXISTING, num_, FLAGS_value_size, 1); - DBSynchronize(db_); - } else if (name == Slice("fillrandsync")) { - write_sync = true; - Write(write_sync, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1); - DBSynchronize(db_); - } else if (name == Slice("fillseqsync")) { - write_sync = true; - Write(write_sync, SEQUENTIAL, FRESH, num_ / 100, FLAGS_value_size, 1); - DBSynchronize(db_); - } else if (name == Slice("fillrand100K")) { - Write(write_sync, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1); - DBSynchronize(db_); - } else if (name == Slice("fillseq100K")) { - Write(write_sync, SEQUENTIAL, FRESH, num_ / 1000, 100 * 1000, 1); - DBSynchronize(db_); - } else if (name == Slice("readseq")) { - ReadSequential(); - } else if (name == Slice("readrandom")) { - ReadRandom(); - } else if (name == Slice("readrand100K")) { - int n = reads_; - reads_ /= 1000; - ReadRandom(); - reads_ = n; - } else if (name == Slice("readseq100K")) { - int n = reads_; - reads_ /= 1000; - ReadSequential(); - reads_ = n; - } else { - known = false; - if (name != Slice()) { // No error message for empty name - fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str()); - } - } - if (known) { - Stop(name); - } - } - } - - private: - void Open(bool sync) { - assert(db_ == NULL); - - // Initialize db_ - db_ = new kyotocabinet::TreeDB(); - char file_name[100]; - db_num_++; - std::string test_dir; - Env::Default()->GetTestDirectory(&test_dir); - snprintf(file_name, sizeof(file_name), - "%s/dbbench_polyDB-%d.kct", - test_dir.c_str(), - db_num_); - - // Create tuning options and open the database - int open_options = kyotocabinet::PolyDB::OWRITER | - kyotocabinet::PolyDB::OCREATE; - int tune_options = kyotocabinet::TreeDB::TSMALL | - kyotocabinet::TreeDB::TLINEAR; - if (FLAGS_compression) { - tune_options |= kyotocabinet::TreeDB::TCOMPRESS; - db_->tune_compressor(&comp_); - } - db_->tune_options(tune_options); - db_->tune_page_cache(FLAGS_cache_size); - db_->tune_page(FLAGS_page_size); - db_->tune_map(256LL<<20); - if (sync) { - open_options |= kyotocabinet::PolyDB::OAUTOSYNC; - } - if (!db_->open(file_name, open_options)) { - fprintf(stderr, "open error: %s\n", db_->error().name()); - } - } - - void Write(bool sync, Order order, DBState state, - int num_entries, int value_size, int entries_per_batch) { - // Create new database if state == FRESH - if (state == FRESH) { - if (FLAGS_use_existing_db) { - message_ = "skipping (--use_existing_db is true)"; - return; - } - delete db_; - db_ = NULL; - Open(sync); - Start(); // Do not count time taken to destroy/open - } - - if (num_entries != num_) { - char msg[100]; - snprintf(msg, sizeof(msg), "(%d ops)", num_entries); - message_ = msg; - } - - // Write to database - for (int i = 0; i < num_entries; i++) - { - const int k = (order == SEQUENTIAL) ? i : (rand_.Next() % num_entries); - char key[100]; - snprintf(key, sizeof(key), "%016d", k); - bytes_ += value_size + strlen(key); - std::string cpp_key = key; - if (!db_->set(cpp_key, gen_.Generate(value_size).ToString())) { - fprintf(stderr, "set error: %s\n", db_->error().name()); - } - FinishedSingleOp(); - } - } - - void ReadSequential() { - kyotocabinet::DB::Cursor* cur = db_->cursor(); - cur->jump(); - std::string ckey, cvalue; - while (cur->get(&ckey, &cvalue, true)) { - bytes_ += ckey.size() + cvalue.size(); - FinishedSingleOp(); - } - delete cur; - } - - void ReadRandom() { - std::string value; - for (int i = 0; i < reads_; i++) { - char key[100]; - const int k = rand_.Next() % reads_; - snprintf(key, sizeof(key), "%016d", k); - db_->get(key, &value); - FinishedSingleOp(); - } - } -}; - -} // namespace leveldb - -int main(int argc, char** argv) { - std::string default_db_path; - for (int i = 1; i < argc; i++) { - double d; - int n; - char junk; - if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) { - FLAGS_benchmarks = argv[i] + strlen("--benchmarks="); - } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) { - FLAGS_compression_ratio = d; - } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_histogram = n; - } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) { - FLAGS_num = n; - } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) { - FLAGS_reads = n; - } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) { - FLAGS_value_size = n; - } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { - FLAGS_cache_size = n; - } else if (sscanf(argv[i], "--page_size=%d%c", &n, &junk) == 1) { - FLAGS_page_size = n; - } else if (sscanf(argv[i], "--compression=%d%c", &n, &junk) == 1 && - (n == 0 || n == 1)) { - FLAGS_compression = (n == 1) ? true : false; - } else if (strncmp(argv[i], "--db=", 5) == 0) { - FLAGS_db = argv[i] + 5; - } else { - fprintf(stderr, "Invalid flag '%s'\n", argv[i]); - exit(1); - } - } - - // Choose a location for the test database if none given with --db= - if (FLAGS_db == NULL) { - leveldb::Env::Default()->GetTestDirectory(&default_db_path); - default_db_path += "/dbbench"; - FLAGS_db = default_db_path.c_str(); - } - - leveldb::Benchmark benchmark; - benchmark.Run(); - return 0; -} diff --git a/src/leveldb/doc/benchmark.html b/src/leveldb/doc/benchmark.html deleted file mode 100644 index c4639772c1..0000000000 --- a/src/leveldb/doc/benchmark.html +++ /dev/null @@ -1,459 +0,0 @@ - - - -LevelDB Benchmarks - - - - -

LevelDB Benchmarks

-

Google, July 2011

-
- -

In order to test LevelDB's performance, we benchmark it against other well-established database implementations. We compare LevelDB (revision 39) against SQLite3 (version 3.7.6.3) and Kyoto Cabinet's (version 1.2.67) TreeDB (a B+Tree based key-value store). We would like to acknowledge Scott Hess and Mikio Hirabayashi for their suggestions and contributions to the SQLite3 and Kyoto Cabinet benchmarks, respectively.

- -

Benchmarks were all performed on a six-core Intel(R) Xeon(R) CPU X5650 @ 2.67GHz, with 12288 KB of total L3 cache and 12 GB of DDR3 RAM at 1333 MHz. (Note that LevelDB uses at most two CPUs since the benchmarks are single threaded: one to run the benchmark, and one for background compactions.) We ran the benchmarks on two machines (with identical processors), one with an Ext3 file system and one with an Ext4 file system. The machine with the Ext3 file system has a SATA Hitachi HDS721050CLA362 hard drive. The machine with the Ext4 file system has a SATA Samsung HD502HJ hard drive. Both hard drives spin at 7200 RPM and have hard drive write-caching enabled (using `hdparm -W 1 [device]`). The numbers reported below are the median of three measurements.

- -

Benchmark Source Code

-

We wrote benchmark tools for SQLite and Kyoto TreeDB based on LevelDB's db_bench. The code for each of the benchmarks resides here:

- - -

Custom Build Specifications

-
    -
  • LevelDB: LevelDB was compiled with the tcmalloc library and the Snappy compression library (revision 33). Assertions were disabled.
  • -
  • TreeDB: TreeDB was compiled using the LZO compression library (version 2.03). Furthermore, we enabled the TSMALL and TLINEAR options when opening the database in order to reduce the footprint of each record.
  • -
  • SQLite: We tuned SQLite's performance, by setting its locking mode to exclusive. We also enabled SQLite's write-ahead logging.
  • -
- -

1. Baseline Performance

-

This section gives the baseline performance of all the -databases. Following sections show how performance changes as various -parameters are varied. For the baseline:

-
    -
  • Each database is allowed 4 MB of cache memory.
  • -
  • Databases are opened in asynchronous write mode. - (LevelDB's sync option, TreeDB's OAUTOSYNC option, and - SQLite3's synchronous options are all turned off). I.e., - every write is pushed to the operating system, but the - benchmark does not wait for the write to reach the disk.
  • -
  • Keys are 16 bytes each.
  • -
  • Value are 100 bytes each (with enough redundancy so that - a simple compressor shrinks them to 50% of their original - size).
  • -
  • Sequential reads/writes traverse the key space in increasing order.
  • -
  • Random reads/writes traverse the key space in random order.
  • -
- -

A. Sequential Reads

- - - - - - - - - - -
LevelDB4,030,000 ops/sec
 
Kyoto TreeDB1,010,000 ops/sec
 
SQLite3383,000 ops/sec
 
-

B. Random Reads

- - - - - - - - - - -
LevelDB129,000 ops/sec
 
Kyoto TreeDB151,000 ops/sec
 
SQLite3134,000 ops/sec
 
-

C. Sequential Writes

- - - - - - - - - - -
LevelDB779,000 ops/sec
 
Kyoto TreeDB342,000 ops/sec
 
SQLite348,600 ops/sec
 
-

D. Random Writes

- - - - - - - - - - -
LevelDB164,000 ops/sec
 
Kyoto TreeDB88,500 ops/sec
 
SQLite39,860 ops/sec
 
- -

LevelDB outperforms both SQLite3 and TreeDB in sequential and random write operations and sequential read operations. Kyoto Cabinet has the fastest random read operations.

- -

2. Write Performance under Different Configurations

-

A. Large Values

-

For this benchmark, we start with an empty database, and write 100,000 byte values (~50% compressible). To keep the benchmark running time reasonable, we stop after writing 1000 values.

-

Sequential Writes

- - - - - - - - - - -
LevelDB1,100 ops/sec
 
Kyoto TreeDB1,000 ops/sec
 
SQLite31,600 ops/sec
 
-

Random Writes

- - - - - - - - - - -
LevelDB480 ops/sec
 
Kyoto TreeDB1,100 ops/sec
 
SQLite31,600 ops/sec
 
-

LevelDB doesn't perform as well with large values of 100,000 bytes each. This is because LevelDB writes keys and values at least twice: first time to the transaction log, and second time (during a compaction) to a sorted file. -With larger values, LevelDB's per-operation efficiency is swamped by the -cost of extra copies of large values.

-

B. Batch Writes

-

A batch write is a set of writes that are applied atomically to the underlying database. A single batch of N writes may be significantly faster than N individual writes. The following benchmark writes one thousand batches where each batch contains one thousand 100-byte values. TreeDB does not support batch writes and is omitted from this benchmark.

-

Sequential Writes

- - - - - - - - - -
LevelDB840,000 entries/sec
 
(1.08x baseline)
SQLite3124,000 entries/sec
 
(2.55x baseline)
-

Random Writes

- - - - - - - - - -
LevelDB221,000 entries/sec
 
(1.35x baseline)
SQLite322,000 entries/sec
 
(2.23x baseline)
- -

Because of the way LevelDB persistent storage is organized, batches of -random writes are not much slower (only a factor of 4x) than batches -of sequential writes.

- -

C. Synchronous Writes

-

In the following benchmark, we enable the synchronous writing modes -of all of the databases. Since this change significantly slows down the -benchmark, we stop after 10,000 writes. For synchronous write tests, we've -disabled hard drive write-caching (using `hdparm -W 0 [device]`).

-
    -
  • For LevelDB, we set WriteOptions.sync = true.
  • -
  • In TreeDB, we enabled TreeDB's OAUTOSYNC option.
  • -
  • For SQLite3, we set "PRAGMA synchronous = FULL".
  • -
-

Sequential Writes

- - - - - - - - - - - - - -
LevelDB100 ops/sec
 
(0.003x baseline)
Kyoto TreeDB7 ops/sec
 
(0.0004x baseline)
SQLite388 ops/sec
 
(0.002x baseline)
-

Random Writes

- - - - - - - - - - - - - -
LevelDB100 ops/sec
 
(0.015x baseline)
Kyoto TreeDB8 ops/sec
 
(0.001x baseline)
SQLite388 ops/sec
 
(0.009x baseline)
- -

Also see the ext4 performance numbers below -since synchronous writes behave significantly differently -on ext3 and ext4.

- -

D. Turning Compression Off

- -

In the baseline measurements, LevelDB and TreeDB were using -light-weight compression -(Snappy for LevelDB, -and LZO for -TreeDB). SQLite3, by default does not use compression. The -experiments below show what happens when compression is disabled in -all of the databases (the SQLite3 numbers are just a copy of -its baseline measurements):

- -

Sequential Writes

- - - - - - - - - - - - - -
LevelDB594,000 ops/sec
 
(0.76x baseline)
Kyoto TreeDB485,000 ops/sec
 
(1.42x baseline)
SQLite348,600 ops/sec
 
(1.00x baseline)
-

Random Writes

- - - - - - - - - - - - - -
LevelDB135,000 ops/sec
 
(0.82x baseline)
Kyoto TreeDB159,000 ops/sec
 
(1.80x baseline)
SQLite39,860 ops/sec
 
(1.00x baseline)
- -

LevelDB's write performance is better with compression than without -since compression decreases the amount of data that has to be written -to disk. Therefore LevelDB users can leave compression enabled in -most scenarios without having worry about a tradeoff between space -usage and performance. TreeDB's performance on the other hand is -better without compression than with compression. Presumably this is -because TreeDB's compression library (LZO) is more expensive than -LevelDB's compression library (Snappy).

- -

E. Using More Memory

-

We increased the overall cache size for each database to 128 MB. For LevelDB, we partitioned 128 MB into a 120 MB write buffer and 8 MB of cache (up from 2 MB of write buffer and 2 MB of cache). For SQLite3, we kept the page size at 1024 bytes, but increased the number of pages to 131,072 (up from 4096). For TreeDB, we also kept the page size at 1024 bytes, but increased the cache size to 128 MB (up from 4 MB).

-

Sequential Writes

- - - - - - - - - - - - - -
LevelDB812,000 ops/sec
 
(1.04x baseline)
Kyoto TreeDB321,000 ops/sec
 
(0.94x baseline)
SQLite348,500 ops/sec
 
(1.00x baseline)
-

Random Writes

- - - - - - - - - - - - - -
LevelDB355,000 ops/sec
 
(2.16x baseline)
Kyoto TreeDB284,000 ops/sec
 
(3.21x baseline)
SQLite39,670 ops/sec
 
(0.98x baseline)
- -

SQLite's performance does not change substantially when compared to -the baseline, but the random write performance for both LevelDB and -TreeDB increases significantly. LevelDB's performance improves -because a larger write buffer reduces the need to merge sorted files -(since it creates a smaller number of larger sorted files). TreeDB's -performance goes up because the entire database is available in memory -for fast in-place updates.

- -

3. Read Performance under Different Configurations

-

A. Larger Caches

-

We increased the overall memory usage to 128 MB for each database. -For LevelDB, we allocated 8 MB to LevelDB's write buffer and 120 MB -to LevelDB's cache. The other databases don't differentiate between a -write buffer and a cache, so we simply set their cache size to 128 -MB.

-

Sequential Reads

- - - - - - - - - - - - - -
LevelDB5,210,000 ops/sec
 
(1.29x baseline)
Kyoto TreeDB1,070,000 ops/sec
 
(1.06x baseline)
SQLite3609,000 ops/sec
 
(1.59x baseline)
- -

Random Reads

- - - - - - - - - - - - - -
LevelDB190,000 ops/sec
 
(1.47x baseline)
Kyoto TreeDB463,000 ops/sec
 
(3.07x baseline)
SQLite3186,000 ops/sec
 
(1.39x baseline)
- -

As expected, the read performance of all of the databases increases -when the caches are enlarged. In particular, TreeDB seems to make -very effective use of a cache that is large enough to hold the entire -database.

- -

B. No Compression Reads

-

For this benchmark, we populated a database with 1 million entries consisting of 16 byte keys and 100 byte values. We compiled LevelDB and Kyoto Cabinet without compression support, so results that are read out from the database are already uncompressed. We've listed the SQLite3 baseline read performance as a point of comparison.

-

Sequential Reads

- - - - - - - - - - - - - -
LevelDB4,880,000 ops/sec
 
(1.21x baseline)
Kyoto TreeDB1,230,000 ops/sec
 
(3.60x baseline)
SQLite3383,000 ops/sec
 
(1.00x baseline)
-

Random Reads

- - - - - - - - - - - - - -
LevelDB149,000 ops/sec
 
(1.16x baseline)
Kyoto TreeDB175,000 ops/sec
 
(1.16x baseline)
SQLite3134,000 ops/sec
 
(1.00x baseline)
- -

Performance of both LevelDB and TreeDB improves a small amount when -compression is disabled. Note however that under different workloads, -performance may very well be better with compression if it allows more -of the working set to fit in memory.

- -

Note about Ext4 Filesystems

-

The preceding numbers are for an ext3 file system. Synchronous writes are much slower under ext4 (LevelDB drops to ~31 writes / second and TreeDB drops to ~5 writes / second; SQLite3's synchronous writes do not noticeably drop) due to ext4's different handling of fsync / msync calls. Even LevelDB's asynchronous write performance drops somewhat since it spreads its storage across multiple files and issues fsync calls when switching to a new file.

- -

Acknowledgements

-

Jeff Dean and Sanjay Ghemawat wrote LevelDB. Kevin Tseng wrote and compiled these benchmarks. Mikio Hirabayashi, Scott Hess, and Gabor Cselle provided help and advice.

- - diff --git a/src/leveldb/doc/doc.css b/src/leveldb/doc/doc.css deleted file mode 100644 index 700c564e43..0000000000 --- a/src/leveldb/doc/doc.css +++ /dev/null @@ -1,89 +0,0 @@ -body { - margin-left: 0.5in; - margin-right: 0.5in; - background: white; - color: black; -} - -h1 { - margin-left: -0.2in; - font-size: 14pt; -} -h2 { - margin-left: -0in; - font-size: 12pt; -} -h3 { - margin-left: -0in; -} -h4 { - margin-left: -0in; -} -hr { - margin-left: -0in; -} - -/* Definition lists: definition term bold */ -dt { - font-weight: bold; -} - -address { - text-align: center; -} -code,samp,var { - color: blue; -} -kbd { - color: #600000; -} -div.note p { - float: right; - width: 3in; - margin-right: 0%; - padding: 1px; - border: 2px solid #6060a0; - background-color: #fffff0; -} - -ul { - margin-top: -0em; - margin-bottom: -0em; -} - -ol { - margin-top: -0em; - margin-bottom: -0em; -} - -UL.nobullets { - list-style-type: none; - list-style-image: none; - margin-left: -1em; -} - -p { - margin: 1em 0 1em 0; - padding: 0 0 0 0; -} - -pre { - line-height: 1.3em; - padding: 0.4em 0 0.8em 0; - margin: 0 0 0 0; - border: 0 0 0 0; - color: blue; -} - -.datatable { - margin-left: auto; - margin-right: auto; - margin-top: 2em; - margin-bottom: 2em; - border: 1px solid; -} - -.datatable td,th { - padding: 0 0.5em 0 0.5em; - text-align: right; -} diff --git a/src/leveldb/doc/impl.html b/src/leveldb/doc/impl.html deleted file mode 100644 index 6a468be095..0000000000 --- a/src/leveldb/doc/impl.html +++ /dev/null @@ -1,213 +0,0 @@ - - - - -Leveldb file layout and compactions - - - - -

Files

- -The implementation of leveldb is similar in spirit to the -representation of a single - -Bigtable tablet (section 5.3). -However the organization of the files that make up the representation -is somewhat different and is explained below. - -

-Each database is represented by a set of files stored in a directory. -There are several different types of files as documented below: -

-

Log files

-

-A log file (*.log) stores a sequence of recent updates. Each update -is appended to the current log file. When the log file reaches a -pre-determined size (approximately 4MB by default), it is converted -to a sorted table (see below) and a new log file is created for future -updates. -

-A copy of the current log file is kept in an in-memory structure (the -memtable). This copy is consulted on every read so that read -operations reflect all logged updates. -

-

Sorted tables

-

-A sorted table (*.sst) stores a sequence of entries sorted by key. -Each entry is either a value for the key, or a deletion marker for the -key. (Deletion markers are kept around to hide obsolete values -present in older sorted tables). -

-The set of sorted tables are organized into a sequence of levels. The -sorted table generated from a log file is placed in a special young -level (also called level-0). When the number of young files exceeds a -certain threshold (currently four), all of the young files are merged -together with all of the overlapping level-1 files to produce a -sequence of new level-1 files (we create a new level-1 file for every -2MB of data.) -

-Files in the young level may contain overlapping keys. However files -in other levels have distinct non-overlapping key ranges. Consider -level number L where L >= 1. When the combined size of files in -level-L exceeds (10^L) MB (i.e., 10MB for level-1, 100MB for level-2, -...), one file in level-L, and all of the overlapping files in -level-(L+1) are merged to form a set of new files for level-(L+1). -These merges have the effect of gradually migrating new updates from -the young level to the largest level using only bulk reads and writes -(i.e., minimizing expensive seeks). - -

Manifest

-

-A MANIFEST file lists the set of sorted tables that make up each -level, the corresponding key ranges, and other important metadata. -A new MANIFEST file (with a new number embedded in the file name) -is created whenever the database is reopened. The MANIFEST file is -formatted as a log, and changes made to the serving state (as files -are added or removed) are appended to this log. -

-

Current

-

-CURRENT is a simple text file that contains the name of the latest -MANIFEST file. -

-

Info logs

-

-Informational messages are printed to files named LOG and LOG.old. -

-

Others

-

-Other files used for miscellaneous purposes may also be present -(LOCK, *.dbtmp). - -

Level 0

-When the log file grows above a certain size (1MB by default): -
    -
  • Create a brand new memtable and log file and direct future updates here -
  • In the background: -
      -
    • Write the contents of the previous memtable to an sstable -
    • Discard the memtable -
    • Delete the old log file and the old memtable -
    • Add the new sstable to the young (level-0) level. -
    -
- -

Compactions

- -

-When the size of level L exceeds its limit, we compact it in a -background thread. The compaction picks a file from level L and all -overlapping files from the next level L+1. Note that if a level-L -file overlaps only part of a level-(L+1) file, the entire file at -level-(L+1) is used as an input to the compaction and will be -discarded after the compaction. Aside: because level-0 is special -(files in it may overlap each other), we treat compactions from -level-0 to level-1 specially: a level-0 compaction may pick more than -one level-0 file in case some of these files overlap each other. - -

-A compaction merges the contents of the picked files to produce a -sequence of level-(L+1) files. We switch to producing a new -level-(L+1) file after the current output file has reached the target -file size (2MB). We also switch to a new output file when the key -range of the current output file has grown enough to overlap more than -ten level-(L+2) files. This last rule ensures that a later compaction -of a level-(L+1) file will not pick up too much data from level-(L+2). - -

-The old files are discarded and the new files are added to the serving -state. - -

-Compactions for a particular level rotate through the key space. In -more detail, for each level L, we remember the ending key of the last -compaction at level L. The next compaction for level L will pick the -first file that starts after this key (wrapping around to the -beginning of the key space if there is no such file). - -

-Compactions drop overwritten values. They also drop deletion markers -if there are no higher numbered levels that contain a file whose range -overlaps the current key. - -

Timing

- -Level-0 compactions will read up to four 1MB files from level-0, and -at worst all the level-1 files (10MB). I.e., we will read 14MB and -write 14MB. - -

-Other than the special level-0 compactions, we will pick one 2MB file -from level L. In the worst case, this will overlap ~ 12 files from -level L+1 (10 because level-(L+1) is ten times the size of level-L, -and another two at the boundaries since the file ranges at level-L -will usually not be aligned with the file ranges at level-L+1). The -compaction will therefore read 26MB and write 26MB. Assuming a disk -IO rate of 100MB/s (ballpark range for modern drives), the worst -compaction cost will be approximately 0.5 second. - -

-If we throttle the background writing to something small, say 10% of -the full 100MB/s speed, a compaction may take up to 5 seconds. If the -user is writing at 10MB/s, we might build up lots of level-0 files -(~50 to hold the 5*10MB). This may significantly increase the cost of -reads due to the overhead of merging more files together on every -read. - -

-Solution 1: To reduce this problem, we might want to increase the log -switching threshold when the number of level-0 files is large. Though -the downside is that the larger this threshold, the more memory we will -need to hold the corresponding memtable. - -

-Solution 2: We might want to decrease write rate artificially when the -number of level-0 files goes up. - -

-Solution 3: We work on reducing the cost of very wide merges. -Perhaps most of the level-0 files will have their blocks sitting -uncompressed in the cache and we will only need to worry about the -O(N) complexity in the merging iterator. - -

Number of files

- -Instead of always making 2MB files, we could make larger files for -larger levels to reduce the total file count, though at the expense of -more bursty compactions. Alternatively, we could shard the set of -files into multiple directories. - -

-An experiment on an ext3 filesystem on Feb 04, 2011 shows -the following timings to do 100K file opens in directories with -varying number of files: - - - - - -
Files in directoryMicroseconds to open a file
10009
1000010
10000016
-So maybe even the sharding is not necessary on modern filesystems? - -

Recovery

- -
    -
  • Read CURRENT to find name of the latest committed MANIFEST -
  • Read the named MANIFEST file -
  • Clean up stale files -
  • We could open all sstables here, but it is probably better to be lazy... -
  • Convert log chunk to a new level-0 sstable -
  • Start directing new writes to a new log file with recovered sequence# -
- -

Garbage collection of files

- -DeleteObsoleteFiles() is called at the end of every -compaction and at the end of recovery. It finds the names of all -files in the database. It deletes all log files that are not the -current log file. It deletes all table files that are not referenced -from some level and are not the output of an active compaction. - - - diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html deleted file mode 100644 index 3ed0ed9d9e..0000000000 --- a/src/leveldb/doc/index.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - -Leveldb - - - -

Leveldb

-
Jeff Dean, Sanjay Ghemawat
-

-The leveldb library provides a persistent key value store. Keys and -values are arbitrary byte arrays. The keys are ordered within the key -value store according to a user-specified comparator function. - -

-

Opening A Database

-

-A leveldb database has a name which corresponds to a file system -directory. All of the contents of database are stored in this -directory. The following example shows how to open a database, -creating it if necessary: -

-

-  #include <assert>
-  #include "leveldb/db.h"
-
-  leveldb::DB* db;
-  leveldb::Options options;
-  options.create_if_missing = true;
-  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
-  assert(status.ok());
-  ...
-
-If you want to raise an error if the database already exists, add -the following line before the leveldb::DB::Open call: -
-  options.error_if_exists = true;
-
-

Status

-

-You may have noticed the leveldb::Status type above. Values of this -type are returned by most functions in leveldb that may encounter an -error. You can check if such a result is ok, and also print an -associated error message: -

-

-   leveldb::Status s = ...;
-   if (!s.ok()) cerr << s.ToString() << endl;
-
-

Closing A Database

-

-When you are done with a database, just delete the database object. -Example: -

-

-  ... open the db as described above ...
-  ... do something with db ...
-  delete db;
-
-

Reads And Writes

-

-The database provides Put, Delete, and Get methods to -modify/query the database. For example, the following code -moves the value stored under key1 to key2. -

-  std::string value;
-  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
-  if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
-  if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
-
- -

Atomic Updates

-

-Note that if the process dies after the Put of key2 but before the -delete of key1, the same value may be left stored under multiple keys. -Such problems can be avoided by using the WriteBatch class to -atomically apply a set of updates: -

-

-  #include "leveldb/write_batch.h"
-  ...
-  std::string value;
-  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
-  if (s.ok()) {
-    leveldb::WriteBatch batch;
-    batch.Delete(key1);
-    batch.Put(key2, value);
-    s = db->Write(leveldb::WriteOptions(), &batch);
-  }
-
-The WriteBatch holds a sequence of edits to be made to the database, -and these edits within the batch are applied in order. Note that we -called Delete before Put so that if key1 is identical to key2, -we do not end up erroneously dropping the value entirely. -

-Apart from its atomicity benefits, WriteBatch may also be used to -speed up bulk updates by placing lots of individual mutations into the -same batch. - -

Synchronous Writes

-By default, each write to leveldb is asynchronous: it -returns after pushing the write from the process into the operating -system. The transfer from operating system memory to the underlying -persistent storage happens asynchronously. The sync flag -can be turned on for a particular write to make the write operation -not return until the data being written has been pushed all the way to -persistent storage. (On Posix systems, this is implemented by calling -either fsync(...) or fdatasync(...) or -msync(..., MS_SYNC) before the write operation returns.) -
-  leveldb::WriteOptions write_options;
-  write_options.sync = true;
-  db->Put(write_options, ...);
-
-Asynchronous writes are often more than a thousand times as fast as -synchronous writes. The downside of asynchronous writes is that a -crash of the machine may cause the last few updates to be lost. Note -that a crash of just the writing process (i.e., not a reboot) will not -cause any loss since even when sync is false, an update -is pushed from the process memory into the operating system before it -is considered done. - -

-Asynchronous writes can often be used safely. For example, when -loading a large amount of data into the database you can handle lost -updates by restarting the bulk load after a crash. A hybrid scheme is -also possible where every Nth write is synchronous, and in the event -of a crash, the bulk load is restarted just after the last synchronous -write finished by the previous run. (The synchronous write can update -a marker that describes where to restart on a crash.) - -

-WriteBatch provides an alternative to asynchronous writes. -Multiple updates may be placed in the same WriteBatch and -applied together using a synchronous write (i.e., -write_options.sync is set to true). The extra cost of -the synchronous write will be amortized across all of the writes in -the batch. - -

-

Concurrency

-

-A database may only be opened by one process at a time. -The leveldb implementation acquires a lock from the -operating system to prevent misuse. Within a single process, the -same leveldb::DB object may be safely shared by multiple -concurrent threads. I.e., different threads may write into or fetch -iterators or call Get on the same database without any -external synchronization (the leveldb implementation will -automatically do the required synchronization). However other objects -(like Iterator and WriteBatch) may require external synchronization. -If two threads share such an object, they must protect access to it -using their own locking protocol. More details are available in -the public header files. -

-

Iteration

-

-The following example demonstrates how to print all key,value pairs -in a database. -

-

-  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
-  }
-  assert(it->status().ok());  // Check for any errors found during the scan
-  delete it;
-
-The following variation shows how to process just the keys in the -range [start,limit): -

-

-  for (it->Seek(start);
-       it->Valid() && it->key().ToString() < limit;
-       it->Next()) {
-    ...
-  }
-
-You can also process entries in reverse order. (Caveat: reverse -iteration may be somewhat slower than forward iteration.) -

-

-  for (it->SeekToLast(); it->Valid(); it->Prev()) {
-    ...
-  }
-
-

Snapshots

-

-Snapshots provide consistent read-only views over the entire state of -the key-value store. ReadOptions::snapshot may be non-NULL to indicate -that a read should operate on a particular version of the DB state. -If ReadOptions::snapshot is NULL, the read will operate on an -implicit snapshot of the current state. -

-Snapshots are created by the DB::GetSnapshot() method: -

-

-  leveldb::ReadOptions options;
-  options.snapshot = db->GetSnapshot();
-  ... apply some updates to db ...
-  leveldb::Iterator* iter = db->NewIterator(options);
-  ... read using iter to view the state when the snapshot was created ...
-  delete iter;
-  db->ReleaseSnapshot(options.snapshot);
-
-Note that when a snapshot is no longer needed, it should be released -using the DB::ReleaseSnapshot interface. This allows the -implementation to get rid of state that was being maintained just to -support reading as of that snapshot. -

Slice

-

-The return value of the it->key() and it->value() calls above -are instances of the leveldb::Slice type. Slice is a simple -structure that contains a length and a pointer to an external byte -array. Returning a Slice is a cheaper alternative to returning a -std::string since we do not need to copy potentially large keys and -values. In addition, leveldb methods do not return null-terminated -C-style strings since leveldb keys and values are allowed to -contain '\0' bytes. -

-C++ strings and null-terminated C-style strings can be easily converted -to a Slice: -

-

-   leveldb::Slice s1 = "hello";
-
-   std::string str("world");
-   leveldb::Slice s2 = str;
-
-A Slice can be easily converted back to a C++ string: -
-   std::string str = s1.ToString();
-   assert(str == std::string("hello"));
-
-Be careful when using Slices since it is up to the caller to ensure that -the external byte array into which the Slice points remains live while -the Slice is in use. For example, the following is buggy: -

-

-   leveldb::Slice slice;
-   if (...) {
-     std::string str = ...;
-     slice = str;
-   }
-   Use(slice);
-
-When the if statement goes out of scope, str will be destroyed and the -backing storage for slice will disappear. -

-

Comparators

-

-The preceding examples used the default ordering function for key, -which orders bytes lexicographically. You can however supply a custom -comparator when opening a database. For example, suppose each -database key consists of two numbers and we should sort by the first -number, breaking ties by the second number. First, define a proper -subclass of leveldb::Comparator that expresses these rules: -

-

-  class TwoPartComparator : public leveldb::Comparator {
-   public:
-    // Three-way comparison function:
-    //   if a < b: negative result
-    //   if a > b: positive result
-    //   else: zero result
-    int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const {
-      int a1, a2, b1, b2;
-      ParseKey(a, &a1, &a2);
-      ParseKey(b, &b1, &b2);
-      if (a1 < b1) return -1;
-      if (a1 > b1) return +1;
-      if (a2 < b2) return -1;
-      if (a2 > b2) return +1;
-      return 0;
-    }
-
-    // Ignore the following methods for now:
-    const char* Name() const { return "TwoPartComparator"; }
-    void FindShortestSeparator(std::string*, const leveldb::Slice&) const { }
-    void FindShortSuccessor(std::string*) const { }
-  };
-
-Now create a database using this custom comparator: -

-

-  TwoPartComparator cmp;
-  leveldb::DB* db;
-  leveldb::Options options;
-  options.create_if_missing = true;
-  options.comparator = &cmp;
-  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
-  ...
-
-

Backwards compatibility

-

-The result of the comparator's Name method is attached to the -database when it is created, and is checked on every subsequent -database open. If the name changes, the leveldb::DB::Open call will -fail. Therefore, change the name if and only if the new key format -and comparison function are incompatible with existing databases, and -it is ok to discard the contents of all existing databases. -

-You can however still gradually evolve your key format over time with -a little bit of pre-planning. For example, you could store a version -number at the end of each key (one byte should suffice for most uses). -When you wish to switch to a new key format (e.g., adding an optional -third part to the keys processed by TwoPartComparator), -(a) keep the same comparator name (b) increment the version number -for new keys (c) change the comparator function so it uses the -version numbers found in the keys to decide how to interpret them. -

-

Performance

-

-Performance can be tuned by changing the default values of the -types defined in include/leveldb/options.h. - -

-

Block size

-

-leveldb groups adjacent keys together into the same block and such a -block is the unit of transfer to and from persistent storage. The -default block size is approximately 4096 uncompressed bytes. -Applications that mostly do bulk scans over the contents of the -database may wish to increase this size. Applications that do a lot -of point reads of small values may wish to switch to a smaller block -size if performance measurements indicate an improvement. There isn't -much benefit in using blocks smaller than one kilobyte, or larger than -a few megabytes. Also note that compression will be more effective -with larger block sizes. -

-

Compression

-

-Each block is individually compressed before being written to -persistent storage. Compression is on by default since the default -compression method is very fast, and is automatically disabled for -uncompressible data. In rare cases, applications may want to disable -compression entirely, but should only do so if benchmarks show a -performance improvement: -

-

-  leveldb::Options options;
-  options.compression = leveldb::kNoCompression;
-  ... leveldb::DB::Open(options, name, ...) ....
-
-

Cache

-

-The contents of the database are stored in a set of files in the -filesystem and each file stores a sequence of compressed blocks. If -options.cache is non-NULL, it is used to cache frequently used -uncompressed block contents. -

-

-  #include "leveldb/cache.h"
-
-  leveldb::Options options;
-  options.cache = leveldb::NewLRUCache(100 * 1048576);  // 100MB cache
-  leveldb::DB* db;
-  leveldb::DB::Open(options, name, &db);
-  ... use the db ...
-  delete db
-  delete options.cache;
-
-Note that the cache holds uncompressed data, and therefore it should -be sized according to application level data sizes, without any -reduction from compression. (Caching of compressed blocks is left to -the operating system buffer cache, or any custom Env -implementation provided by the client.) -

-When performing a bulk read, the application may wish to disable -caching so that the data processed by the bulk read does not end up -displacing most of the cached contents. A per-iterator option can be -used to achieve this: -

-

-  leveldb::ReadOptions options;
-  options.fill_cache = false;
-  leveldb::Iterator* it = db->NewIterator(options);
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    ...
-  }
-
-

Key Layout

-

-Note that the unit of disk transfer and caching is a block. Adjacent -keys (according to the database sort order) will usually be placed in -the same block. Therefore the application can improve its performance -by placing keys that are accessed together near each other and placing -infrequently used keys in a separate region of the key space. -

-For example, suppose we are implementing a simple file system on top -of leveldb. The types of entries we might wish to store are: -

-

-   filename -> permission-bits, length, list of file_block_ids
-   file_block_id -> data
-
-We might want to prefix filename keys with one letter (say '/') and the -file_block_id keys with a different letter (say '0') so that scans -over just the metadata do not force us to fetch and cache bulky file -contents. -

-

Filters

-

-Because of the way leveldb data is organized on disk, -a single Get() call may involve multiple reads from disk. -The optional FilterPolicy mechanism can be used to reduce -the number of disk reads substantially. -

-   leveldb::Options options;
-   options.filter_policy = NewBloomFilterPolicy(10);
-   leveldb::DB* db;
-   leveldb::DB::Open(options, "/tmp/testdb", &db);
-   ... use the database ...
-   delete db;
-   delete options.filter_policy;
-
-The preceding code associates a -Bloom filter -based filtering policy with the database. Bloom filter based -filtering relies on keeping some number of bits of data in memory per -key (in this case 10 bits per key since that is the argument we passed -to NewBloomFilterPolicy). This filter will reduce the number of unnecessary -disk reads needed for Get() calls by a factor of -approximately a 100. Increasing the bits per key will lead to a -larger reduction at the cost of more memory usage. We recommend that -applications whose working set does not fit in memory and that do a -lot of random reads set a filter policy. -

-If you are using a custom comparator, you should ensure that the filter -policy you are using is compatible with your comparator. For example, -consider a comparator that ignores trailing spaces when comparing keys. -NewBloomFilterPolicy must not be used with such a comparator. -Instead, the application should provide a custom filter policy that -also ignores trailing spaces. For example: -

-  class CustomFilterPolicy : public leveldb::FilterPolicy {
-   private:
-    FilterPolicy* builtin_policy_;
-   public:
-    CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) { }
-    ~CustomFilterPolicy() { delete builtin_policy_; }
-
-    const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
-
-    void CreateFilter(const Slice* keys, int n, std::string* dst) const {
-      // Use builtin bloom filter code after removing trailing spaces
-      std::vector<Slice> trimmed(n);
-      for (int i = 0; i < n; i++) {
-        trimmed[i] = RemoveTrailingSpaces(keys[i]);
-      }
-      return builtin_policy_->CreateFilter(&trimmed[i], n, dst);
-    }
-
-    bool KeyMayMatch(const Slice& key, const Slice& filter) const {
-      // Use builtin bloom filter code after removing trailing spaces
-      return builtin_policy_->KeyMayMatch(RemoveTrailingSpaces(key), filter);
-    }
-  };
-
-

-Advanced applications may provide a filter policy that does not use -a bloom filter but uses some other mechanism for summarizing a set -of keys. See leveldb/filter_policy.h for detail. -

-

Checksums

-

-leveldb associates checksums with all data it stores in the file system. -There are two separate controls provided over how aggressively these -checksums are verified: -

-

    -
  • ReadOptions::verify_checksums may be set to true to force - checksum verification of all data that is read from the file system on - behalf of a particular read. By default, no such verification is - done. -

    -

  • Options::paranoid_checks may be set to true before opening a - database to make the database implementation raise an error as soon as - it detects an internal corruption. Depending on which portion of the - database has been corrupted, the error may be raised when the database - is opened, or later by another database operation. By default, - paranoid checking is off so that the database can be used even if - parts of its persistent storage have been corrupted. -

    - If a database is corrupted (perhaps it cannot be opened when - paranoid checking is turned on), the leveldb::RepairDB function - may be used to recover as much of the data as possible -

    -

-

Approximate Sizes

-

-The GetApproximateSizes method can used to get the approximate -number of bytes of file system space used by one or more key ranges. -

-

-   leveldb::Range ranges[2];
-   ranges[0] = leveldb::Range("a", "c");
-   ranges[1] = leveldb::Range("x", "z");
-   uint64_t sizes[2];
-   leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
-
-The preceding call will set sizes[0] to the approximate number of -bytes of file system space used by the key range [a..c) and -sizes[1] to the approximate number of bytes used by the key range -[x..z). -

-

Environment

-

-All file operations (and other operating system calls) issued by the -leveldb implementation are routed through a leveldb::Env object. -Sophisticated clients may wish to provide their own Env -implementation to get better control. For example, an application may -introduce artificial delays in the file IO paths to limit the impact -of leveldb on other activities in the system. -

-

-  class SlowEnv : public leveldb::Env {
-    .. implementation of the Env interface ...
-  };
-
-  SlowEnv env;
-  leveldb::Options options;
-  options.env = &env;
-  Status s = leveldb::DB::Open(options, ...);
-
-

Porting

-

-leveldb may be ported to a new platform by providing platform -specific implementations of the types/methods/functions exported by -leveldb/port/port.h. See leveldb/port/port_example.h for more -details. -

-In addition, the new platform may need a new default leveldb::Env -implementation. See leveldb/util/env_posix.h for an example. - -

Other Information

- -

-Details about the leveldb implementation may be found in -the following documents: -

- - - diff --git a/src/leveldb/doc/log_format.txt b/src/leveldb/doc/log_format.txt deleted file mode 100644 index 4cca5ef6ea..0000000000 --- a/src/leveldb/doc/log_format.txt +++ /dev/null @@ -1,75 +0,0 @@ -The log file contents are a sequence of 32KB blocks. The only -exception is that the tail of the file may contain a partial block. - -Each block consists of a sequence of records: - block := record* trailer? - record := - checksum: uint32 // crc32c of type and data[] ; little-endian - length: uint16 // little-endian - type: uint8 // One of FULL, FIRST, MIDDLE, LAST - data: uint8[length] - -A record never starts within the last six bytes of a block (since it -won't fit). Any leftover bytes here form the trailer, which must -consist entirely of zero bytes and must be skipped by readers. - -Aside: if exactly seven bytes are left in the current block, and a new -non-zero length record is added, the writer must emit a FIRST record -(which contains zero bytes of user data) to fill up the trailing seven -bytes of the block and then emit all of the user data in subsequent -blocks. - -More types may be added in the future. Some Readers may skip record -types they do not understand, others may report that some data was -skipped. - -FULL == 1 -FIRST == 2 -MIDDLE == 3 -LAST == 4 - -The FULL record contains the contents of an entire user record. - -FIRST, MIDDLE, LAST are types used for user records that have been -split into multiple fragments (typically because of block boundaries). -FIRST is the type of the first fragment of a user record, LAST is the -type of the last fragment of a user record, and MIDDLE is the type of -all interior fragments of a user record. - -Example: consider a sequence of user records: - A: length 1000 - B: length 97270 - C: length 8000 -A will be stored as a FULL record in the first block. - -B will be split into three fragments: first fragment occupies the rest -of the first block, second fragment occupies the entirety of the -second block, and the third fragment occupies a prefix of the third -block. This will leave six bytes free in the third block, which will -be left empty as the trailer. - -C will be stored as a FULL record in the fourth block. - -=================== - -Some benefits over the recordio format: - -(1) We do not need any heuristics for resyncing - just go to next -block boundary and scan. If there is a corruption, skip to the next -block. As a side-benefit, we do not get confused when part of the -contents of one log file are embedded as a record inside another log -file. - -(2) Splitting at approximate boundaries (e.g., for mapreduce) is -simple: find the next block boundary and skip records until we -hit a FULL or FIRST record. - -(3) We do not need extra buffering for large records. - -Some downsides compared to recordio format: - -(1) No packing of tiny records. This could be fixed by adding a new -record type, so it is a shortcoming of the current implementation, -not necessarily the format. - -(2) No compression. Again, this could be fixed by adding new record types. diff --git a/src/leveldb/doc/table_format.txt b/src/leveldb/doc/table_format.txt deleted file mode 100644 index ca8f9b4460..0000000000 --- a/src/leveldb/doc/table_format.txt +++ /dev/null @@ -1,104 +0,0 @@ -File format -=========== - - - [data block 1] - [data block 2] - ... - [data block N] - [meta block 1] - ... - [meta block K] - [metaindex block] - [index block] - [Footer] (fixed size; starts at file_size - sizeof(Footer)) - - -The file contains internal pointers. Each such pointer is called -a BlockHandle and contains the following information: - offset: varint64 - size: varint64 -See https://developers.google.com/protocol-buffers/docs/encoding#varints -for an explanation of varint64 format. - -(1) The sequence of key/value pairs in the file are stored in sorted -order and partitioned into a sequence of data blocks. These blocks -come one after another at the beginning of the file. Each data block -is formatted according to the code in block_builder.cc, and then -optionally compressed. - -(2) After the data blocks we store a bunch of meta blocks. The -supported meta block types are described below. More meta block types -may be added in the future. Each meta block is again formatted using -block_builder.cc and then optionally compressed. - -(3) A "metaindex" block. It contains one entry for every other meta -block where the key is the name of the meta block and the value is a -BlockHandle pointing to that meta block. - -(4) An "index" block. This block contains one entry per data block, -where the key is a string >= last key in that data block and before -the first key in the successive data block. The value is the -BlockHandle for the data block. - -(6) At the very end of the file is a fixed length footer that contains -the BlockHandle of the metaindex and index blocks as well as a magic number. - metaindex_handle: char[p]; // Block handle for metaindex - index_handle: char[q]; // Block handle for index - padding: char[40-p-q]; // zeroed bytes to make fixed length - // (40==2*BlockHandle::kMaxEncodedLength) - magic: fixed64; // == 0xdb4775248b80fb57 (little-endian) - -"filter" Meta Block -------------------- - -If a "FilterPolicy" was specified when the database was opened, a -filter block is stored in each table. The "metaindex" block contains -an entry that maps from "filter." to the BlockHandle for the filter -block where "" is the string returned by the filter policy's -"Name()" method. - -The filter block stores a sequence of filters, where filter i contains -the output of FilterPolicy::CreateFilter() on all keys that are stored -in a block whose file offset falls within the range - - [ i*base ... (i+1)*base-1 ] - -Currently, "base" is 2KB. So for example, if blocks X and Y start in -the range [ 0KB .. 2KB-1 ], all of the keys in X and Y will be -converted to a filter by calling FilterPolicy::CreateFilter(), and the -resulting filter will be stored as the first filter in the filter -block. - -The filter block is formatted as follows: - - [filter 0] - [filter 1] - [filter 2] - ... - [filter N-1] - - [offset of filter 0] : 4 bytes - [offset of filter 1] : 4 bytes - [offset of filter 2] : 4 bytes - ... - [offset of filter N-1] : 4 bytes - - [offset of beginning of offset array] : 4 bytes - lg(base) : 1 byte - -The offset array at the end of the filter block allows efficient -mapping from a data block offset to the corresponding filter. - -"stats" Meta Block ------------------- - -This meta block contains a bunch of stats. The key is the name -of the statistic. The value contains the statistic. -TODO(postrelease): record following stats. - data size - index size - key size (uncompressed) - value size (uncompressed) - number of entries - number of data blocks diff --git a/src/leveldb/helpers/memenv/memenv.cc b/src/leveldb/helpers/memenv/memenv.cc deleted file mode 100644 index 43ef2e0729..0000000000 --- a/src/leveldb/helpers/memenv/memenv.cc +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "helpers/memenv/memenv.h" - -#include "leveldb/env.h" -#include "leveldb/status.h" -#include "port/port.h" -#include "util/mutexlock.h" -#include -#include -#include -#include - -namespace leveldb { - -namespace { - -class FileState { - public: - // FileStates are reference counted. The initial reference count is zero - // and the caller must call Ref() at least once. - FileState() : refs_(0), size_(0) {} - - // Increase the reference count. - void Ref() { - MutexLock lock(&refs_mutex_); - ++refs_; - } - - // Decrease the reference count. Delete if this is the last reference. - void Unref() { - bool do_delete = false; - - { - MutexLock lock(&refs_mutex_); - --refs_; - assert(refs_ >= 0); - if (refs_ <= 0) { - do_delete = true; - } - } - - if (do_delete) { - delete this; - } - } - - uint64_t Size() const { return size_; } - - Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const { - if (offset > size_) { - return Status::IOError("Offset greater than file size."); - } - const uint64_t available = size_ - offset; - if (n > available) { - n = static_cast(available); - } - if (n == 0) { - *result = Slice(); - return Status::OK(); - } - - assert(offset / kBlockSize <= SIZE_MAX); - size_t block = static_cast(offset / kBlockSize); - size_t block_offset = offset % kBlockSize; - - if (n <= kBlockSize - block_offset) { - // The requested bytes are all in the first block. - *result = Slice(blocks_[block] + block_offset, n); - return Status::OK(); - } - - size_t bytes_to_copy = n; - char* dst = scratch; - - while (bytes_to_copy > 0) { - size_t avail = kBlockSize - block_offset; - if (avail > bytes_to_copy) { - avail = bytes_to_copy; - } - memcpy(dst, blocks_[block] + block_offset, avail); - - bytes_to_copy -= avail; - dst += avail; - block++; - block_offset = 0; - } - - *result = Slice(scratch, n); - return Status::OK(); - } - - Status Append(const Slice& data) { - const char* src = data.data(); - size_t src_len = data.size(); - - while (src_len > 0) { - size_t avail; - size_t offset = size_ % kBlockSize; - - if (offset != 0) { - // There is some room in the last block. - avail = kBlockSize - offset; - } else { - // No room in the last block; push new one. - blocks_.push_back(new char[kBlockSize]); - avail = kBlockSize; - } - - if (avail > src_len) { - avail = src_len; - } - memcpy(blocks_.back() + offset, src, avail); - src_len -= avail; - src += avail; - size_ += avail; - } - - return Status::OK(); - } - - private: - // Private since only Unref() should be used to delete it. - ~FileState() { - for (std::vector::iterator i = blocks_.begin(); i != blocks_.end(); - ++i) { - delete [] *i; - } - } - - // No copying allowed. - FileState(const FileState&); - void operator=(const FileState&); - - port::Mutex refs_mutex_; - int refs_; // Protected by refs_mutex_; - - // The following fields are not protected by any mutex. They are only mutable - // while the file is being written, and concurrent access is not allowed - // to writable files. - std::vector blocks_; - uint64_t size_; - - enum { kBlockSize = 8 * 1024 }; -}; - -class SequentialFileImpl : public SequentialFile { - public: - explicit SequentialFileImpl(FileState* file) : file_(file), pos_(0) { - file_->Ref(); - } - - ~SequentialFileImpl() { - file_->Unref(); - } - - virtual Status Read(size_t n, Slice* result, char* scratch) { - Status s = file_->Read(pos_, n, result, scratch); - if (s.ok()) { - pos_ += result->size(); - } - return s; - } - - virtual Status Skip(uint64_t n) { - if (pos_ > file_->Size()) { - return Status::IOError("pos_ > file_->Size()"); - } - const uint64_t available = file_->Size() - pos_; - if (n > available) { - n = available; - } - pos_ += n; - return Status::OK(); - } - - private: - FileState* file_; - uint64_t pos_; -}; - -class RandomAccessFileImpl : public RandomAccessFile { - public: - explicit RandomAccessFileImpl(FileState* file) : file_(file) { - file_->Ref(); - } - - ~RandomAccessFileImpl() { - file_->Unref(); - } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const { - return file_->Read(offset, n, result, scratch); - } - - private: - FileState* file_; -}; - -class WritableFileImpl : public WritableFile { - public: - WritableFileImpl(FileState* file) : file_(file) { - file_->Ref(); - } - - ~WritableFileImpl() { - file_->Unref(); - } - - virtual Status Append(const Slice& data) { - return file_->Append(data); - } - - virtual Status Close() { return Status::OK(); } - virtual Status Flush() { return Status::OK(); } - virtual Status Sync() { return Status::OK(); } - - private: - FileState* file_; -}; - -class NoOpLogger : public Logger { - public: - virtual void Logv(const char* format, va_list ap) { } -}; - -class InMemoryEnv : public EnvWrapper { - public: - explicit InMemoryEnv(Env* base_env) : EnvWrapper(base_env) { } - - virtual ~InMemoryEnv() { - for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ - i->second->Unref(); - } - } - - // Partial implementation of the Env interface. - virtual Status NewSequentialFile(const std::string& fname, - SequentialFile** result) { - MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { - *result = NULL; - return Status::IOError(fname, "File not found"); - } - - *result = new SequentialFileImpl(file_map_[fname]); - return Status::OK(); - } - - virtual Status NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result) { - MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { - *result = NULL; - return Status::IOError(fname, "File not found"); - } - - *result = new RandomAccessFileImpl(file_map_[fname]); - return Status::OK(); - } - - virtual Status NewWritableFile(const std::string& fname, - WritableFile** result) { - MutexLock lock(&mutex_); - if (file_map_.find(fname) != file_map_.end()) { - DeleteFileInternal(fname); - } - - FileState* file = new FileState(); - file->Ref(); - file_map_[fname] = file; - - *result = new WritableFileImpl(file); - return Status::OK(); - } - - virtual bool FileExists(const std::string& fname) { - MutexLock lock(&mutex_); - return file_map_.find(fname) != file_map_.end(); - } - - virtual Status GetChildren(const std::string& dir, - std::vector* result) { - MutexLock lock(&mutex_); - result->clear(); - - for (FileSystem::iterator i = file_map_.begin(); i != file_map_.end(); ++i){ - const std::string& filename = i->first; - - if (filename.size() >= dir.size() + 1 && filename[dir.size()] == '/' && - Slice(filename).starts_with(Slice(dir))) { - result->push_back(filename.substr(dir.size() + 1)); - } - } - - return Status::OK(); - } - - void DeleteFileInternal(const std::string& fname) { - if (file_map_.find(fname) == file_map_.end()) { - return; - } - - file_map_[fname]->Unref(); - file_map_.erase(fname); - } - - virtual Status DeleteFile(const std::string& fname) { - MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { - return Status::IOError(fname, "File not found"); - } - - DeleteFileInternal(fname); - return Status::OK(); - } - - virtual Status CreateDir(const std::string& dirname) { - return Status::OK(); - } - - virtual Status DeleteDir(const std::string& dirname) { - return Status::OK(); - } - - virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) { - MutexLock lock(&mutex_); - if (file_map_.find(fname) == file_map_.end()) { - return Status::IOError(fname, "File not found"); - } - - *file_size = file_map_[fname]->Size(); - return Status::OK(); - } - - virtual Status RenameFile(const std::string& src, - const std::string& target) { - MutexLock lock(&mutex_); - if (file_map_.find(src) == file_map_.end()) { - return Status::IOError(src, "File not found"); - } - - DeleteFileInternal(target); - file_map_[target] = file_map_[src]; - file_map_.erase(src); - return Status::OK(); - } - - virtual Status LockFile(const std::string& fname, FileLock** lock) { - *lock = new FileLock; - return Status::OK(); - } - - virtual Status UnlockFile(FileLock* lock) { - delete lock; - return Status::OK(); - } - - virtual Status GetTestDirectory(std::string* path) { - *path = "/test"; - return Status::OK(); - } - - virtual Status NewLogger(const std::string& fname, Logger** result) { - *result = new NoOpLogger; - return Status::OK(); - } - - private: - // Map from filenames to FileState objects, representing a simple file system. - typedef std::map FileSystem; - port::Mutex mutex_; - FileSystem file_map_; // Protected by mutex_. -}; - -} // namespace - -Env* NewMemEnv(Env* base_env) { - return new InMemoryEnv(base_env); -} - -} // namespace leveldb diff --git a/src/leveldb/helpers/memenv/memenv.h b/src/leveldb/helpers/memenv/memenv.h deleted file mode 100644 index 03b88de761..0000000000 --- a/src/leveldb/helpers/memenv/memenv.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ -#define STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ - -namespace leveldb { - -class Env; - -// Returns a new environment that stores its data in memory and delegates -// all non-file-storage tasks to base_env. The caller must delete the result -// when it is no longer needed. -// *base_env must remain live while the result is in use. -Env* NewMemEnv(Env* base_env); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_ diff --git a/src/leveldb/helpers/memenv/memenv_test.cc b/src/leveldb/helpers/memenv/memenv_test.cc deleted file mode 100644 index a44310fed8..0000000000 --- a/src/leveldb/helpers/memenv/memenv_test.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "helpers/memenv/memenv.h" - -#include "db/db_impl.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "util/testharness.h" -#include -#include - -namespace leveldb { - -class MemEnvTest { - public: - Env* env_; - - MemEnvTest() - : env_(NewMemEnv(Env::Default())) { - } - ~MemEnvTest() { - delete env_; - } -}; - -TEST(MemEnvTest, Basics) { - uint64_t file_size; - WritableFile* writable_file; - std::vector children; - - ASSERT_OK(env_->CreateDir("/dir")); - - // Check that the directory is empty. - ASSERT_TRUE(!env_->FileExists("/dir/non_existent")); - ASSERT_TRUE(!env_->GetFileSize("/dir/non_existent", &file_size).ok()); - ASSERT_OK(env_->GetChildren("/dir", &children)); - ASSERT_EQ(0, children.size()); - - // Create a file. - ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); - delete writable_file; - - // Check that the file exists. - ASSERT_TRUE(env_->FileExists("/dir/f")); - ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); - ASSERT_EQ(0, file_size); - ASSERT_OK(env_->GetChildren("/dir", &children)); - ASSERT_EQ(1, children.size()); - ASSERT_EQ("f", children[0]); - - // Write to the file. - ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); - ASSERT_OK(writable_file->Append("abc")); - delete writable_file; - - // Check for expected size. - ASSERT_OK(env_->GetFileSize("/dir/f", &file_size)); - ASSERT_EQ(3, file_size); - - // Check that renaming works. - ASSERT_TRUE(!env_->RenameFile("/dir/non_existent", "/dir/g").ok()); - ASSERT_OK(env_->RenameFile("/dir/f", "/dir/g")); - ASSERT_TRUE(!env_->FileExists("/dir/f")); - ASSERT_TRUE(env_->FileExists("/dir/g")); - ASSERT_OK(env_->GetFileSize("/dir/g", &file_size)); - ASSERT_EQ(3, file_size); - - // Check that opening non-existent file fails. - SequentialFile* seq_file; - RandomAccessFile* rand_file; - ASSERT_TRUE(!env_->NewSequentialFile("/dir/non_existent", &seq_file).ok()); - ASSERT_TRUE(!seq_file); - ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file).ok()); - ASSERT_TRUE(!rand_file); - - // Check that deleting works. - ASSERT_TRUE(!env_->DeleteFile("/dir/non_existent").ok()); - ASSERT_OK(env_->DeleteFile("/dir/g")); - ASSERT_TRUE(!env_->FileExists("/dir/g")); - ASSERT_OK(env_->GetChildren("/dir", &children)); - ASSERT_EQ(0, children.size()); - ASSERT_OK(env_->DeleteDir("/dir")); -} - -TEST(MemEnvTest, ReadWrite) { - WritableFile* writable_file; - SequentialFile* seq_file; - RandomAccessFile* rand_file; - Slice result; - char scratch[100]; - - ASSERT_OK(env_->CreateDir("/dir")); - - ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); - ASSERT_OK(writable_file->Append("hello ")); - ASSERT_OK(writable_file->Append("world")); - delete writable_file; - - // Read sequentially. - ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); - ASSERT_OK(seq_file->Read(5, &result, scratch)); // Read "hello". - ASSERT_EQ(0, result.compare("hello")); - ASSERT_OK(seq_file->Skip(1)); - ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Read "world". - ASSERT_EQ(0, result.compare("world")); - ASSERT_OK(seq_file->Read(1000, &result, scratch)); // Try reading past EOF. - ASSERT_EQ(0, result.size()); - ASSERT_OK(seq_file->Skip(100)); // Try to skip past end of file. - ASSERT_OK(seq_file->Read(1000, &result, scratch)); - ASSERT_EQ(0, result.size()); - delete seq_file; - - // Random reads. - ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file)); - ASSERT_OK(rand_file->Read(6, 5, &result, scratch)); // Read "world". - ASSERT_EQ(0, result.compare("world")); - ASSERT_OK(rand_file->Read(0, 5, &result, scratch)); // Read "hello". - ASSERT_EQ(0, result.compare("hello")); - ASSERT_OK(rand_file->Read(10, 100, &result, scratch)); // Read "d". - ASSERT_EQ(0, result.compare("d")); - - // Too high offset. - ASSERT_TRUE(!rand_file->Read(1000, 5, &result, scratch).ok()); - delete rand_file; -} - -TEST(MemEnvTest, Locks) { - FileLock* lock; - - // These are no-ops, but we test they return success. - ASSERT_OK(env_->LockFile("some file", &lock)); - ASSERT_OK(env_->UnlockFile(lock)); -} - -TEST(MemEnvTest, Misc) { - std::string test_dir; - ASSERT_OK(env_->GetTestDirectory(&test_dir)); - ASSERT_TRUE(!test_dir.empty()); - - WritableFile* writable_file; - ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file)); - - // These are no-ops, but we test they return success. - ASSERT_OK(writable_file->Sync()); - ASSERT_OK(writable_file->Flush()); - ASSERT_OK(writable_file->Close()); - delete writable_file; -} - -TEST(MemEnvTest, LargeWrite) { - const size_t kWriteSize = 300 * 1024; - char* scratch = new char[kWriteSize * 2]; - - std::string write_data; - for (size_t i = 0; i < kWriteSize; ++i) { - write_data.append(1, static_cast(i)); - } - - WritableFile* writable_file; - ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file)); - ASSERT_OK(writable_file->Append("foo")); - ASSERT_OK(writable_file->Append(write_data)); - delete writable_file; - - SequentialFile* seq_file; - Slice result; - ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file)); - ASSERT_OK(seq_file->Read(3, &result, scratch)); // Read "foo". - ASSERT_EQ(0, result.compare("foo")); - - size_t read = 0; - std::string read_data; - while (read < kWriteSize) { - ASSERT_OK(seq_file->Read(kWriteSize - read, &result, scratch)); - read_data.append(result.data(), result.size()); - read += result.size(); - } - ASSERT_TRUE(write_data == read_data); - delete seq_file; - delete [] scratch; -} - -TEST(MemEnvTest, DBTest) { - Options options; - options.create_if_missing = true; - options.env = env_; - DB* db; - - const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")}; - const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")}; - - ASSERT_OK(DB::Open(options, "/dir/db", &db)); - for (size_t i = 0; i < 3; ++i) { - ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i])); - } - - for (size_t i = 0; i < 3; ++i) { - std::string res; - ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); - ASSERT_TRUE(res == vals[i]); - } - - Iterator* iterator = db->NewIterator(ReadOptions()); - iterator->SeekToFirst(); - for (size_t i = 0; i < 3; ++i) { - ASSERT_TRUE(iterator->Valid()); - ASSERT_TRUE(keys[i] == iterator->key()); - ASSERT_TRUE(vals[i] == iterator->value()); - iterator->Next(); - } - ASSERT_TRUE(!iterator->Valid()); - delete iterator; - - DBImpl* dbi = reinterpret_cast(db); - ASSERT_OK(dbi->TEST_CompactMemTable()); - - for (size_t i = 0; i < 3; ++i) { - std::string res; - ASSERT_OK(db->Get(ReadOptions(), keys[i], &res)); - ASSERT_TRUE(res == vals[i]); - } - - delete db; -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/include/leveldb/c.h b/src/leveldb/include/leveldb/c.h deleted file mode 100644 index 1048fe3b86..0000000000 --- a/src/leveldb/include/leveldb/c.h +++ /dev/null @@ -1,290 +0,0 @@ -/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. See the AUTHORS file for names of contributors. - - C bindings for leveldb. May be useful as a stable ABI that can be - used by programs that keep leveldb in a shared library, or for - a JNI api. - - Does not support: - . getters for the option types - . custom comparators that implement key shortening - . custom iter, db, env, cache implementations using just the C bindings - - Some conventions: - - (1) We expose just opaque struct pointers and functions to clients. - This allows us to change internal representations without having to - recompile clients. - - (2) For simplicity, there is no equivalent to the Slice type. Instead, - the caller has to pass the pointer and length as separate - arguments. - - (3) Errors are represented by a null-terminated c string. NULL - means no error. All operations that can raise an error are passed - a "char** errptr" as the last argument. One of the following must - be true on entry: - *errptr == NULL - *errptr points to a malloc()ed null-terminated error message - (On Windows, *errptr must have been malloc()-ed by this library.) - On success, a leveldb routine leaves *errptr unchanged. - On failure, leveldb frees the old value of *errptr and - set *errptr to a malloc()ed error message. - - (4) Bools have the type unsigned char (0 == false; rest == true) - - (5) All of the pointer arguments must be non-NULL. -*/ - -#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ -#define STORAGE_LEVELDB_INCLUDE_C_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/* Exported types */ - -typedef struct leveldb_t leveldb_t; -typedef struct leveldb_cache_t leveldb_cache_t; -typedef struct leveldb_comparator_t leveldb_comparator_t; -typedef struct leveldb_env_t leveldb_env_t; -typedef struct leveldb_filelock_t leveldb_filelock_t; -typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; -typedef struct leveldb_iterator_t leveldb_iterator_t; -typedef struct leveldb_logger_t leveldb_logger_t; -typedef struct leveldb_options_t leveldb_options_t; -typedef struct leveldb_randomfile_t leveldb_randomfile_t; -typedef struct leveldb_readoptions_t leveldb_readoptions_t; -typedef struct leveldb_seqfile_t leveldb_seqfile_t; -typedef struct leveldb_snapshot_t leveldb_snapshot_t; -typedef struct leveldb_writablefile_t leveldb_writablefile_t; -typedef struct leveldb_writebatch_t leveldb_writebatch_t; -typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; - -/* DB operations */ - -extern leveldb_t* leveldb_open( - const leveldb_options_t* options, - const char* name, - char** errptr); - -extern void leveldb_close(leveldb_t* db); - -extern void leveldb_put( - leveldb_t* db, - const leveldb_writeoptions_t* options, - const char* key, size_t keylen, - const char* val, size_t vallen, - char** errptr); - -extern void leveldb_delete( - leveldb_t* db, - const leveldb_writeoptions_t* options, - const char* key, size_t keylen, - char** errptr); - -extern void leveldb_write( - leveldb_t* db, - const leveldb_writeoptions_t* options, - leveldb_writebatch_t* batch, - char** errptr); - -/* Returns NULL if not found. A malloc()ed array otherwise. - Stores the length of the array in *vallen. */ -extern char* leveldb_get( - leveldb_t* db, - const leveldb_readoptions_t* options, - const char* key, size_t keylen, - size_t* vallen, - char** errptr); - -extern leveldb_iterator_t* leveldb_create_iterator( - leveldb_t* db, - const leveldb_readoptions_t* options); - -extern const leveldb_snapshot_t* leveldb_create_snapshot( - leveldb_t* db); - -extern void leveldb_release_snapshot( - leveldb_t* db, - const leveldb_snapshot_t* snapshot); - -/* Returns NULL if property name is unknown. - Else returns a pointer to a malloc()-ed null-terminated value. */ -extern char* leveldb_property_value( - leveldb_t* db, - const char* propname); - -extern void leveldb_approximate_sizes( - leveldb_t* db, - int num_ranges, - const char* const* range_start_key, const size_t* range_start_key_len, - const char* const* range_limit_key, const size_t* range_limit_key_len, - uint64_t* sizes); - -extern void leveldb_compact_range( - leveldb_t* db, - const char* start_key, size_t start_key_len, - const char* limit_key, size_t limit_key_len); - -/* Management operations */ - -extern void leveldb_destroy_db( - const leveldb_options_t* options, - const char* name, - char** errptr); - -extern void leveldb_repair_db( - const leveldb_options_t* options, - const char* name, - char** errptr); - -/* Iterator */ - -extern void leveldb_iter_destroy(leveldb_iterator_t*); -extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*); -extern void leveldb_iter_seek_to_first(leveldb_iterator_t*); -extern void leveldb_iter_seek_to_last(leveldb_iterator_t*); -extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen); -extern void leveldb_iter_next(leveldb_iterator_t*); -extern void leveldb_iter_prev(leveldb_iterator_t*); -extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen); -extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen); -extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr); - -/* Write batch */ - -extern leveldb_writebatch_t* leveldb_writebatch_create(); -extern void leveldb_writebatch_destroy(leveldb_writebatch_t*); -extern void leveldb_writebatch_clear(leveldb_writebatch_t*); -extern void leveldb_writebatch_put( - leveldb_writebatch_t*, - const char* key, size_t klen, - const char* val, size_t vlen); -extern void leveldb_writebatch_delete( - leveldb_writebatch_t*, - const char* key, size_t klen); -extern void leveldb_writebatch_iterate( - leveldb_writebatch_t*, - void* state, - void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), - void (*deleted)(void*, const char* k, size_t klen)); - -/* Options */ - -extern leveldb_options_t* leveldb_options_create(); -extern void leveldb_options_destroy(leveldb_options_t*); -extern void leveldb_options_set_comparator( - leveldb_options_t*, - leveldb_comparator_t*); -extern void leveldb_options_set_filter_policy( - leveldb_options_t*, - leveldb_filterpolicy_t*); -extern void leveldb_options_set_create_if_missing( - leveldb_options_t*, unsigned char); -extern void leveldb_options_set_error_if_exists( - leveldb_options_t*, unsigned char); -extern void leveldb_options_set_paranoid_checks( - leveldb_options_t*, unsigned char); -extern void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); -extern void leveldb_options_set_info_log(leveldb_options_t*, leveldb_logger_t*); -extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t); -extern void leveldb_options_set_max_open_files(leveldb_options_t*, int); -extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*); -extern void leveldb_options_set_block_size(leveldb_options_t*, size_t); -extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int); - -enum { - leveldb_no_compression = 0, - leveldb_snappy_compression = 1 -}; -extern void leveldb_options_set_compression(leveldb_options_t*, int); - -/* Comparator */ - -extern leveldb_comparator_t* leveldb_comparator_create( - void* state, - void (*destructor)(void*), - int (*compare)( - void*, - const char* a, size_t alen, - const char* b, size_t blen), - const char* (*name)(void*)); -extern void leveldb_comparator_destroy(leveldb_comparator_t*); - -/* Filter policy */ - -extern leveldb_filterpolicy_t* leveldb_filterpolicy_create( - void* state, - void (*destructor)(void*), - char* (*create_filter)( - void*, - const char* const* key_array, const size_t* key_length_array, - int num_keys, - size_t* filter_length), - unsigned char (*key_may_match)( - void*, - const char* key, size_t length, - const char* filter, size_t filter_length), - const char* (*name)(void*)); -extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); - -extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( - int bits_per_key); - -/* Read options */ - -extern leveldb_readoptions_t* leveldb_readoptions_create(); -extern void leveldb_readoptions_destroy(leveldb_readoptions_t*); -extern void leveldb_readoptions_set_verify_checksums( - leveldb_readoptions_t*, - unsigned char); -extern void leveldb_readoptions_set_fill_cache( - leveldb_readoptions_t*, unsigned char); -extern void leveldb_readoptions_set_snapshot( - leveldb_readoptions_t*, - const leveldb_snapshot_t*); - -/* Write options */ - -extern leveldb_writeoptions_t* leveldb_writeoptions_create(); -extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); -extern void leveldb_writeoptions_set_sync( - leveldb_writeoptions_t*, unsigned char); - -/* Cache */ - -extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); -extern void leveldb_cache_destroy(leveldb_cache_t* cache); - -/* Env */ - -extern leveldb_env_t* leveldb_create_default_env(); -extern void leveldb_env_destroy(leveldb_env_t*); - -/* Utility */ - -/* Calls free(ptr). - REQUIRES: ptr was malloc()-ed and returned by one of the routines - in this file. Note that in certain cases (typically on Windows), you - may need to call this routine instead of free(ptr) to dispose of - malloc()-ed memory returned by this library. */ -extern void leveldb_free(void* ptr); - -/* Return the major version number for this release. */ -extern int leveldb_major_version(); - -/* Return the minor version number for this release. */ -extern int leveldb_minor_version(); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/src/leveldb/include/leveldb/cache.h b/src/leveldb/include/leveldb/cache.h deleted file mode 100644 index 1a201e5e0a..0000000000 --- a/src/leveldb/include/leveldb/cache.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// A Cache is an interface that maps keys to values. It has internal -// synchronization and may be safely accessed concurrently from -// multiple threads. It may automatically evict entries to make room -// for new entries. Values have a specified charge against the cache -// capacity. For example, a cache where the values are variable -// length strings, may use the length of the string as the charge for -// the string. -// -// A builtin cache implementation with a least-recently-used eviction -// policy is provided. Clients may use their own implementations if -// they want something more sophisticated (like scan-resistance, a -// custom eviction policy, variable cache sizing, etc.) - -#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ -#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ - -#include -#include "leveldb/slice.h" - -namespace leveldb { - -class Cache; - -// Create a new cache with a fixed size capacity. This implementation -// of Cache uses a least-recently-used eviction policy. -extern Cache* NewLRUCache(size_t capacity); - -class Cache { - public: - Cache() { } - - // Destroys all existing entries by calling the "deleter" - // function that was passed to the constructor. - virtual ~Cache(); - - // Opaque handle to an entry stored in the cache. - struct Handle { }; - - // Insert a mapping from key->value into the cache and assign it - // the specified charge against the total cache capacity. - // - // Returns a handle that corresponds to the mapping. The caller - // must call this->Release(handle) when the returned mapping is no - // longer needed. - // - // When the inserted entry is no longer needed, the key and - // value will be passed to "deleter". - virtual Handle* Insert(const Slice& key, void* value, size_t charge, - void (*deleter)(const Slice& key, void* value)) = 0; - - // If the cache has no mapping for "key", returns NULL. - // - // Else return a handle that corresponds to the mapping. The caller - // must call this->Release(handle) when the returned mapping is no - // longer needed. - virtual Handle* Lookup(const Slice& key) = 0; - - // Release a mapping returned by a previous Lookup(). - // REQUIRES: handle must not have been released yet. - // REQUIRES: handle must have been returned by a method on *this. - virtual void Release(Handle* handle) = 0; - - // Return the value encapsulated in a handle returned by a - // successful Lookup(). - // REQUIRES: handle must not have been released yet. - // REQUIRES: handle must have been returned by a method on *this. - virtual void* Value(Handle* handle) = 0; - - // If the cache contains entry for key, erase it. Note that the - // underlying entry will be kept around until all existing handles - // to it have been released. - virtual void Erase(const Slice& key) = 0; - - // Return a new numeric id. May be used by multiple clients who are - // sharing the same cache to partition the key space. Typically the - // client will allocate a new id at startup and prepend the id to - // its cache keys. - virtual uint64_t NewId() = 0; - - private: - void LRU_Remove(Handle* e); - void LRU_Append(Handle* e); - void Unref(Handle* e); - - struct Rep; - Rep* rep_; - - // No copying allowed - Cache(const Cache&); - void operator=(const Cache&); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_CACHE_H_ diff --git a/src/leveldb/include/leveldb/comparator.h b/src/leveldb/include/leveldb/comparator.h deleted file mode 100644 index 556b984c76..0000000000 --- a/src/leveldb/include/leveldb/comparator.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ -#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ - -#include - -namespace leveldb { - -class Slice; - -// A Comparator object provides a total order across slices that are -// used as keys in an sstable or a database. A Comparator implementation -// must be thread-safe since leveldb may invoke its methods concurrently -// from multiple threads. -class Comparator { - public: - virtual ~Comparator(); - - // Three-way comparison. Returns value: - // < 0 iff "a" < "b", - // == 0 iff "a" == "b", - // > 0 iff "a" > "b" - virtual int Compare(const Slice& a, const Slice& b) const = 0; - - // The name of the comparator. Used to check for comparator - // mismatches (i.e., a DB created with one comparator is - // accessed using a different comparator. - // - // The client of this package should switch to a new name whenever - // the comparator implementation changes in a way that will cause - // the relative ordering of any two keys to change. - // - // Names starting with "leveldb." are reserved and should not be used - // by any clients of this package. - virtual const char* Name() const = 0; - - // Advanced functions: these are used to reduce the space requirements - // for internal data structures like index blocks. - - // If *start < limit, changes *start to a short string in [start,limit). - // Simple comparator implementations may return with *start unchanged, - // i.e., an implementation of this method that does nothing is correct. - virtual void FindShortestSeparator( - std::string* start, - const Slice& limit) const = 0; - - // Changes *key to a short string >= *key. - // Simple comparator implementations may return with *key unchanged, - // i.e., an implementation of this method that does nothing is correct. - virtual void FindShortSuccessor(std::string* key) const = 0; -}; - -// Return a builtin comparator that uses lexicographic byte-wise -// ordering. The result remains the property of this module and -// must not be deleted. -extern const Comparator* BytewiseComparator(); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h deleted file mode 100644 index 4c169bf22e..0000000000 --- a/src/leveldb/include/leveldb/db.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ -#define STORAGE_LEVELDB_INCLUDE_DB_H_ - -#include -#include -#include "leveldb/iterator.h" -#include "leveldb/options.h" - -namespace leveldb { - -// Update Makefile if you change these -static const int kMajorVersion = 1; -static const int kMinorVersion = 18; - -struct Options; -struct ReadOptions; -struct WriteOptions; -class WriteBatch; - -// Abstract handle to particular state of a DB. -// A Snapshot is an immutable object and can therefore be safely -// accessed from multiple threads without any external synchronization. -class Snapshot { - protected: - virtual ~Snapshot(); -}; - -// A range of keys -struct Range { - Slice start; // Included in the range - Slice limit; // Not included in the range - - Range() { } - Range(const Slice& s, const Slice& l) : start(s), limit(l) { } -}; - -// A DB is a persistent ordered map from keys to values. -// A DB is safe for concurrent access from multiple threads without -// any external synchronization. -class DB { - public: - // Open the database with the specified "name". - // Stores a pointer to a heap-allocated database in *dbptr and returns - // OK on success. - // Stores NULL in *dbptr and returns a non-OK status on error. - // Caller should delete *dbptr when it is no longer needed. - static Status Open(const Options& options, - const std::string& name, - DB** dbptr); - - DB() { } - virtual ~DB(); - - // Set the database entry for "key" to "value". Returns OK on success, - // and a non-OK status on error. - // Note: consider setting options.sync = true. - virtual Status Put(const WriteOptions& options, - const Slice& key, - const Slice& value) = 0; - - // Remove the database entry (if any) for "key". Returns OK on - // success, and a non-OK status on error. It is not an error if "key" - // did not exist in the database. - // Note: consider setting options.sync = true. - virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; - - // Apply the specified updates to the database. - // Returns OK on success, non-OK on failure. - // Note: consider setting options.sync = true. - virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; - - // If the database contains an entry for "key" store the - // corresponding value in *value and return OK. - // - // If there is no entry for "key" leave *value unchanged and return - // a status for which Status::IsNotFound() returns true. - // - // May return some other Status on an error. - virtual Status Get(const ReadOptions& options, - const Slice& key, std::string* value) = 0; - - // Return a heap-allocated iterator over the contents of the database. - // The result of NewIterator() is initially invalid (caller must - // call one of the Seek methods on the iterator before using it). - // - // Caller should delete the iterator when it is no longer needed. - // The returned iterator should be deleted before this db is deleted. - virtual Iterator* NewIterator(const ReadOptions& options) = 0; - - // Return a handle to the current DB state. Iterators created with - // this handle will all observe a stable snapshot of the current DB - // state. The caller must call ReleaseSnapshot(result) when the - // snapshot is no longer needed. - virtual const Snapshot* GetSnapshot() = 0; - - // Release a previously acquired snapshot. The caller must not - // use "snapshot" after this call. - virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; - - // DB implementations can export properties about their state - // via this method. If "property" is a valid property understood by this - // DB implementation, fills "*value" with its current value and returns - // true. Otherwise returns false. - // - // - // Valid property names include: - // - // "leveldb.num-files-at-level" - return the number of files at level , - // where is an ASCII representation of a level number (e.g. "0"). - // "leveldb.stats" - returns a multi-line string that describes statistics - // about the internal operation of the DB. - // "leveldb.sstables" - returns a multi-line string that describes all - // of the sstables that make up the db contents. - virtual bool GetProperty(const Slice& property, std::string* value) = 0; - - // For each i in [0,n-1], store in "sizes[i]", the approximate - // file system space used by keys in "[range[i].start .. range[i].limit)". - // - // Note that the returned sizes measure file system space usage, so - // if the user data compresses by a factor of ten, the returned - // sizes will be one-tenth the size of the corresponding user data size. - // - // The results may not include the sizes of recently written data. - virtual void GetApproximateSizes(const Range* range, int n, - uint64_t* sizes) = 0; - - // Compact the underlying storage for the key range [*begin,*end]. - // In particular, deleted and overwritten versions are discarded, - // and the data is rearranged to reduce the cost of operations - // needed to access the data. This operation should typically only - // be invoked by users who understand the underlying implementation. - // - // begin==NULL is treated as a key before all keys in the database. - // end==NULL is treated as a key after all keys in the database. - // Therefore the following call will compact the entire database: - // db->CompactRange(NULL, NULL); - virtual void CompactRange(const Slice* begin, const Slice* end) = 0; - - private: - // No copying allowed - DB(const DB&); - void operator=(const DB&); -}; - -// Destroy the contents of the specified database. -// Be very careful using this method. -Status DestroyDB(const std::string& name, const Options& options); - -// If a DB cannot be opened, you may attempt to call this method to -// resurrect as much of the contents of the database as possible. -// Some data may be lost, so be careful when calling this function -// on a database that contains important information. -Status RepairDB(const std::string& dbname, const Options& options); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/src/leveldb/include/leveldb/dumpfile.h b/src/leveldb/include/leveldb/dumpfile.h deleted file mode 100644 index 3f97fda16b..0000000000 --- a/src/leveldb/include/leveldb/dumpfile.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2014 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ -#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ - -#include -#include "leveldb/env.h" -#include "leveldb/status.h" - -namespace leveldb { - -// Dump the contents of the file named by fname in text format to -// *dst. Makes a sequence of dst->Append() calls; each call is passed -// the newline-terminated text corresponding to a single item found -// in the file. -// -// Returns a non-OK result if fname does not name a leveldb storage -// file, or if the file cannot be read. -Status DumpFile(Env* env, const std::string& fname, WritableFile* dst); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ diff --git a/src/leveldb/include/leveldb/env.h b/src/leveldb/include/leveldb/env.h deleted file mode 100644 index f709514da6..0000000000 --- a/src/leveldb/include/leveldb/env.h +++ /dev/null @@ -1,333 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// An Env is an interface used by the leveldb implementation to access -// operating system functionality like the filesystem etc. Callers -// may wish to provide a custom Env object when opening a database to -// get fine gain control; e.g., to rate limit file system operations. -// -// All Env implementations are safe for concurrent access from -// multiple threads without any external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ -#define STORAGE_LEVELDB_INCLUDE_ENV_H_ - -#include -#include -#include -#include -#include "leveldb/status.h" - -namespace leveldb { - -class FileLock; -class Logger; -class RandomAccessFile; -class SequentialFile; -class Slice; -class WritableFile; - -class Env { - public: - Env() { } - virtual ~Env(); - - // Return a default environment suitable for the current operating - // system. Sophisticated users may wish to provide their own Env - // implementation instead of relying on this default environment. - // - // The result of Default() belongs to leveldb and must never be deleted. - static Env* Default(); - - // Create a brand new sequentially-readable file with the specified name. - // On success, stores a pointer to the new file in *result and returns OK. - // On failure stores NULL in *result and returns non-OK. If the file does - // not exist, returns a non-OK status. - // - // The returned file will only be accessed by one thread at a time. - virtual Status NewSequentialFile(const std::string& fname, - SequentialFile** result) = 0; - - // Create a brand new random access read-only file with the - // specified name. On success, stores a pointer to the new file in - // *result and returns OK. On failure stores NULL in *result and - // returns non-OK. If the file does not exist, returns a non-OK - // status. - // - // The returned file may be concurrently accessed by multiple threads. - virtual Status NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result) = 0; - - // Create an object that writes to a new file with the specified - // name. Deletes any existing file with the same name and creates a - // new file. On success, stores a pointer to the new file in - // *result and returns OK. On failure stores NULL in *result and - // returns non-OK. - // - // The returned file will only be accessed by one thread at a time. - virtual Status NewWritableFile(const std::string& fname, - WritableFile** result) = 0; - - // Returns true iff the named file exists. - virtual bool FileExists(const std::string& fname) = 0; - - // Store in *result the names of the children of the specified directory. - // The names are relative to "dir". - // Original contents of *results are dropped. - virtual Status GetChildren(const std::string& dir, - std::vector* result) = 0; - - // Delete the named file. - virtual Status DeleteFile(const std::string& fname) = 0; - - // Create the specified directory. - virtual Status CreateDir(const std::string& dirname) = 0; - - // Delete the specified directory. - virtual Status DeleteDir(const std::string& dirname) = 0; - - // Store the size of fname in *file_size. - virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; - - // Rename file src to target. - virtual Status RenameFile(const std::string& src, - const std::string& target) = 0; - - // Lock the specified file. Used to prevent concurrent access to - // the same db by multiple processes. On failure, stores NULL in - // *lock and returns non-OK. - // - // On success, stores a pointer to the object that represents the - // acquired lock in *lock and returns OK. The caller should call - // UnlockFile(*lock) to release the lock. If the process exits, - // the lock will be automatically released. - // - // If somebody else already holds the lock, finishes immediately - // with a failure. I.e., this call does not wait for existing locks - // to go away. - // - // May create the named file if it does not already exist. - virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; - - // Release the lock acquired by a previous successful call to LockFile. - // REQUIRES: lock was returned by a successful LockFile() call - // REQUIRES: lock has not already been unlocked. - virtual Status UnlockFile(FileLock* lock) = 0; - - // Arrange to run "(*function)(arg)" once in a background thread. - // - // "function" may run in an unspecified thread. Multiple functions - // added to the same Env may run concurrently in different threads. - // I.e., the caller may not assume that background work items are - // serialized. - virtual void Schedule( - void (*function)(void* arg), - void* arg) = 0; - - // Start a new thread, invoking "function(arg)" within the new thread. - // When "function(arg)" returns, the thread will be destroyed. - virtual void StartThread(void (*function)(void* arg), void* arg) = 0; - - // *path is set to a temporary directory that can be used for testing. It may - // or many not have just been created. The directory may or may not differ - // between runs of the same process, but subsequent calls will return the - // same directory. - virtual Status GetTestDirectory(std::string* path) = 0; - - // Create and return a log file for storing informational messages. - virtual Status NewLogger(const std::string& fname, Logger** result) = 0; - - // Returns the number of micro-seconds since some fixed point in time. Only - // useful for computing deltas of time. - virtual uint64_t NowMicros() = 0; - - // Sleep/delay the thread for the prescribed number of micro-seconds. - virtual void SleepForMicroseconds(int micros) = 0; - - private: - // No copying allowed - Env(const Env&); - void operator=(const Env&); -}; - -// A file abstraction for reading sequentially through a file -class SequentialFile { - public: - SequentialFile() { } - virtual ~SequentialFile(); - - // Read up to "n" bytes from the file. "scratch[0..n-1]" may be - // written by this routine. Sets "*result" to the data that was - // read (including if fewer than "n" bytes were successfully read). - // May set "*result" to point at data in "scratch[0..n-1]", so - // "scratch[0..n-1]" must be live when "*result" is used. - // If an error was encountered, returns a non-OK status. - // - // REQUIRES: External synchronization - virtual Status Read(size_t n, Slice* result, char* scratch) = 0; - - // Skip "n" bytes from the file. This is guaranteed to be no - // slower that reading the same data, but may be faster. - // - // If end of file is reached, skipping will stop at the end of the - // file, and Skip will return OK. - // - // REQUIRES: External synchronization - virtual Status Skip(uint64_t n) = 0; - - private: - // No copying allowed - SequentialFile(const SequentialFile&); - void operator=(const SequentialFile&); -}; - -// A file abstraction for randomly reading the contents of a file. -class RandomAccessFile { - public: - RandomAccessFile() { } - virtual ~RandomAccessFile(); - - // Read up to "n" bytes from the file starting at "offset". - // "scratch[0..n-1]" may be written by this routine. Sets "*result" - // to the data that was read (including if fewer than "n" bytes were - // successfully read). May set "*result" to point at data in - // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when - // "*result" is used. If an error was encountered, returns a non-OK - // status. - // - // Safe for concurrent use by multiple threads. - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const = 0; - - private: - // No copying allowed - RandomAccessFile(const RandomAccessFile&); - void operator=(const RandomAccessFile&); -}; - -// A file abstraction for sequential writing. The implementation -// must provide buffering since callers may append small fragments -// at a time to the file. -class WritableFile { - public: - WritableFile() { } - virtual ~WritableFile(); - - virtual Status Append(const Slice& data) = 0; - virtual Status Close() = 0; - virtual Status Flush() = 0; - virtual Status Sync() = 0; - - private: - // No copying allowed - WritableFile(const WritableFile&); - void operator=(const WritableFile&); -}; - -// An interface for writing log messages. -class Logger { - public: - Logger() { } - virtual ~Logger(); - - // Write an entry to the log file with the specified format. - virtual void Logv(const char* format, va_list ap) = 0; - - private: - // No copying allowed - Logger(const Logger&); - void operator=(const Logger&); -}; - - -// Identifies a locked file. -class FileLock { - public: - FileLock() { } - virtual ~FileLock(); - private: - // No copying allowed - FileLock(const FileLock&); - void operator=(const FileLock&); -}; - -// Log the specified data to *info_log if info_log is non-NULL. -extern void Log(Logger* info_log, const char* format, ...) -# if defined(__GNUC__) || defined(__clang__) - __attribute__((__format__ (__printf__, 2, 3))) -# endif - ; - -// A utility routine: write "data" to the named file. -extern Status WriteStringToFile(Env* env, const Slice& data, - const std::string& fname); - -// A utility routine: read contents of named file into *data -extern Status ReadFileToString(Env* env, const std::string& fname, - std::string* data); - -// An implementation of Env that forwards all calls to another Env. -// May be useful to clients who wish to override just part of the -// functionality of another Env. -class EnvWrapper : public Env { - public: - // Initialize an EnvWrapper that delegates all calls to *t - explicit EnvWrapper(Env* t) : target_(t) { } - virtual ~EnvWrapper(); - - // Return the target to which this Env forwards all calls - Env* target() const { return target_; } - - // The following text is boilerplate that forwards all methods to target() - Status NewSequentialFile(const std::string& f, SequentialFile** r) { - return target_->NewSequentialFile(f, r); - } - Status NewRandomAccessFile(const std::string& f, RandomAccessFile** r) { - return target_->NewRandomAccessFile(f, r); - } - Status NewWritableFile(const std::string& f, WritableFile** r) { - return target_->NewWritableFile(f, r); - } - bool FileExists(const std::string& f) { return target_->FileExists(f); } - Status GetChildren(const std::string& dir, std::vector* r) { - return target_->GetChildren(dir, r); - } - Status DeleteFile(const std::string& f) { return target_->DeleteFile(f); } - Status CreateDir(const std::string& d) { return target_->CreateDir(d); } - Status DeleteDir(const std::string& d) { return target_->DeleteDir(d); } - Status GetFileSize(const std::string& f, uint64_t* s) { - return target_->GetFileSize(f, s); - } - Status RenameFile(const std::string& s, const std::string& t) { - return target_->RenameFile(s, t); - } - Status LockFile(const std::string& f, FileLock** l) { - return target_->LockFile(f, l); - } - Status UnlockFile(FileLock* l) { return target_->UnlockFile(l); } - void Schedule(void (*f)(void*), void* a) { - return target_->Schedule(f, a); - } - void StartThread(void (*f)(void*), void* a) { - return target_->StartThread(f, a); - } - virtual Status GetTestDirectory(std::string* path) { - return target_->GetTestDirectory(path); - } - virtual Status NewLogger(const std::string& fname, Logger** result) { - return target_->NewLogger(fname, result); - } - uint64_t NowMicros() { - return target_->NowMicros(); - } - void SleepForMicroseconds(int micros) { - target_->SleepForMicroseconds(micros); - } - private: - Env* target_; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/src/leveldb/include/leveldb/filter_policy.h b/src/leveldb/include/leveldb/filter_policy.h deleted file mode 100644 index 1fba08001f..0000000000 --- a/src/leveldb/include/leveldb/filter_policy.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// A database can be configured with a custom FilterPolicy object. -// This object is responsible for creating a small filter from a set -// of keys. These filters are stored in leveldb and are consulted -// automatically by leveldb to decide whether or not to read some -// information from disk. In many cases, a filter can cut down the -// number of disk seeks form a handful to a single disk seek per -// DB::Get() call. -// -// Most people will want to use the builtin bloom filter support (see -// NewBloomFilterPolicy() below). - -#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ -#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ - -#include - -namespace leveldb { - -class Slice; - -class FilterPolicy { - public: - virtual ~FilterPolicy(); - - // Return the name of this policy. Note that if the filter encoding - // changes in an incompatible way, the name returned by this method - // must be changed. Otherwise, old incompatible filters may be - // passed to methods of this type. - virtual const char* Name() const = 0; - - // keys[0,n-1] contains a list of keys (potentially with duplicates) - // that are ordered according to the user supplied comparator. - // Append a filter that summarizes keys[0,n-1] to *dst. - // - // Warning: do not change the initial contents of *dst. Instead, - // append the newly constructed filter to *dst. - virtual void CreateFilter(const Slice* keys, int n, std::string* dst) - const = 0; - - // "filter" contains the data appended by a preceding call to - // CreateFilter() on this class. This method must return true if - // the key was in the list of keys passed to CreateFilter(). - // This method may return true or false if the key was not on the - // list, but it should aim to return false with a high probability. - virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; -}; - -// Return a new filter policy that uses a bloom filter with approximately -// the specified number of bits per key. A good value for bits_per_key -// is 10, which yields a filter with ~ 1% false positive rate. -// -// Callers must delete the result after any database that is using the -// result has been closed. -// -// Note: if you are using a custom comparator that ignores some parts -// of the keys being compared, you must not use NewBloomFilterPolicy() -// and must provide your own FilterPolicy that also ignores the -// corresponding parts of the keys. For example, if the comparator -// ignores trailing spaces, it would be incorrect to use a -// FilterPolicy (like NewBloomFilterPolicy) that does not ignore -// trailing spaces in keys. -extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); - -} - -#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/src/leveldb/include/leveldb/iterator.h b/src/leveldb/include/leveldb/iterator.h deleted file mode 100644 index 76aced04bd..0000000000 --- a/src/leveldb/include/leveldb/iterator.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// An iterator yields a sequence of key/value pairs from a source. -// The following class defines the interface. Multiple implementations -// are provided by this library. In particular, iterators are provided -// to access the contents of a Table or a DB. -// -// Multiple threads can invoke const methods on an Iterator without -// external synchronization, but if any of the threads may call a -// non-const method, all threads accessing the same Iterator must use -// external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ -#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ - -#include "leveldb/slice.h" -#include "leveldb/status.h" - -namespace leveldb { - -class Iterator { - public: - Iterator(); - virtual ~Iterator(); - - // An iterator is either positioned at a key/value pair, or - // not valid. This method returns true iff the iterator is valid. - virtual bool Valid() const = 0; - - // Position at the first key in the source. The iterator is Valid() - // after this call iff the source is not empty. - virtual void SeekToFirst() = 0; - - // Position at the last key in the source. The iterator is - // Valid() after this call iff the source is not empty. - virtual void SeekToLast() = 0; - - // Position at the first key in the source that at or past target - // The iterator is Valid() after this call iff the source contains - // an entry that comes at or past target. - virtual void Seek(const Slice& target) = 0; - - // Moves to the next entry in the source. After this call, Valid() is - // true iff the iterator was not positioned at the last entry in the source. - // REQUIRES: Valid() - virtual void Next() = 0; - - // Moves to the previous entry in the source. After this call, Valid() is - // true iff the iterator was not positioned at the first entry in source. - // REQUIRES: Valid() - virtual void Prev() = 0; - - // Return the key for the current entry. The underlying storage for - // the returned slice is valid only until the next modification of - // the iterator. - // REQUIRES: Valid() - virtual Slice key() const = 0; - - // Return the value for the current entry. The underlying storage for - // the returned slice is valid only until the next modification of - // the iterator. - // REQUIRES: Valid() - virtual Slice value() const = 0; - - // If an error has occurred, return it. Else return an ok status. - virtual Status status() const = 0; - - // Clients are allowed to register function/arg1/arg2 triples that - // will be invoked when this iterator is destroyed. - // - // Note that unlike all of the preceding methods, this method is - // not abstract and therefore clients should not override it. - typedef void (*CleanupFunction)(void* arg1, void* arg2); - void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); - - private: - struct Cleanup { - CleanupFunction function; - void* arg1; - void* arg2; - Cleanup* next; - }; - Cleanup cleanup_; - - // No copying allowed - Iterator(const Iterator&); - void operator=(const Iterator&); -}; - -// Return an empty iterator (yields nothing). -extern Iterator* NewEmptyIterator(); - -// Return an empty iterator with the specified status. -extern Iterator* NewErrorIterator(const Status& status); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/src/leveldb/include/leveldb/options.h b/src/leveldb/include/leveldb/options.h deleted file mode 100644 index 7c9b973454..0000000000 --- a/src/leveldb/include/leveldb/options.h +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ -#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ - -#include - -namespace leveldb { - -class Cache; -class Comparator; -class Env; -class FilterPolicy; -class Logger; -class Snapshot; - -// DB contents are stored in a set of blocks, each of which holds a -// sequence of key,value pairs. Each block may be compressed before -// being stored in a file. The following enum describes which -// compression method (if any) is used to compress a block. -enum CompressionType { - // NOTE: do not change the values of existing entries, as these are - // part of the persistent format on disk. - kNoCompression = 0x0, - kSnappyCompression = 0x1 -}; - -// Options to control the behavior of a database (passed to DB::Open) -struct Options { - // ------------------- - // Parameters that affect behavior - - // Comparator used to define the order of keys in the table. - // Default: a comparator that uses lexicographic byte-wise ordering - // - // REQUIRES: The client must ensure that the comparator supplied - // here has the same name and orders keys *exactly* the same as the - // comparator provided to previous open calls on the same DB. - const Comparator* comparator; - - // If true, the database will be created if it is missing. - // Default: false - bool create_if_missing; - - // If true, an error is raised if the database already exists. - // Default: false - bool error_if_exists; - - // If true, the implementation will do aggressive checking of the - // data it is processing and will stop early if it detects any - // errors. This may have unforeseen ramifications: for example, a - // corruption of one DB entry may cause a large number of entries to - // become unreadable or for the entire DB to become unopenable. - // Default: false - bool paranoid_checks; - - // Use the specified object to interact with the environment, - // e.g. to read/write files, schedule background work, etc. - // Default: Env::Default() - Env* env; - - // Any internal progress/error information generated by the db will - // be written to info_log if it is non-NULL, or to a file stored - // in the same directory as the DB contents if info_log is NULL. - // Default: NULL - Logger* info_log; - - // ------------------- - // Parameters that affect performance - - // Amount of data to build up in memory (backed by an unsorted log - // on disk) before converting to a sorted on-disk file. - // - // Larger values increase performance, especially during bulk loads. - // Up to two write buffers may be held in memory at the same time, - // so you may wish to adjust this parameter to control memory usage. - // Also, a larger write buffer will result in a longer recovery time - // the next time the database is opened. - // - // Default: 4MB - size_t write_buffer_size; - - // Number of open files that can be used by the DB. You may need to - // increase this if your database has a large working set (budget - // one open file per 2MB of working set). - // - // Default: 1000 - int max_open_files; - - // Control over blocks (user data is stored in a set of blocks, and - // a block is the unit of reading from disk). - - // If non-NULL, use the specified cache for blocks. - // If NULL, leveldb will automatically create and use an 8MB internal cache. - // Default: NULL - Cache* block_cache; - - // Approximate size of user data packed per block. Note that the - // block size specified here corresponds to uncompressed data. The - // actual size of the unit read from disk may be smaller if - // compression is enabled. This parameter can be changed dynamically. - // - // Default: 4K - size_t block_size; - - // Number of keys between restart points for delta encoding of keys. - // This parameter can be changed dynamically. Most clients should - // leave this parameter alone. - // - // Default: 16 - int block_restart_interval; - - // Compress blocks using the specified compression algorithm. This - // parameter can be changed dynamically. - // - // Default: kSnappyCompression, which gives lightweight but fast - // compression. - // - // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: - // ~200-500MB/s compression - // ~400-800MB/s decompression - // Note that these speeds are significantly faster than most - // persistent storage speeds, and therefore it is typically never - // worth switching to kNoCompression. Even if the input data is - // incompressible, the kSnappyCompression implementation will - // efficiently detect that and will switch to uncompressed mode. - CompressionType compression; - - // If non-NULL, use the specified filter policy to reduce disk reads. - // Many applications will benefit from passing the result of - // NewBloomFilterPolicy() here. - // - // Default: NULL - const FilterPolicy* filter_policy; - - // Create an Options object with default values for all fields. - Options(); -}; - -// Options that control read operations -struct ReadOptions { - // If true, all data read from underlying storage will be - // verified against corresponding checksums. - // Default: false - bool verify_checksums; - - // Should the data read for this iteration be cached in memory? - // Callers may wish to set this field to false for bulk scans. - // Default: true - bool fill_cache; - - // If "snapshot" is non-NULL, read as of the supplied snapshot - // (which must belong to the DB that is being read and which must - // not have been released). If "snapshot" is NULL, use an implicit - // snapshot of the state at the beginning of this read operation. - // Default: NULL - const Snapshot* snapshot; - - ReadOptions() - : verify_checksums(false), - fill_cache(true), - snapshot(NULL) { - } -}; - -// Options that control write operations -struct WriteOptions { - // If true, the write will be flushed from the operating system - // buffer cache (by calling WritableFile::Sync()) before the write - // is considered complete. If this flag is true, writes will be - // slower. - // - // If this flag is false, and the machine crashes, some recent - // writes may be lost. Note that if it is just the process that - // crashes (i.e., the machine does not reboot), no writes will be - // lost even if sync==false. - // - // In other words, a DB write with sync==false has similar - // crash semantics as the "write()" system call. A DB write - // with sync==true has similar crash semantics to a "write()" - // system call followed by "fsync()". - // - // Default: false - bool sync; - - WriteOptions() - : sync(false) { - } -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/src/leveldb/include/leveldb/slice.h b/src/leveldb/include/leveldb/slice.h deleted file mode 100644 index bc367986f7..0000000000 --- a/src/leveldb/include/leveldb/slice.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Slice is a simple structure containing a pointer into some external -// storage and a size. The user of a Slice must ensure that the slice -// is not used after the corresponding external storage has been -// deallocated. -// -// Multiple threads can invoke const methods on a Slice without -// external synchronization, but if any of the threads may call a -// non-const method, all threads accessing the same Slice must use -// external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ -#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ - -#include -#include -#include -#include - -namespace leveldb { - -class Slice { - public: - // Create an empty slice. - Slice() : data_(""), size_(0) { } - - // Create a slice that refers to d[0,n-1]. - Slice(const char* d, size_t n) : data_(d), size_(n) { } - - // Create a slice that refers to the contents of "s" - Slice(const std::string& s) : data_(s.data()), size_(s.size()) { } - - // Create a slice that refers to s[0,strlen(s)-1] - Slice(const char* s) : data_(s), size_(strlen(s)) { } - - // Return a pointer to the beginning of the referenced data - const char* data() const { return data_; } - - // Return the length (in bytes) of the referenced data - size_t size() const { return size_; } - - // Return true iff the length of the referenced data is zero - bool empty() const { return size_ == 0; } - - // Return the ith byte in the referenced data. - // REQUIRES: n < size() - char operator[](size_t n) const { - assert(n < size()); - return data_[n]; - } - - // Change this slice to refer to an empty array - void clear() { data_ = ""; size_ = 0; } - - // Drop the first "n" bytes from this slice. - void remove_prefix(size_t n) { - assert(n <= size()); - data_ += n; - size_ -= n; - } - - // Return a string that contains the copy of the referenced data. - std::string ToString() const { return std::string(data_, size_); } - - // Three-way comparison. Returns value: - // < 0 iff "*this" < "b", - // == 0 iff "*this" == "b", - // > 0 iff "*this" > "b" - int compare(const Slice& b) const; - - // Return true iff "x" is a prefix of "*this" - bool starts_with(const Slice& x) const { - return ((size_ >= x.size_) && - (memcmp(data_, x.data_, x.size_) == 0)); - } - - private: - const char* data_; - size_t size_; - - // Intentionally copyable -}; - -inline bool operator==(const Slice& x, const Slice& y) { - return ((x.size() == y.size()) && - (memcmp(x.data(), y.data(), x.size()) == 0)); -} - -inline bool operator!=(const Slice& x, const Slice& y) { - return !(x == y); -} - -inline int Slice::compare(const Slice& b) const { - const size_t min_len = (size_ < b.size_) ? size_ : b.size_; - int r = memcmp(data_, b.data_, min_len); - if (r == 0) { - if (size_ < b.size_) r = -1; - else if (size_ > b.size_) r = +1; - } - return r; -} - -} // namespace leveldb - - -#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/src/leveldb/include/leveldb/status.h b/src/leveldb/include/leveldb/status.h deleted file mode 100644 index 11dbd4b47e..0000000000 --- a/src/leveldb/include/leveldb/status.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// A Status encapsulates the result of an operation. It may indicate success, -// or it may indicate an error with an associated error message. -// -// Multiple threads can invoke const methods on a Status without -// external synchronization, but if any of the threads may call a -// non-const method, all threads accessing the same Status must use -// external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ -#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ - -#include -#include "leveldb/slice.h" - -namespace leveldb { - -class Status { - public: - // Create a success status. - Status() : state_(NULL) { } - ~Status() { delete[] state_; } - - // Copy the specified status. - Status(const Status& s); - void operator=(const Status& s); - - // Return a success status. - static Status OK() { return Status(); } - - // Return error status of an appropriate type. - static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { - return Status(kNotFound, msg, msg2); - } - static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { - return Status(kCorruption, msg, msg2); - } - static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { - return Status(kNotSupported, msg, msg2); - } - static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { - return Status(kInvalidArgument, msg, msg2); - } - static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { - return Status(kIOError, msg, msg2); - } - - // Returns true iff the status indicates success. - bool ok() const { return (state_ == NULL); } - - // Returns true iff the status indicates a NotFound error. - bool IsNotFound() const { return code() == kNotFound; } - - // Returns true iff the status indicates a Corruption error. - bool IsCorruption() const { return code() == kCorruption; } - - // Returns true iff the status indicates an IOError. - bool IsIOError() const { return code() == kIOError; } - - // Return a string representation of this status suitable for printing. - // Returns the string "OK" for success. - std::string ToString() const; - - private: - // OK status has a NULL state_. Otherwise, state_ is a new[] array - // of the following form: - // state_[0..3] == length of message - // state_[4] == code - // state_[5..] == message - const char* state_; - - enum Code { - kOk = 0, - kNotFound = 1, - kCorruption = 2, - kNotSupported = 3, - kInvalidArgument = 4, - kIOError = 5 - }; - - Code code() const { - return (state_ == NULL) ? kOk : static_cast(state_[4]); - } - - Status(Code code, const Slice& msg, const Slice& msg2); - static const char* CopyState(const char* s); -}; - -inline Status::Status(const Status& s) { - state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_); -} -inline void Status::operator=(const Status& s) { - // The following condition catches both aliasing (when this == &s), - // and the common case where both s and *this are ok. - if (state_ != s.state_) { - delete[] state_; - state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_); - } -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/src/leveldb/include/leveldb/table.h b/src/leveldb/include/leveldb/table.h deleted file mode 100644 index a9746c3f5e..0000000000 --- a/src/leveldb/include/leveldb/table.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ -#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ - -#include -#include "leveldb/iterator.h" - -namespace leveldb { - -class Block; -class BlockHandle; -class Footer; -struct Options; -class RandomAccessFile; -struct ReadOptions; -class TableCache; - -// A Table is a sorted map from strings to strings. Tables are -// immutable and persistent. A Table may be safely accessed from -// multiple threads without external synchronization. -class Table { - public: - // Attempt to open the table that is stored in bytes [0..file_size) - // of "file", and read the metadata entries necessary to allow - // retrieving data from the table. - // - // If successful, returns ok and sets "*table" to the newly opened - // table. The client should delete "*table" when no longer needed. - // If there was an error while initializing the table, sets "*table" - // to NULL and returns a non-ok status. Does not take ownership of - // "*source", but the client must ensure that "source" remains live - // for the duration of the returned table's lifetime. - // - // *file must remain live while this Table is in use. - static Status Open(const Options& options, - RandomAccessFile* file, - uint64_t file_size, - Table** table); - - ~Table(); - - // Returns a new iterator over the table contents. - // The result of NewIterator() is initially invalid (caller must - // call one of the Seek methods on the iterator before using it). - Iterator* NewIterator(const ReadOptions&) const; - - // Given a key, return an approximate byte offset in the file where - // the data for that key begins (or would begin if the key were - // present in the file). The returned value is in terms of file - // bytes, and so includes effects like compression of the underlying data. - // E.g., the approximate offset of the last key in the table will - // be close to the file length. - uint64_t ApproximateOffsetOf(const Slice& key) const; - - private: - struct Rep; - Rep* rep_; - - explicit Table(Rep* rep) { rep_ = rep; } - static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); - - // Calls (*handle_result)(arg, ...) with the entry found after a call - // to Seek(key). May not make such a call if filter policy says - // that key is not present. - friend class TableCache; - Status InternalGet( - const ReadOptions&, const Slice& key, - void* arg, - void (*handle_result)(void* arg, const Slice& k, const Slice& v)); - - - void ReadMeta(const Footer& footer); - void ReadFilter(const Slice& filter_handle_value); - - // No copying allowed - Table(const Table&); - void operator=(const Table&); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/src/leveldb/include/leveldb/table_builder.h b/src/leveldb/include/leveldb/table_builder.h deleted file mode 100644 index 5fd1dc71f1..0000000000 --- a/src/leveldb/include/leveldb/table_builder.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// TableBuilder provides the interface used to build a Table -// (an immutable and sorted map from keys to values). -// -// Multiple threads can invoke const methods on a TableBuilder without -// external synchronization, but if any of the threads may call a -// non-const method, all threads accessing the same TableBuilder must use -// external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ -#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ - -#include -#include "leveldb/options.h" -#include "leveldb/status.h" - -namespace leveldb { - -class BlockBuilder; -class BlockHandle; -class WritableFile; - -class TableBuilder { - public: - // Create a builder that will store the contents of the table it is - // building in *file. Does not close the file. It is up to the - // caller to close the file after calling Finish(). - TableBuilder(const Options& options, WritableFile* file); - - // REQUIRES: Either Finish() or Abandon() has been called. - ~TableBuilder(); - - // Change the options used by this builder. Note: only some of the - // option fields can be changed after construction. If a field is - // not allowed to change dynamically and its value in the structure - // passed to the constructor is different from its value in the - // structure passed to this method, this method will return an error - // without changing any fields. - Status ChangeOptions(const Options& options); - - // Add key,value to the table being constructed. - // REQUIRES: key is after any previously added key according to comparator. - // REQUIRES: Finish(), Abandon() have not been called - void Add(const Slice& key, const Slice& value); - - // Advanced operation: flush any buffered key/value pairs to file. - // Can be used to ensure that two adjacent entries never live in - // the same data block. Most clients should not need to use this method. - // REQUIRES: Finish(), Abandon() have not been called - void Flush(); - - // Return non-ok iff some error has been detected. - Status status() const; - - // Finish building the table. Stops using the file passed to the - // constructor after this function returns. - // REQUIRES: Finish(), Abandon() have not been called - Status Finish(); - - // Indicate that the contents of this builder should be abandoned. Stops - // using the file passed to the constructor after this function returns. - // If the caller is not going to call Finish(), it must call Abandon() - // before destroying this builder. - // REQUIRES: Finish(), Abandon() have not been called - void Abandon(); - - // Number of calls to Add() so far. - uint64_t NumEntries() const; - - // Size of the file generated so far. If invoked after a successful - // Finish() call, returns the size of the final generated file. - uint64_t FileSize() const; - - private: - bool ok() const { return status().ok(); } - void WriteBlock(BlockBuilder* block, BlockHandle* handle); - void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); - - struct Rep; - Rep* rep_; - - // No copying allowed - TableBuilder(const TableBuilder&); - void operator=(const TableBuilder&); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/src/leveldb/include/leveldb/write_batch.h b/src/leveldb/include/leveldb/write_batch.h deleted file mode 100644 index ee9aab68e0..0000000000 --- a/src/leveldb/include/leveldb/write_batch.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// WriteBatch holds a collection of updates to apply atomically to a DB. -// -// The updates are applied in the order in which they are added -// to the WriteBatch. For example, the value of "key" will be "v3" -// after the following batch is written: -// -// batch.Put("key", "v1"); -// batch.Delete("key"); -// batch.Put("key", "v2"); -// batch.Put("key", "v3"); -// -// Multiple threads can invoke const methods on a WriteBatch without -// external synchronization, but if any of the threads may call a -// non-const method, all threads accessing the same WriteBatch must use -// external synchronization. - -#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ -#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ - -#include -#include "leveldb/status.h" - -namespace leveldb { - -class Slice; - -class WriteBatch { - public: - WriteBatch(); - ~WriteBatch(); - - // Store the mapping "key->value" in the database. - void Put(const Slice& key, const Slice& value); - - // If the database contains a mapping for "key", erase it. Else do nothing. - void Delete(const Slice& key); - - // Clear all updates buffered in this batch. - void Clear(); - - // Support for iterating over the contents of a batch. - class Handler { - public: - virtual ~Handler(); - virtual void Put(const Slice& key, const Slice& value) = 0; - virtual void Delete(const Slice& key) = 0; - }; - Status Iterate(Handler* handler) const; - - private: - friend class WriteBatchInternal; - - std::string rep_; // See comment in write_batch.cc for the format of rep_ - - // Intentionally copyable -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/src/leveldb/issues/issue178_test.cc b/src/leveldb/issues/issue178_test.cc deleted file mode 100644 index 1b1cf8bb28..0000000000 --- a/src/leveldb/issues/issue178_test.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -// Test for issue 178: a manual compaction causes deleted data to reappear. -#include -#include -#include - -#include "leveldb/db.h" -#include "leveldb/write_batch.h" -#include "util/testharness.h" - -namespace { - -const int kNumKeys = 1100000; - -std::string Key1(int i) { - char buf[100]; - snprintf(buf, sizeof(buf), "my_key_%d", i); - return buf; -} - -std::string Key2(int i) { - return Key1(i) + "_xxx"; -} - -class Issue178 { }; - -TEST(Issue178, Test) { - // Get rid of any state from an old run. - std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test"; - DestroyDB(dbpath, leveldb::Options()); - - // Open database. Disable compression since it affects the creation - // of layers and the code below is trying to test against a very - // specific scenario. - leveldb::DB* db; - leveldb::Options db_options; - db_options.create_if_missing = true; - db_options.compression = leveldb::kNoCompression; - ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db)); - - // create first key range - leveldb::WriteBatch batch; - for (size_t i = 0; i < kNumKeys; i++) { - batch.Put(Key1(i), "value for range 1 key"); - } - ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); - - // create second key range - batch.Clear(); - for (size_t i = 0; i < kNumKeys; i++) { - batch.Put(Key2(i), "value for range 2 key"); - } - ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); - - // delete second key range - batch.Clear(); - for (size_t i = 0; i < kNumKeys; i++) { - batch.Delete(Key2(i)); - } - ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch)); - - // compact database - std::string start_key = Key1(0); - std::string end_key = Key1(kNumKeys - 1); - leveldb::Slice least(start_key.data(), start_key.size()); - leveldb::Slice greatest(end_key.data(), end_key.size()); - - // commenting out the line below causes the example to work correctly - db->CompactRange(&least, &greatest); - - // count the keys - leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions()); - size_t num_keys = 0; - for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { - num_keys++; - } - delete iter; - ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys"; - - // close database - delete db; - DestroyDB(dbpath, leveldb::Options()); -} - -} // anonymous namespace - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/issues/issue200_test.cc b/src/leveldb/issues/issue200_test.cc deleted file mode 100644 index 1cec79f443..0000000000 --- a/src/leveldb/issues/issue200_test.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -// Test for issue 200: when iterator switches direction from backward -// to forward, the current key can be yielded unexpectedly if a new -// mutation has been added just before the current key. - -#include "leveldb/db.h" -#include "util/testharness.h" - -namespace leveldb { - -class Issue200 { }; - -TEST(Issue200, Test) { - // Get rid of any state from an old run. - std::string dbpath = test::TmpDir() + "/leveldb_issue200_test"; - DestroyDB(dbpath, Options()); - - DB *db; - Options options; - options.create_if_missing = true; - ASSERT_OK(DB::Open(options, dbpath, &db)); - - WriteOptions write_options; - ASSERT_OK(db->Put(write_options, "1", "b")); - ASSERT_OK(db->Put(write_options, "2", "c")); - ASSERT_OK(db->Put(write_options, "3", "d")); - ASSERT_OK(db->Put(write_options, "4", "e")); - ASSERT_OK(db->Put(write_options, "5", "f")); - - ReadOptions read_options; - Iterator *iter = db->NewIterator(read_options); - - // Add an element that should not be reflected in the iterator. - ASSERT_OK(db->Put(write_options, "25", "cd")); - - iter->Seek("5"); - ASSERT_EQ(iter->key().ToString(), "5"); - iter->Prev(); - ASSERT_EQ(iter->key().ToString(), "4"); - iter->Prev(); - ASSERT_EQ(iter->key().ToString(), "3"); - iter->Next(); - ASSERT_EQ(iter->key().ToString(), "4"); - iter->Next(); - ASSERT_EQ(iter->key().ToString(), "5"); - - delete iter; - delete db; - DestroyDB(dbpath, options); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/port/README b/src/leveldb/port/README deleted file mode 100644 index 422563e25c..0000000000 --- a/src/leveldb/port/README +++ /dev/null @@ -1,10 +0,0 @@ -This directory contains interfaces and implementations that isolate the -rest of the package from platform details. - -Code in the rest of the package includes "port.h" from this directory. -"port.h" in turn includes a platform specific "port_.h" file -that provides the platform specific implementation. - -See port_posix.h for an example of what must be provided in a platform -specific header file. - diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h deleted file mode 100644 index 9bf091f757..0000000000 --- a/src/leveldb/port/atomic_pointer.h +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -// AtomicPointer provides storage for a lock-free pointer. -// Platform-dependent implementation of AtomicPointer: -// - If the platform provides a cheap barrier, we use it with raw pointers -// - If is present (on newer versions of gcc, it is), we use -// a -based AtomicPointer. However we prefer the memory -// barrier based version, because at least on a gcc 4.4 32-bit build -// on linux, we have encountered a buggy implementation. -// Also, some implementations are much slower than a memory-barrier -// based implementation (~16ns for based acquire-load vs. ~1ns for -// a barrier based acquire-load). -// This code is based on atomicops-internals-* in Google's perftools: -// http://code.google.com/p/google-perftools/source/browse/#svn%2Ftrunk%2Fsrc%2Fbase - -#ifndef PORT_ATOMIC_POINTER_H_ -#define PORT_ATOMIC_POINTER_H_ - -#include -#ifdef LEVELDB_ATOMIC_PRESENT -#include -#endif -#ifdef OS_WIN -#include -#endif -#ifdef OS_MACOSX -#include -#endif - -#if defined(_M_X64) || defined(__x86_64__) -#define ARCH_CPU_X86_FAMILY 1 -#elif defined(_M_IX86) || defined(__i386__) || defined(__i386) -#define ARCH_CPU_X86_FAMILY 1 -#elif defined(__ARMEL__) -#define ARCH_CPU_ARM_FAMILY 1 -#elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__) -#define ARCH_CPU_PPC_FAMILY 1 -#endif - -namespace leveldb { -namespace port { - -// Define MemoryBarrier() if available -// Windows on x86 -#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) -// windows.h already provides a MemoryBarrier(void) macro -// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx -#define LEVELDB_HAVE_MEMORY_BARRIER - -// Mac OS -#elif defined(OS_MACOSX) -inline void MemoryBarrier() { - OSMemoryBarrier(); -} -#define LEVELDB_HAVE_MEMORY_BARRIER - -// Gcc on x86 -#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__) -inline void MemoryBarrier() { - // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on - // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. - __asm__ __volatile__("" : : : "memory"); -} -#define LEVELDB_HAVE_MEMORY_BARRIER - -// Sun Studio -#elif defined(ARCH_CPU_X86_FAMILY) && defined(__SUNPRO_CC) -inline void MemoryBarrier() { - // See http://gcc.gnu.org/ml/gcc/2003-04/msg01180.html for a discussion on - // this idiom. Also see http://en.wikipedia.org/wiki/Memory_ordering. - asm volatile("" : : : "memory"); -} -#define LEVELDB_HAVE_MEMORY_BARRIER - -// ARM Linux -#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__) -typedef void (*LinuxKernelMemoryBarrierFunc)(void); -// The Linux ARM kernel provides a highly optimized device-specific memory -// barrier function at a fixed memory address that is mapped in every -// user-level process. -// -// This beats using CPU-specific instructions which are, on single-core -// devices, un-necessary and very costly (e.g. ARMv7-A "dmb" takes more -// than 180ns on a Cortex-A8 like the one on a Nexus One). Benchmarking -// shows that the extra function call cost is completely negligible on -// multi-core devices. -// -inline void MemoryBarrier() { - (*(LinuxKernelMemoryBarrierFunc)0xffff0fa0)(); -} -#define LEVELDB_HAVE_MEMORY_BARRIER - -// PPC -#elif defined(ARCH_CPU_PPC_FAMILY) && defined(__GNUC__) -inline void MemoryBarrier() { - // TODO for some powerpc expert: is there a cheaper suitable variant? - // Perhaps by having separate barriers for acquire and release ops. - asm volatile("sync" : : : "memory"); -} -#define LEVELDB_HAVE_MEMORY_BARRIER - -#endif - -// AtomicPointer built using platform-specific MemoryBarrier() -#if defined(LEVELDB_HAVE_MEMORY_BARRIER) -class AtomicPointer { - private: - void* rep_; - public: - AtomicPointer() { } - explicit AtomicPointer(void* p) : rep_(p) {} - inline void* NoBarrier_Load() const { return rep_; } - inline void NoBarrier_Store(void* v) { rep_ = v; } - inline void* Acquire_Load() const { - void* result = rep_; - MemoryBarrier(); - return result; - } - inline void Release_Store(void* v) { - MemoryBarrier(); - rep_ = v; - } -}; - -// AtomicPointer based on -#elif defined(LEVELDB_ATOMIC_PRESENT) -class AtomicPointer { - private: - std::atomic rep_; - public: - AtomicPointer() { } - explicit AtomicPointer(void* v) : rep_(v) { } - inline void* Acquire_Load() const { - return rep_.load(std::memory_order_acquire); - } - inline void Release_Store(void* v) { - rep_.store(v, std::memory_order_release); - } - inline void* NoBarrier_Load() const { - return rep_.load(std::memory_order_relaxed); - } - inline void NoBarrier_Store(void* v) { - rep_.store(v, std::memory_order_relaxed); - } -}; - -// Atomic pointer based on sparc memory barriers -#elif defined(__sparcv9) && defined(__GNUC__) -class AtomicPointer { - private: - void* rep_; - public: - AtomicPointer() { } - explicit AtomicPointer(void* v) : rep_(v) { } - inline void* Acquire_Load() const { - void* val; - __asm__ __volatile__ ( - "ldx [%[rep_]], %[val] \n\t" - "membar #LoadLoad|#LoadStore \n\t" - : [val] "=r" (val) - : [rep_] "r" (&rep_) - : "memory"); - return val; - } - inline void Release_Store(void* v) { - __asm__ __volatile__ ( - "membar #LoadStore|#StoreStore \n\t" - "stx %[v], [%[rep_]] \n\t" - : - : [rep_] "r" (&rep_), [v] "r" (v) - : "memory"); - } - inline void* NoBarrier_Load() const { return rep_; } - inline void NoBarrier_Store(void* v) { rep_ = v; } -}; - -// Atomic pointer based on ia64 acq/rel -#elif defined(__ia64) && defined(__GNUC__) -class AtomicPointer { - private: - void* rep_; - public: - AtomicPointer() { } - explicit AtomicPointer(void* v) : rep_(v) { } - inline void* Acquire_Load() const { - void* val ; - __asm__ __volatile__ ( - "ld8.acq %[val] = [%[rep_]] \n\t" - : [val] "=r" (val) - : [rep_] "r" (&rep_) - : "memory" - ); - return val; - } - inline void Release_Store(void* v) { - __asm__ __volatile__ ( - "st8.rel [%[rep_]] = %[v] \n\t" - : - : [rep_] "r" (&rep_), [v] "r" (v) - : "memory" - ); - } - inline void* NoBarrier_Load() const { return rep_; } - inline void NoBarrier_Store(void* v) { rep_ = v; } -}; - -// We have neither MemoryBarrier(), nor -#else -#error Please implement AtomicPointer for this platform. - -#endif - -#undef LEVELDB_HAVE_MEMORY_BARRIER -#undef ARCH_CPU_X86_FAMILY -#undef ARCH_CPU_ARM_FAMILY -#undef ARCH_CPU_PPC_FAMILY - -} // namespace port -} // namespace leveldb - -#endif // PORT_ATOMIC_POINTER_H_ diff --git a/src/leveldb/port/port.h b/src/leveldb/port/port.h deleted file mode 100644 index 4baafa8e22..0000000000 --- a/src/leveldb/port/port.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_PORT_PORT_H_ -#define STORAGE_LEVELDB_PORT_PORT_H_ - -#include - -// Include the appropriate platform specific file below. If you are -// porting to a new platform, see "port_example.h" for documentation -// of what the new port_.h file must provide. -#if defined(LEVELDB_PLATFORM_POSIX) -# include "port/port_posix.h" -#elif defined(LEVELDB_PLATFORM_CHROMIUM) -# include "port/port_chromium.h" -#elif defined(LEVELDB_PLATFORM_WINDOWS) -# include "port/port_win.h" -#endif - -#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h deleted file mode 100644 index ab9e489b32..0000000000 --- a/src/leveldb/port/port_example.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// This file contains the specification, but not the implementations, -// of the types/operations/etc. that should be defined by a platform -// specific port_.h file. Use this file as a reference for -// how to port this package to a new platform. - -#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ -#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ - -namespace leveldb { -namespace port { - -// TODO(jorlow): Many of these belong more in the environment class rather than -// here. We should try moving them and see if it affects perf. - -// The following boolean constant must be true on a little-endian machine -// and false otherwise. -static const bool kLittleEndian = true /* or some other expression */; - -// ------------------ Threading ------------------- - -// A Mutex represents an exclusive lock. -class Mutex { - public: - Mutex(); - ~Mutex(); - - // Lock the mutex. Waits until other lockers have exited. - // Will deadlock if the mutex is already locked by this thread. - void Lock(); - - // Unlock the mutex. - // REQUIRES: This mutex was locked by this thread. - void Unlock(); - - // Optionally crash if this thread does not hold this mutex. - // The implementation must be fast, especially if NDEBUG is - // defined. The implementation is allowed to skip all checks. - void AssertHeld(); -}; - -class CondVar { - public: - explicit CondVar(Mutex* mu); - ~CondVar(); - - // Atomically release *mu and block on this condition variable until - // either a call to SignalAll(), or a call to Signal() that picks - // this thread to wakeup. - // REQUIRES: this thread holds *mu - void Wait(); - - // If there are some threads waiting, wake up at least one of them. - void Signal(); - - // Wake up all waiting threads. - void SignallAll(); -}; - -// Thread-safe initialization. -// Used as follows: -// static port::OnceType init_control = LEVELDB_ONCE_INIT; -// static void Initializer() { ... do something ...; } -// ... -// port::InitOnce(&init_control, &Initializer); -typedef intptr_t OnceType; -#define LEVELDB_ONCE_INIT 0 -extern void InitOnce(port::OnceType*, void (*initializer)()); - -// A type that holds a pointer that can be read or written atomically -// (i.e., without word-tearing.) -class AtomicPointer { - private: - intptr_t rep_; - public: - // Initialize to arbitrary value - AtomicPointer(); - - // Initialize to hold v - explicit AtomicPointer(void* v) : rep_(v) { } - - // Read and return the stored pointer with the guarantee that no - // later memory access (read or write) by this thread can be - // reordered ahead of this read. - void* Acquire_Load() const; - - // Set v as the stored pointer with the guarantee that no earlier - // memory access (read or write) by this thread can be reordered - // after this store. - void Release_Store(void* v); - - // Read the stored pointer with no ordering guarantees. - void* NoBarrier_Load() const; - - // Set va as the stored pointer with no ordering guarantees. - void NoBarrier_Store(void* v); -}; - -// ------------------ Compression ------------------- - -// Store the snappy compression of "input[0,input_length-1]" in *output. -// Returns false if snappy is not supported by this port. -extern bool Snappy_Compress(const char* input, size_t input_length, - std::string* output); - -// If input[0,input_length-1] looks like a valid snappy compressed -// buffer, store the size of the uncompressed data in *result and -// return true. Else return false. -extern bool Snappy_GetUncompressedLength(const char* input, size_t length, - size_t* result); - -// Attempt to snappy uncompress input[0,input_length-1] into *output. -// Returns true if successful, false if the input is invalid lightweight -// compressed data. -// -// REQUIRES: at least the first "n" bytes of output[] must be writable -// where "n" is the result of a successful call to -// Snappy_GetUncompressedLength. -extern bool Snappy_Uncompress(const char* input_data, size_t input_length, - char* output); - -// ------------------ Miscellaneous ------------------- - -// If heap profiling is not supported, returns false. -// Else repeatedly calls (*func)(arg, data, n) and then returns true. -// The concatenation of all "data[0,n-1]" fragments is the heap profile. -extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); - -} // namespace port -} // namespace leveldb - -#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/src/leveldb/port/port_posix.cc b/src/leveldb/port/port_posix.cc deleted file mode 100644 index 5ba127a5b9..0000000000 --- a/src/leveldb/port/port_posix.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "port/port_posix.h" - -#include -#include -#include -#include "util/logging.h" - -namespace leveldb { -namespace port { - -static void PthreadCall(const char* label, int result) { - if (result != 0) { - fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); - abort(); - } -} - -Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); } - -Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); } - -void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); } - -void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); } - -CondVar::CondVar(Mutex* mu) - : mu_(mu) { - PthreadCall("init cv", pthread_cond_init(&cv_, NULL)); -} - -CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); } - -void CondVar::Wait() { - PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_)); -} - -void CondVar::Signal() { - PthreadCall("signal", pthread_cond_signal(&cv_)); -} - -void CondVar::SignalAll() { - PthreadCall("broadcast", pthread_cond_broadcast(&cv_)); -} - -void InitOnce(OnceType* once, void (*initializer)()) { - PthreadCall("once", pthread_once(once, initializer)); -} - -} // namespace port -} // namespace leveldb diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h deleted file mode 100644 index ccca9939d3..0000000000 --- a/src/leveldb/port/port_posix.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// See port_example.h for documentation for the following types/functions. - -#ifndef STORAGE_LEVELDB_PORT_PORT_POSIX_H_ -#define STORAGE_LEVELDB_PORT_PORT_POSIX_H_ - -#undef PLATFORM_IS_LITTLE_ENDIAN -#if defined(OS_MACOSX) - #include - #if defined(__DARWIN_LITTLE_ENDIAN) && defined(__DARWIN_BYTE_ORDER) - #define PLATFORM_IS_LITTLE_ENDIAN \ - (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN) - #endif -#elif defined(OS_SOLARIS) - #include - #ifdef _LITTLE_ENDIAN - #define PLATFORM_IS_LITTLE_ENDIAN true - #else - #define PLATFORM_IS_LITTLE_ENDIAN false - #endif -#elif defined(OS_FREEBSD) || defined(OS_OPENBSD) ||\ - defined(OS_NETBSD) || defined(OS_DRAGONFLYBSD) - #include - #include - #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN) -#elif defined(OS_HPUX) - #define PLATFORM_IS_LITTLE_ENDIAN false -#elif defined(OS_ANDROID) - // Due to a bug in the NDK x86 definition, - // _BYTE_ORDER must be used instead of __BYTE_ORDER on Android. - // See http://code.google.com/p/android/issues/detail?id=39824 - #include - #define PLATFORM_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN) -#else - #include -#endif - -#include -#ifdef SNAPPY -#include -#endif -#include -#include -#include "port/atomic_pointer.h" - -#ifndef PLATFORM_IS_LITTLE_ENDIAN -#define PLATFORM_IS_LITTLE_ENDIAN (__BYTE_ORDER == __LITTLE_ENDIAN) -#endif - -#if defined(OS_MACOSX) || defined(OS_SOLARIS) || defined(OS_FREEBSD) ||\ - defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) ||\ - defined(OS_ANDROID) || defined(OS_HPUX) || defined(CYGWIN) -// Use fread/fwrite/fflush on platforms without _unlocked variants -#define fread_unlocked fread -#define fwrite_unlocked fwrite -#define fflush_unlocked fflush -#endif - -#if defined(OS_FREEBSD) ||\ - defined(OS_OPENBSD) || defined(OS_DRAGONFLYBSD) -// Use fsync() on platforms without fdatasync() -#define fdatasync fsync -#endif - -#if defined(OS_MACOSX) -#define fdatasync(fd) fcntl(fd, F_FULLFSYNC, 0) -#endif - -#if defined(OS_ANDROID) && __ANDROID_API__ < 9 -// fdatasync() was only introduced in API level 9 on Android. Use fsync() -// when targetting older platforms. -#define fdatasync fsync -#endif - -namespace leveldb { -namespace port { - -static const bool kLittleEndian = PLATFORM_IS_LITTLE_ENDIAN; -#undef PLATFORM_IS_LITTLE_ENDIAN - -class CondVar; - -class Mutex { - public: - Mutex(); - ~Mutex(); - - void Lock(); - void Unlock(); - void AssertHeld() { } - - private: - friend class CondVar; - pthread_mutex_t mu_; - - // No copying - Mutex(const Mutex&); - void operator=(const Mutex&); -}; - -class CondVar { - public: - explicit CondVar(Mutex* mu); - ~CondVar(); - void Wait(); - void Signal(); - void SignalAll(); - private: - pthread_cond_t cv_; - Mutex* mu_; -}; - -typedef pthread_once_t OnceType; -#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT -extern void InitOnce(OnceType* once, void (*initializer)()); - -inline bool Snappy_Compress(const char* input, size_t length, - ::std::string* output) { -#ifdef SNAPPY - output->resize(snappy::MaxCompressedLength(length)); - size_t outlen; - snappy::RawCompress(input, length, &(*output)[0], &outlen); - output->resize(outlen); - return true; -#endif - - return false; -} - -inline bool Snappy_GetUncompressedLength(const char* input, size_t length, - size_t* result) { -#ifdef SNAPPY - return snappy::GetUncompressedLength(input, length, result); -#else - return false; -#endif -} - -inline bool Snappy_Uncompress(const char* input, size_t length, - char* output) { -#ifdef SNAPPY - return snappy::RawUncompress(input, length, output); -#else - return false; -#endif -} - -inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { - return false; -} - -} // namespace port -} // namespace leveldb - -#endif // STORAGE_LEVELDB_PORT_PORT_POSIX_H_ diff --git a/src/leveldb/port/port_win.cc b/src/leveldb/port/port_win.cc deleted file mode 100644 index 1b0f060a19..0000000000 --- a/src/leveldb/port/port_win.cc +++ /dev/null @@ -1,147 +0,0 @@ -// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// See port_example.h for documentation for the following types/functions. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * 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. -// * Neither the name of the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. -// - -#include "port/port_win.h" - -#include -#include - -namespace leveldb { -namespace port { - -Mutex::Mutex() : - cs_(NULL) { - assert(!cs_); - cs_ = static_cast(new CRITICAL_SECTION()); - ::InitializeCriticalSection(static_cast(cs_)); - assert(cs_); -} - -Mutex::~Mutex() { - assert(cs_); - ::DeleteCriticalSection(static_cast(cs_)); - delete static_cast(cs_); - cs_ = NULL; - assert(!cs_); -} - -void Mutex::Lock() { - assert(cs_); - ::EnterCriticalSection(static_cast(cs_)); -} - -void Mutex::Unlock() { - assert(cs_); - ::LeaveCriticalSection(static_cast(cs_)); -} - -void Mutex::AssertHeld() { - assert(cs_); - assert(1); -} - -CondVar::CondVar(Mutex* mu) : - waiting_(0), - mu_(mu), - sem1_(::CreateSemaphore(NULL, 0, 10000, NULL)), - sem2_(::CreateSemaphore(NULL, 0, 10000, NULL)) { - assert(mu_); -} - -CondVar::~CondVar() { - ::CloseHandle(sem1_); - ::CloseHandle(sem2_); -} - -void CondVar::Wait() { - mu_->AssertHeld(); - - wait_mtx_.Lock(); - ++waiting_; - wait_mtx_.Unlock(); - - mu_->Unlock(); - - // initiate handshake - ::WaitForSingleObject(sem1_, INFINITE); - ::ReleaseSemaphore(sem2_, 1, NULL); - mu_->Lock(); -} - -void CondVar::Signal() { - wait_mtx_.Lock(); - if (waiting_ > 0) { - --waiting_; - - // finalize handshake - ::ReleaseSemaphore(sem1_, 1, NULL); - ::WaitForSingleObject(sem2_, INFINITE); - } - wait_mtx_.Unlock(); -} - -void CondVar::SignalAll() { - wait_mtx_.Lock(); - ::ReleaseSemaphore(sem1_, waiting_, NULL); - while(waiting_ > 0) { - --waiting_; - ::WaitForSingleObject(sem2_, INFINITE); - } - wait_mtx_.Unlock(); -} - -AtomicPointer::AtomicPointer(void* v) { - Release_Store(v); -} - -void InitOnce(OnceType* once, void (*initializer)()) { - once->InitOnce(initializer); -} - -void* AtomicPointer::Acquire_Load() const { - void * p = NULL; - InterlockedExchangePointer(&p, rep_); - return p; -} - -void AtomicPointer::Release_Store(void* v) { - InterlockedExchangePointer(&rep_, v); -} - -void* AtomicPointer::NoBarrier_Load() const { - return rep_; -} - -void AtomicPointer::NoBarrier_Store(void* v) { - rep_ = v; -} - -} -} diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h deleted file mode 100644 index 45bf2f0ea7..0000000000 --- a/src/leveldb/port/port_win.h +++ /dev/null @@ -1,174 +0,0 @@ -// LevelDB Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// See port_example.h for documentation for the following types/functions. - -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * 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. -// * Neither the name of the University of California, Berkeley 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 REGENTS 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 REGENTS AND 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. -// - -#ifndef STORAGE_LEVELDB_PORT_PORT_WIN_H_ -#define STORAGE_LEVELDB_PORT_PORT_WIN_H_ - -#ifdef _MSC_VER -#define snprintf _snprintf -#define close _close -#define fread_unlocked _fread_nolock -#endif - -#include -#include -#ifdef SNAPPY -#include -#endif - -namespace leveldb { -namespace port { - -// Windows is little endian (for now :p) -static const bool kLittleEndian = true; - -class CondVar; - -class Mutex { - public: - Mutex(); - ~Mutex(); - - void Lock(); - void Unlock(); - void AssertHeld(); - - private: - friend class CondVar; - // critical sections are more efficient than mutexes - // but they are not recursive and can only be used to synchronize threads within the same process - // we use opaque void * to avoid including windows.h in port_win.h - void * cs_; - - // No copying - Mutex(const Mutex&); - void operator=(const Mutex&); -}; - -// the Win32 API offers a dependable condition variable mechanism, but only starting with -// Windows 2008 and Vista -// no matter what we will implement our own condition variable with a semaphore -// implementation as described in a paper written by Andrew D. Birrell in 2003 -class CondVar { - public: - explicit CondVar(Mutex* mu); - ~CondVar(); - void Wait(); - void Signal(); - void SignalAll(); - private: - Mutex* mu_; - - Mutex wait_mtx_; - long waiting_; - - void * sem1_; - void * sem2_; - - -}; - -class OnceType { -public: -// OnceType() : init_(false) {} - OnceType(const OnceType &once) : init_(once.init_) {} - OnceType(bool f) : init_(f) {} - void InitOnce(void (*initializer)()) { - mutex_.Lock(); - if (!init_) { - init_ = true; - initializer(); - } - mutex_.Unlock(); - } - -private: - bool init_; - Mutex mutex_; -}; - -#define LEVELDB_ONCE_INIT false -extern void InitOnce(port::OnceType*, void (*initializer)()); - -// Storage for a lock-free pointer -class AtomicPointer { - private: - void * rep_; - public: - AtomicPointer() : rep_(NULL) { } - explicit AtomicPointer(void* v); - void* Acquire_Load() const; - - void Release_Store(void* v); - - void* NoBarrier_Load() const; - - void NoBarrier_Store(void* v); -}; - -inline bool Snappy_Compress(const char* input, size_t length, - ::std::string* output) { -#ifdef SNAPPY - output->resize(snappy::MaxCompressedLength(length)); - size_t outlen; - snappy::RawCompress(input, length, &(*output)[0], &outlen); - output->resize(outlen); - return true; -#endif - - return false; -} - -inline bool Snappy_GetUncompressedLength(const char* input, size_t length, - size_t* result) { -#ifdef SNAPPY - return snappy::GetUncompressedLength(input, length, result); -#else - return false; -#endif -} - -inline bool Snappy_Uncompress(const char* input, size_t length, - char* output) { -#ifdef SNAPPY - return snappy::RawUncompress(input, length, output); -#else - return false; -#endif -} - -inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { - return false; -} - -} -} - -#endif // STORAGE_LEVELDB_PORT_PORT_WIN_H_ diff --git a/src/leveldb/port/thread_annotations.h b/src/leveldb/port/thread_annotations.h deleted file mode 100644 index 9470ef587c..0000000000 --- a/src/leveldb/port/thread_annotations.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ -#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ - -// Some environments provide custom macros to aid in static thread-safety -// analysis. Provide empty definitions of such macros unless they are already -// defined. - -#ifndef EXCLUSIVE_LOCKS_REQUIRED -#define EXCLUSIVE_LOCKS_REQUIRED(...) -#endif - -#ifndef SHARED_LOCKS_REQUIRED -#define SHARED_LOCKS_REQUIRED(...) -#endif - -#ifndef LOCKS_EXCLUDED -#define LOCKS_EXCLUDED(...) -#endif - -#ifndef LOCK_RETURNED -#define LOCK_RETURNED(x) -#endif - -#ifndef LOCKABLE -#define LOCKABLE -#endif - -#ifndef SCOPED_LOCKABLE -#define SCOPED_LOCKABLE -#endif - -#ifndef EXCLUSIVE_LOCK_FUNCTION -#define EXCLUSIVE_LOCK_FUNCTION(...) -#endif - -#ifndef SHARED_LOCK_FUNCTION -#define SHARED_LOCK_FUNCTION(...) -#endif - -#ifndef EXCLUSIVE_TRYLOCK_FUNCTION -#define EXCLUSIVE_TRYLOCK_FUNCTION(...) -#endif - -#ifndef SHARED_TRYLOCK_FUNCTION -#define SHARED_TRYLOCK_FUNCTION(...) -#endif - -#ifndef UNLOCK_FUNCTION -#define UNLOCK_FUNCTION(...) -#endif - -#ifndef NO_THREAD_SAFETY_ANALYSIS -#define NO_THREAD_SAFETY_ANALYSIS -#endif - -#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ diff --git a/src/leveldb/port/win/stdint.h b/src/leveldb/port/win/stdint.h deleted file mode 100644 index 39edd0db13..0000000000 --- a/src/leveldb/port/win/stdint.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -// MSVC didn't ship with this file until the 2010 version. - -#ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_ -#define STORAGE_LEVELDB_PORT_WIN_STDINT_H_ - -#if !defined(_MSC_VER) -#error This file should only be included when compiling with MSVC. -#endif - -// Define C99 equivalent types. -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; - -#endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_ diff --git a/src/leveldb/table/block.cc b/src/leveldb/table/block.cc deleted file mode 100644 index 43e402c9c0..0000000000 --- a/src/leveldb/table/block.cc +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Decodes the blocks generated by block_builder.cc. - -#include "table/block.h" - -#include -#include -#include "leveldb/comparator.h" -#include "table/format.h" -#include "util/coding.h" -#include "util/logging.h" - -namespace leveldb { - -inline uint32_t Block::NumRestarts() const { - assert(size_ >= sizeof(uint32_t)); - return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); -} - -Block::Block(const BlockContents& contents) - : data_(contents.data.data()), - size_(contents.data.size()), - owned_(contents.heap_allocated) { - if (size_ < sizeof(uint32_t)) { - size_ = 0; // Error marker - } else { - size_t max_restarts_allowed = (size_-sizeof(uint32_t)) / sizeof(uint32_t); - if (NumRestarts() > max_restarts_allowed) { - // The size is too small for NumRestarts() - size_ = 0; - } else { - restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); - } - } -} - -Block::~Block() { - if (owned_) { - delete[] data_; - } -} - -// Helper routine: decode the next block entry starting at "p", -// storing the number of shared key bytes, non_shared key bytes, -// and the length of the value in "*shared", "*non_shared", and -// "*value_length", respectively. Will not dereference past "limit". -// -// If any errors are detected, returns NULL. Otherwise, returns a -// pointer to the key delta (just past the three decoded values). -static inline const char* DecodeEntry(const char* p, const char* limit, - uint32_t* shared, - uint32_t* non_shared, - uint32_t* value_length) { - if (limit - p < 3) return NULL; - *shared = reinterpret_cast(p)[0]; - *non_shared = reinterpret_cast(p)[1]; - *value_length = reinterpret_cast(p)[2]; - if ((*shared | *non_shared | *value_length) < 128) { - // Fast path: all three values are encoded in one byte each - p += 3; - } else { - if ((p = GetVarint32Ptr(p, limit, shared)) == NULL) return NULL; - if ((p = GetVarint32Ptr(p, limit, non_shared)) == NULL) return NULL; - if ((p = GetVarint32Ptr(p, limit, value_length)) == NULL) return NULL; - } - - if (static_cast(limit - p) < (*non_shared + *value_length)) { - return NULL; - } - return p; -} - -class Block::Iter : public Iterator { - private: - const Comparator* const comparator_; - const char* const data_; // underlying block contents - uint32_t const restarts_; // Offset of restart array (list of fixed32) - uint32_t const num_restarts_; // Number of uint32_t entries in restart array - - // current_ is offset in data_ of current entry. >= restarts_ if !Valid - uint32_t current_; - uint32_t restart_index_; // Index of restart block in which current_ falls - std::string key_; - Slice value_; - Status status_; - - inline int Compare(const Slice& a, const Slice& b) const { - return comparator_->Compare(a, b); - } - - // Return the offset in data_ just past the end of the current entry. - inline uint32_t NextEntryOffset() const { - return (value_.data() + value_.size()) - data_; - } - - uint32_t GetRestartPoint(uint32_t index) { - assert(index < num_restarts_); - return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); - } - - void SeekToRestartPoint(uint32_t index) { - key_.clear(); - restart_index_ = index; - // current_ will be fixed by ParseNextKey(); - - // ParseNextKey() starts at the end of value_, so set value_ accordingly - uint32_t offset = GetRestartPoint(index); - value_ = Slice(data_ + offset, 0); - } - - public: - Iter(const Comparator* comparator, - const char* data, - uint32_t restarts, - uint32_t num_restarts) - : comparator_(comparator), - data_(data), - restarts_(restarts), - num_restarts_(num_restarts), - current_(restarts_), - restart_index_(num_restarts_) { - assert(num_restarts_ > 0); - } - - virtual bool Valid() const { return current_ < restarts_; } - virtual Status status() const { return status_; } - virtual Slice key() const { - assert(Valid()); - return key_; - } - virtual Slice value() const { - assert(Valid()); - return value_; - } - - virtual void Next() { - assert(Valid()); - ParseNextKey(); - } - - virtual void Prev() { - assert(Valid()); - - // Scan backwards to a restart point before current_ - const uint32_t original = current_; - while (GetRestartPoint(restart_index_) >= original) { - if (restart_index_ == 0) { - // No more entries - current_ = restarts_; - restart_index_ = num_restarts_; - return; - } - restart_index_--; - } - - SeekToRestartPoint(restart_index_); - do { - // Loop until end of current entry hits the start of original entry - } while (ParseNextKey() && NextEntryOffset() < original); - } - - virtual void Seek(const Slice& target) { - // Binary search in restart array to find the last restart point - // with a key < target - uint32_t left = 0; - uint32_t right = num_restarts_ - 1; - while (left < right) { - uint32_t mid = (left + right + 1) / 2; - uint32_t region_offset = GetRestartPoint(mid); - uint32_t shared, non_shared, value_length; - const char* key_ptr = DecodeEntry(data_ + region_offset, - data_ + restarts_, - &shared, &non_shared, &value_length); - if (key_ptr == NULL || (shared != 0)) { - CorruptionError(); - return; - } - Slice mid_key(key_ptr, non_shared); - if (Compare(mid_key, target) < 0) { - // Key at "mid" is smaller than "target". Therefore all - // blocks before "mid" are uninteresting. - left = mid; - } else { - // Key at "mid" is >= "target". Therefore all blocks at or - // after "mid" are uninteresting. - right = mid - 1; - } - } - - // Linear search (within restart block) for first key >= target - SeekToRestartPoint(left); - while (true) { - if (!ParseNextKey()) { - return; - } - if (Compare(key_, target) >= 0) { - return; - } - } - } - - virtual void SeekToFirst() { - SeekToRestartPoint(0); - ParseNextKey(); - } - - virtual void SeekToLast() { - SeekToRestartPoint(num_restarts_ - 1); - while (ParseNextKey() && NextEntryOffset() < restarts_) { - // Keep skipping - } - } - - private: - void CorruptionError() { - current_ = restarts_; - restart_index_ = num_restarts_; - status_ = Status::Corruption("bad entry in block"); - key_.clear(); - value_.clear(); - } - - bool ParseNextKey() { - current_ = NextEntryOffset(); - const char* p = data_ + current_; - const char* limit = data_ + restarts_; // Restarts come right after data - if (p >= limit) { - // No more entries to return. Mark as invalid. - current_ = restarts_; - restart_index_ = num_restarts_; - return false; - } - - // Decode next entry - uint32_t shared, non_shared, value_length; - p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); - if (p == NULL || key_.size() < shared) { - CorruptionError(); - return false; - } else { - key_.resize(shared); - key_.append(p, non_shared); - value_ = Slice(p + non_shared, value_length); - while (restart_index_ + 1 < num_restarts_ && - GetRestartPoint(restart_index_ + 1) < current_) { - ++restart_index_; - } - return true; - } - } -}; - -Iterator* Block::NewIterator(const Comparator* cmp) { - if (size_ < sizeof(uint32_t)) { - return NewErrorIterator(Status::Corruption("bad block contents")); - } - const uint32_t num_restarts = NumRestarts(); - if (num_restarts == 0) { - return NewEmptyIterator(); - } else { - return new Iter(cmp, data_, restart_offset_, num_restarts); - } -} - -} // namespace leveldb diff --git a/src/leveldb/table/block.h b/src/leveldb/table/block.h deleted file mode 100644 index 2493eb9f9f..0000000000 --- a/src/leveldb/table/block.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ -#define STORAGE_LEVELDB_TABLE_BLOCK_H_ - -#include -#include -#include "leveldb/iterator.h" - -namespace leveldb { - -struct BlockContents; -class Comparator; - -class Block { - public: - // Initialize the block with the specified contents. - explicit Block(const BlockContents& contents); - - ~Block(); - - size_t size() const { return size_; } - Iterator* NewIterator(const Comparator* comparator); - - private: - uint32_t NumRestarts() const; - - const char* data_; - size_t size_; - uint32_t restart_offset_; // Offset in data_ of restart array - bool owned_; // Block owns data_[] - - // No copying allowed - Block(const Block&); - void operator=(const Block&); - - class Iter; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/src/leveldb/table/block_builder.cc b/src/leveldb/table/block_builder.cc deleted file mode 100644 index db660cd07c..0000000000 --- a/src/leveldb/table/block_builder.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// BlockBuilder generates blocks where keys are prefix-compressed: -// -// When we store a key, we drop the prefix shared with the previous -// string. This helps reduce the space requirement significantly. -// Furthermore, once every K keys, we do not apply the prefix -// compression and store the entire key. We call this a "restart -// point". The tail end of the block stores the offsets of all of the -// restart points, and can be used to do a binary search when looking -// for a particular key. Values are stored as-is (without compression) -// immediately following the corresponding key. -// -// An entry for a particular key-value pair has the form: -// shared_bytes: varint32 -// unshared_bytes: varint32 -// value_length: varint32 -// key_delta: char[unshared_bytes] -// value: char[value_length] -// shared_bytes == 0 for restart points. -// -// The trailer of the block has the form: -// restarts: uint32[num_restarts] -// num_restarts: uint32 -// restarts[i] contains the offset within the block of the ith restart point. - -#include "table/block_builder.h" - -#include -#include -#include "leveldb/comparator.h" -#include "leveldb/table_builder.h" -#include "util/coding.h" - -namespace leveldb { - -BlockBuilder::BlockBuilder(const Options* options) - : options_(options), - restarts_(), - counter_(0), - finished_(false) { - assert(options->block_restart_interval >= 1); - restarts_.push_back(0); // First restart point is at offset 0 -} - -void BlockBuilder::Reset() { - buffer_.clear(); - restarts_.clear(); - restarts_.push_back(0); // First restart point is at offset 0 - counter_ = 0; - finished_ = false; - last_key_.clear(); -} - -size_t BlockBuilder::CurrentSizeEstimate() const { - return (buffer_.size() + // Raw data buffer - restarts_.size() * sizeof(uint32_t) + // Restart array - sizeof(uint32_t)); // Restart array length -} - -Slice BlockBuilder::Finish() { - // Append restart array - for (size_t i = 0; i < restarts_.size(); i++) { - PutFixed32(&buffer_, restarts_[i]); - } - PutFixed32(&buffer_, restarts_.size()); - finished_ = true; - return Slice(buffer_); -} - -void BlockBuilder::Add(const Slice& key, const Slice& value) { - Slice last_key_piece(last_key_); - assert(!finished_); - assert(counter_ <= options_->block_restart_interval); - assert(buffer_.empty() // No values yet? - || options_->comparator->Compare(key, last_key_piece) > 0); - size_t shared = 0; - if (counter_ < options_->block_restart_interval) { - // See how much sharing to do with previous string - const size_t min_length = std::min(last_key_piece.size(), key.size()); - while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { - shared++; - } - } else { - // Restart compression - restarts_.push_back(buffer_.size()); - counter_ = 0; - } - const size_t non_shared = key.size() - shared; - - // Add "" to buffer_ - PutVarint32(&buffer_, shared); - PutVarint32(&buffer_, non_shared); - PutVarint32(&buffer_, value.size()); - - // Add string delta to buffer_ followed by value - buffer_.append(key.data() + shared, non_shared); - buffer_.append(value.data(), value.size()); - - // Update state - last_key_.resize(shared); - last_key_.append(key.data() + shared, non_shared); - assert(Slice(last_key_) == key); - counter_++; -} - -} // namespace leveldb diff --git a/src/leveldb/table/block_builder.h b/src/leveldb/table/block_builder.h deleted file mode 100644 index 4fbcb33972..0000000000 --- a/src/leveldb/table/block_builder.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ -#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ - -#include - -#include -#include "leveldb/slice.h" - -namespace leveldb { - -struct Options; - -class BlockBuilder { - public: - explicit BlockBuilder(const Options* options); - - // Reset the contents as if the BlockBuilder was just constructed. - void Reset(); - - // REQUIRES: Finish() has not been called since the last call to Reset(). - // REQUIRES: key is larger than any previously added key - void Add(const Slice& key, const Slice& value); - - // Finish building the block and return a slice that refers to the - // block contents. The returned slice will remain valid for the - // lifetime of this builder or until Reset() is called. - Slice Finish(); - - // Returns an estimate of the current (uncompressed) size of the block - // we are building. - size_t CurrentSizeEstimate() const; - - // Return true iff no entries have been added since the last Reset() - bool empty() const { - return buffer_.empty(); - } - - private: - const Options* options_; - std::string buffer_; // Destination buffer - std::vector restarts_; // Restart points - int counter_; // Number of entries emitted since restart - bool finished_; // Has Finish() been called? - std::string last_key_; - - // No copying allowed - BlockBuilder(const BlockBuilder&); - void operator=(const BlockBuilder&); -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/src/leveldb/table/filter_block.cc b/src/leveldb/table/filter_block.cc deleted file mode 100644 index 203e15c8bc..0000000000 --- a/src/leveldb/table/filter_block.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "table/filter_block.h" - -#include "leveldb/filter_policy.h" -#include "util/coding.h" - -namespace leveldb { - -// See doc/table_format.txt for an explanation of the filter block format. - -// Generate new filter every 2KB of data -static const size_t kFilterBaseLg = 11; -static const size_t kFilterBase = 1 << kFilterBaseLg; - -FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) - : policy_(policy) { -} - -void FilterBlockBuilder::StartBlock(uint64_t block_offset) { - uint64_t filter_index = (block_offset / kFilterBase); - assert(filter_index >= filter_offsets_.size()); - while (filter_index > filter_offsets_.size()) { - GenerateFilter(); - } -} - -void FilterBlockBuilder::AddKey(const Slice& key) { - Slice k = key; - start_.push_back(keys_.size()); - keys_.append(k.data(), k.size()); -} - -Slice FilterBlockBuilder::Finish() { - if (!start_.empty()) { - GenerateFilter(); - } - - // Append array of per-filter offsets - const uint32_t array_offset = result_.size(); - for (size_t i = 0; i < filter_offsets_.size(); i++) { - PutFixed32(&result_, filter_offsets_[i]); - } - - PutFixed32(&result_, array_offset); - result_.push_back(kFilterBaseLg); // Save encoding parameter in result - return Slice(result_); -} - -void FilterBlockBuilder::GenerateFilter() { - const size_t num_keys = start_.size(); - if (num_keys == 0) { - // Fast path if there are no keys for this filter - filter_offsets_.push_back(result_.size()); - return; - } - - // Make list of keys from flattened key structure - start_.push_back(keys_.size()); // Simplify length computation - tmp_keys_.resize(num_keys); - for (size_t i = 0; i < num_keys; i++) { - const char* base = keys_.data() + start_[i]; - size_t length = start_[i+1] - start_[i]; - tmp_keys_[i] = Slice(base, length); - } - - // Generate filter for current set of keys and append to result_. - filter_offsets_.push_back(result_.size()); - policy_->CreateFilter(&tmp_keys_[0], num_keys, &result_); - - tmp_keys_.clear(); - keys_.clear(); - start_.clear(); -} - -FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, - const Slice& contents) - : policy_(policy), - data_(NULL), - offset_(NULL), - num_(0), - base_lg_(0) { - size_t n = contents.size(); - if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array - base_lg_ = contents[n-1]; - uint32_t last_word = DecodeFixed32(contents.data() + n - 5); - if (last_word > n - 5) return; - data_ = contents.data(); - offset_ = data_ + last_word; - num_ = (n - 5 - last_word) / 4; -} - -bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { - uint64_t index = block_offset >> base_lg_; - if (index < num_) { - uint32_t start = DecodeFixed32(offset_ + index*4); - uint32_t limit = DecodeFixed32(offset_ + index*4 + 4); - if (start <= limit && limit <= (offset_ - data_)) { - Slice filter = Slice(data_ + start, limit - start); - return policy_->KeyMayMatch(key, filter); - } else if (start == limit) { - // Empty filters do not match any keys - return false; - } - } - return true; // Errors are treated as potential matches -} - -} diff --git a/src/leveldb/table/filter_block.h b/src/leveldb/table/filter_block.h deleted file mode 100644 index c67d010bd1..0000000000 --- a/src/leveldb/table/filter_block.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// A filter block is stored near the end of a Table file. It contains -// filters (e.g., bloom filters) for all data blocks in the table combined -// into a single filter block. - -#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ -#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ - -#include -#include -#include -#include -#include "leveldb/slice.h" -#include "util/hash.h" - -namespace leveldb { - -class FilterPolicy; - -// A FilterBlockBuilder is used to construct all of the filters for a -// particular Table. It generates a single string which is stored as -// a special block in the Table. -// -// The sequence of calls to FilterBlockBuilder must match the regexp: -// (StartBlock AddKey*)* Finish -class FilterBlockBuilder { - public: - explicit FilterBlockBuilder(const FilterPolicy*); - - void StartBlock(uint64_t block_offset); - void AddKey(const Slice& key); - Slice Finish(); - - private: - void GenerateFilter(); - - const FilterPolicy* policy_; - std::string keys_; // Flattened key contents - std::vector start_; // Starting index in keys_ of each key - std::string result_; // Filter data computed so far - std::vector tmp_keys_; // policy_->CreateFilter() argument - std::vector filter_offsets_; - - // No copying allowed - FilterBlockBuilder(const FilterBlockBuilder&); - void operator=(const FilterBlockBuilder&); -}; - -class FilterBlockReader { - public: - // REQUIRES: "contents" and *policy must stay live while *this is live. - FilterBlockReader(const FilterPolicy* policy, const Slice& contents); - bool KeyMayMatch(uint64_t block_offset, const Slice& key); - - private: - const FilterPolicy* policy_; - const char* data_; // Pointer to filter data (at block-start) - const char* offset_; // Pointer to beginning of offset array (at block-end) - size_t num_; // Number of entries in offset array - size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) -}; - -} - -#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/src/leveldb/table/filter_block_test.cc b/src/leveldb/table/filter_block_test.cc deleted file mode 100644 index 8c4a4741f2..0000000000 --- a/src/leveldb/table/filter_block_test.cc +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "table/filter_block.h" - -#include "leveldb/filter_policy.h" -#include "util/coding.h" -#include "util/hash.h" -#include "util/logging.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -// For testing: emit an array with one hash value per key -class TestHashFilter : public FilterPolicy { - public: - virtual const char* Name() const { - return "TestHashFilter"; - } - - virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { - for (int i = 0; i < n; i++) { - uint32_t h = Hash(keys[i].data(), keys[i].size(), 1); - PutFixed32(dst, h); - } - } - - virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { - uint32_t h = Hash(key.data(), key.size(), 1); - for (size_t i = 0; i + 4 <= filter.size(); i += 4) { - if (h == DecodeFixed32(filter.data() + i)) { - return true; - } - } - return false; - } -}; - -class FilterBlockTest { - public: - TestHashFilter policy_; -}; - -TEST(FilterBlockTest, EmptyBuilder) { - FilterBlockBuilder builder(&policy_); - Slice block = builder.Finish(); - ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block)); - FilterBlockReader reader(&policy_, block); - ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); - ASSERT_TRUE(reader.KeyMayMatch(100000, "foo")); -} - -TEST(FilterBlockTest, SingleChunk) { - FilterBlockBuilder builder(&policy_); - builder.StartBlock(100); - builder.AddKey("foo"); - builder.AddKey("bar"); - builder.AddKey("box"); - builder.StartBlock(200); - builder.AddKey("box"); - builder.StartBlock(300); - builder.AddKey("hello"); - Slice block = builder.Finish(); - FilterBlockReader reader(&policy_, block); - ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); - ASSERT_TRUE(reader.KeyMayMatch(100, "bar")); - ASSERT_TRUE(reader.KeyMayMatch(100, "box")); - ASSERT_TRUE(reader.KeyMayMatch(100, "hello")); - ASSERT_TRUE(reader.KeyMayMatch(100, "foo")); - ASSERT_TRUE(! reader.KeyMayMatch(100, "missing")); - ASSERT_TRUE(! reader.KeyMayMatch(100, "other")); -} - -TEST(FilterBlockTest, MultiChunk) { - FilterBlockBuilder builder(&policy_); - - // First filter - builder.StartBlock(0); - builder.AddKey("foo"); - builder.StartBlock(2000); - builder.AddKey("bar"); - - // Second filter - builder.StartBlock(3100); - builder.AddKey("box"); - - // Third filter is empty - - // Last filter - builder.StartBlock(9000); - builder.AddKey("box"); - builder.AddKey("hello"); - - Slice block = builder.Finish(); - FilterBlockReader reader(&policy_, block); - - // Check first filter - ASSERT_TRUE(reader.KeyMayMatch(0, "foo")); - ASSERT_TRUE(reader.KeyMayMatch(2000, "bar")); - ASSERT_TRUE(! reader.KeyMayMatch(0, "box")); - ASSERT_TRUE(! reader.KeyMayMatch(0, "hello")); - - // Check second filter - ASSERT_TRUE(reader.KeyMayMatch(3100, "box")); - ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo")); - ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar")); - ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello")); - - // Check third filter (empty) - ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo")); - ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar")); - ASSERT_TRUE(! reader.KeyMayMatch(4100, "box")); - ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello")); - - // Check last filter - ASSERT_TRUE(reader.KeyMayMatch(9000, "box")); - ASSERT_TRUE(reader.KeyMayMatch(9000, "hello")); - ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo")); - ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar")); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/table/format.cc b/src/leveldb/table/format.cc deleted file mode 100644 index aa63144c9e..0000000000 --- a/src/leveldb/table/format.cc +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "table/format.h" - -#include "leveldb/env.h" -#include "port/port.h" -#include "table/block.h" -#include "util/coding.h" -#include "util/crc32c.h" - -namespace leveldb { - -void BlockHandle::EncodeTo(std::string* dst) const { - // Sanity check that all fields have been set - assert(offset_ != ~static_cast(0)); - assert(size_ != ~static_cast(0)); - PutVarint64(dst, offset_); - PutVarint64(dst, size_); -} - -Status BlockHandle::DecodeFrom(Slice* input) { - if (GetVarint64(input, &offset_) && - GetVarint64(input, &size_)) { - return Status::OK(); - } else { - return Status::Corruption("bad block handle"); - } -} - -void Footer::EncodeTo(std::string* dst) const { -#ifndef NDEBUG - const size_t original_size = dst->size(); -#endif - metaindex_handle_.EncodeTo(dst); - index_handle_.EncodeTo(dst); - dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding - PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); - PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); - assert(dst->size() == original_size + kEncodedLength); -} - -Status Footer::DecodeFrom(Slice* input) { - const char* magic_ptr = input->data() + kEncodedLength - 8; - const uint32_t magic_lo = DecodeFixed32(magic_ptr); - const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); - const uint64_t magic = ((static_cast(magic_hi) << 32) | - (static_cast(magic_lo))); - if (magic != kTableMagicNumber) { - return Status::Corruption("not an sstable (bad magic number)"); - } - - Status result = metaindex_handle_.DecodeFrom(input); - if (result.ok()) { - result = index_handle_.DecodeFrom(input); - } - if (result.ok()) { - // We skip over any leftover data (just padding for now) in "input" - const char* end = magic_ptr + 8; - *input = Slice(end, input->data() + input->size() - end); - } - return result; -} - -Status ReadBlock(RandomAccessFile* file, - const ReadOptions& options, - const BlockHandle& handle, - BlockContents* result) { - result->data = Slice(); - result->cachable = false; - result->heap_allocated = false; - - // Read the block contents as well as the type/crc footer. - // See table_builder.cc for the code that built this structure. - size_t n = static_cast(handle.size()); - char* buf = new char[n + kBlockTrailerSize]; - Slice contents; - Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); - if (!s.ok()) { - delete[] buf; - return s; - } - if (contents.size() != n + kBlockTrailerSize) { - delete[] buf; - return Status::Corruption("truncated block read"); - } - - // Check the crc of the type and the block contents - const char* data = contents.data(); // Pointer to where Read put the data - if (options.verify_checksums) { - const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); - const uint32_t actual = crc32c::Value(data, n + 1); - if (actual != crc) { - delete[] buf; - s = Status::Corruption("block checksum mismatch"); - return s; - } - } - - switch (data[n]) { - case kNoCompression: - if (data != buf) { - // File implementation gave us pointer to some other data. - // Use it directly under the assumption that it will be live - // while the file is open. - delete[] buf; - result->data = Slice(data, n); - result->heap_allocated = false; - result->cachable = false; // Do not double-cache - } else { - result->data = Slice(buf, n); - result->heap_allocated = true; - result->cachable = true; - } - - // Ok - break; - case kSnappyCompression: { - size_t ulength = 0; - if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { - delete[] buf; - return Status::Corruption("corrupted compressed block contents"); - } - char* ubuf = new char[ulength]; - if (!port::Snappy_Uncompress(data, n, ubuf)) { - delete[] buf; - delete[] ubuf; - return Status::Corruption("corrupted compressed block contents"); - } - delete[] buf; - result->data = Slice(ubuf, ulength); - result->heap_allocated = true; - result->cachable = true; - break; - } - default: - delete[] buf; - return Status::Corruption("bad block type"); - } - - return Status::OK(); -} - -} // namespace leveldb diff --git a/src/leveldb/table/format.h b/src/leveldb/table/format.h deleted file mode 100644 index 6c0b80c017..0000000000 --- a/src/leveldb/table/format.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ -#define STORAGE_LEVELDB_TABLE_FORMAT_H_ - -#include -#include -#include "leveldb/slice.h" -#include "leveldb/status.h" -#include "leveldb/table_builder.h" - -namespace leveldb { - -class Block; -class RandomAccessFile; -struct ReadOptions; - -// BlockHandle is a pointer to the extent of a file that stores a data -// block or a meta block. -class BlockHandle { - public: - BlockHandle(); - - // The offset of the block in the file. - uint64_t offset() const { return offset_; } - void set_offset(uint64_t offset) { offset_ = offset; } - - // The size of the stored block - uint64_t size() const { return size_; } - void set_size(uint64_t size) { size_ = size; } - - void EncodeTo(std::string* dst) const; - Status DecodeFrom(Slice* input); - - // Maximum encoding length of a BlockHandle - enum { kMaxEncodedLength = 10 + 10 }; - - private: - uint64_t offset_; - uint64_t size_; -}; - -// Footer encapsulates the fixed information stored at the tail -// end of every table file. -class Footer { - public: - Footer() { } - - // The block handle for the metaindex block of the table - const BlockHandle& metaindex_handle() const { return metaindex_handle_; } - void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } - - // The block handle for the index block of the table - const BlockHandle& index_handle() const { - return index_handle_; - } - void set_index_handle(const BlockHandle& h) { - index_handle_ = h; - } - - void EncodeTo(std::string* dst) const; - Status DecodeFrom(Slice* input); - - // Encoded length of a Footer. Note that the serialization of a - // Footer will always occupy exactly this many bytes. It consists - // of two block handles and a magic number. - enum { - kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8 - }; - - private: - BlockHandle metaindex_handle_; - BlockHandle index_handle_; -}; - -// kTableMagicNumber was picked by running -// echo http://code.google.com/p/leveldb/ | sha1sum -// and taking the leading 64 bits. -static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; - -// 1-byte type + 32-bit crc -static const size_t kBlockTrailerSize = 5; - -struct BlockContents { - Slice data; // Actual contents of data - bool cachable; // True iff data can be cached - bool heap_allocated; // True iff caller should delete[] data.data() -}; - -// Read the block identified by "handle" from "file". On failure -// return non-OK. On success fill *result and return OK. -extern Status ReadBlock(RandomAccessFile* file, - const ReadOptions& options, - const BlockHandle& handle, - BlockContents* result); - -// Implementation details follow. Clients should ignore, - -inline BlockHandle::BlockHandle() - : offset_(~static_cast(0)), - size_(~static_cast(0)) { -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/src/leveldb/table/iterator.cc b/src/leveldb/table/iterator.cc deleted file mode 100644 index 3d1c87fdec..0000000000 --- a/src/leveldb/table/iterator.cc +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/iterator.h" - -namespace leveldb { - -Iterator::Iterator() { - cleanup_.function = NULL; - cleanup_.next = NULL; -} - -Iterator::~Iterator() { - if (cleanup_.function != NULL) { - (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); - for (Cleanup* c = cleanup_.next; c != NULL; ) { - (*c->function)(c->arg1, c->arg2); - Cleanup* next = c->next; - delete c; - c = next; - } - } -} - -void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { - assert(func != NULL); - Cleanup* c; - if (cleanup_.function == NULL) { - c = &cleanup_; - } else { - c = new Cleanup; - c->next = cleanup_.next; - cleanup_.next = c; - } - c->function = func; - c->arg1 = arg1; - c->arg2 = arg2; -} - -namespace { -class EmptyIterator : public Iterator { - public: - EmptyIterator(const Status& s) : status_(s) { } - virtual bool Valid() const { return false; } - virtual void Seek(const Slice& target) { } - virtual void SeekToFirst() { } - virtual void SeekToLast() { } - virtual void Next() { assert(false); } - virtual void Prev() { assert(false); } - Slice key() const { assert(false); return Slice(); } - Slice value() const { assert(false); return Slice(); } - virtual Status status() const { return status_; } - private: - Status status_; -}; -} // namespace - -Iterator* NewEmptyIterator() { - return new EmptyIterator(Status::OK()); -} - -Iterator* NewErrorIterator(const Status& status) { - return new EmptyIterator(status); -} - -} // namespace leveldb diff --git a/src/leveldb/table/iterator_wrapper.h b/src/leveldb/table/iterator_wrapper.h deleted file mode 100644 index 9e16b3dbed..0000000000 --- a/src/leveldb/table/iterator_wrapper.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ -#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ - -namespace leveldb { - -// A internal wrapper class with an interface similar to Iterator that -// caches the valid() and key() results for an underlying iterator. -// This can help avoid virtual function calls and also gives better -// cache locality. -class IteratorWrapper { - public: - IteratorWrapper(): iter_(NULL), valid_(false) { } - explicit IteratorWrapper(Iterator* iter): iter_(NULL) { - Set(iter); - } - ~IteratorWrapper() { delete iter_; } - Iterator* iter() const { return iter_; } - - // Takes ownership of "iter" and will delete it when destroyed, or - // when Set() is invoked again. - void Set(Iterator* iter) { - delete iter_; - iter_ = iter; - if (iter_ == NULL) { - valid_ = false; - } else { - Update(); - } - } - - - // Iterator interface methods - bool Valid() const { return valid_; } - Slice key() const { assert(Valid()); return key_; } - Slice value() const { assert(Valid()); return iter_->value(); } - // Methods below require iter() != NULL - Status status() const { assert(iter_); return iter_->status(); } - void Next() { assert(iter_); iter_->Next(); Update(); } - void Prev() { assert(iter_); iter_->Prev(); Update(); } - void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); } - void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); } - void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); } - - private: - void Update() { - valid_ = iter_->Valid(); - if (valid_) { - key_ = iter_->key(); - } - } - - Iterator* iter_; - bool valid_; - Slice key_; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/src/leveldb/table/merger.cc b/src/leveldb/table/merger.cc deleted file mode 100644 index 2dde4dc21f..0000000000 --- a/src/leveldb/table/merger.cc +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "table/merger.h" - -#include "leveldb/comparator.h" -#include "leveldb/iterator.h" -#include "table/iterator_wrapper.h" - -namespace leveldb { - -namespace { -class MergingIterator : public Iterator { - public: - MergingIterator(const Comparator* comparator, Iterator** children, int n) - : comparator_(comparator), - children_(new IteratorWrapper[n]), - n_(n), - current_(NULL), - direction_(kForward) { - for (int i = 0; i < n; i++) { - children_[i].Set(children[i]); - } - } - - virtual ~MergingIterator() { - delete[] children_; - } - - virtual bool Valid() const { - return (current_ != NULL); - } - - virtual void SeekToFirst() { - for (int i = 0; i < n_; i++) { - children_[i].SeekToFirst(); - } - FindSmallest(); - direction_ = kForward; - } - - virtual void SeekToLast() { - for (int i = 0; i < n_; i++) { - children_[i].SeekToLast(); - } - FindLargest(); - direction_ = kReverse; - } - - virtual void Seek(const Slice& target) { - for (int i = 0; i < n_; i++) { - children_[i].Seek(target); - } - FindSmallest(); - direction_ = kForward; - } - - virtual void Next() { - assert(Valid()); - - // Ensure that all children are positioned after key(). - // If we are moving in the forward direction, it is already - // true for all of the non-current_ children since current_ is - // the smallest child and key() == current_->key(). Otherwise, - // we explicitly position the non-current_ children. - if (direction_ != kForward) { - for (int i = 0; i < n_; i++) { - IteratorWrapper* child = &children_[i]; - if (child != current_) { - child->Seek(key()); - if (child->Valid() && - comparator_->Compare(key(), child->key()) == 0) { - child->Next(); - } - } - } - direction_ = kForward; - } - - current_->Next(); - FindSmallest(); - } - - virtual void Prev() { - assert(Valid()); - - // Ensure that all children are positioned before key(). - // If we are moving in the reverse direction, it is already - // true for all of the non-current_ children since current_ is - // the largest child and key() == current_->key(). Otherwise, - // we explicitly position the non-current_ children. - if (direction_ != kReverse) { - for (int i = 0; i < n_; i++) { - IteratorWrapper* child = &children_[i]; - if (child != current_) { - child->Seek(key()); - if (child->Valid()) { - // Child is at first entry >= key(). Step back one to be < key() - child->Prev(); - } else { - // Child has no entries >= key(). Position at last entry. - child->SeekToLast(); - } - } - } - direction_ = kReverse; - } - - current_->Prev(); - FindLargest(); - } - - virtual Slice key() const { - assert(Valid()); - return current_->key(); - } - - virtual Slice value() const { - assert(Valid()); - return current_->value(); - } - - virtual Status status() const { - Status status; - for (int i = 0; i < n_; i++) { - status = children_[i].status(); - if (!status.ok()) { - break; - } - } - return status; - } - - private: - void FindSmallest(); - void FindLargest(); - - // We might want to use a heap in case there are lots of children. - // For now we use a simple array since we expect a very small number - // of children in leveldb. - const Comparator* comparator_; - IteratorWrapper* children_; - int n_; - IteratorWrapper* current_; - - // Which direction is the iterator moving? - enum Direction { - kForward, - kReverse - }; - Direction direction_; -}; - -void MergingIterator::FindSmallest() { - IteratorWrapper* smallest = NULL; - for (int i = 0; i < n_; i++) { - IteratorWrapper* child = &children_[i]; - if (child->Valid()) { - if (smallest == NULL) { - smallest = child; - } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { - smallest = child; - } - } - } - current_ = smallest; -} - -void MergingIterator::FindLargest() { - IteratorWrapper* largest = NULL; - for (int i = n_-1; i >= 0; i--) { - IteratorWrapper* child = &children_[i]; - if (child->Valid()) { - if (largest == NULL) { - largest = child; - } else if (comparator_->Compare(child->key(), largest->key()) > 0) { - largest = child; - } - } - } - current_ = largest; -} -} // namespace - -Iterator* NewMergingIterator(const Comparator* cmp, Iterator** list, int n) { - assert(n >= 0); - if (n == 0) { - return NewEmptyIterator(); - } else if (n == 1) { - return list[0]; - } else { - return new MergingIterator(cmp, list, n); - } -} - -} // namespace leveldb diff --git a/src/leveldb/table/merger.h b/src/leveldb/table/merger.h deleted file mode 100644 index 91ddd80faa..0000000000 --- a/src/leveldb/table/merger.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ -#define STORAGE_LEVELDB_TABLE_MERGER_H_ - -namespace leveldb { - -class Comparator; -class Iterator; - -// Return an iterator that provided the union of the data in -// children[0,n-1]. Takes ownership of the child iterators and -// will delete them when the result iterator is deleted. -// -// The result does no duplicate suppression. I.e., if a particular -// key is present in K child iterators, it will be yielded K times. -// -// REQUIRES: n >= 0 -extern Iterator* NewMergingIterator( - const Comparator* comparator, Iterator** children, int n); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/src/leveldb/table/table.cc b/src/leveldb/table/table.cc deleted file mode 100644 index dff8a82590..0000000000 --- a/src/leveldb/table/table.cc +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/table.h" - -#include "leveldb/cache.h" -#include "leveldb/comparator.h" -#include "leveldb/env.h" -#include "leveldb/filter_policy.h" -#include "leveldb/options.h" -#include "table/block.h" -#include "table/filter_block.h" -#include "table/format.h" -#include "table/two_level_iterator.h" -#include "util/coding.h" - -namespace leveldb { - -struct Table::Rep { - ~Rep() { - delete filter; - delete [] filter_data; - delete index_block; - } - - Options options; - Status status; - RandomAccessFile* file; - uint64_t cache_id; - FilterBlockReader* filter; - const char* filter_data; - - BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer - Block* index_block; -}; - -Status Table::Open(const Options& options, - RandomAccessFile* file, - uint64_t size, - Table** table) { - *table = NULL; - if (size < Footer::kEncodedLength) { - return Status::Corruption("file is too short to be an sstable"); - } - - char footer_space[Footer::kEncodedLength]; - Slice footer_input; - Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, - &footer_input, footer_space); - if (!s.ok()) return s; - - Footer footer; - s = footer.DecodeFrom(&footer_input); - if (!s.ok()) return s; - - // Read the index block - BlockContents contents; - Block* index_block = NULL; - if (s.ok()) { - ReadOptions opt; - if (options.paranoid_checks) { - opt.verify_checksums = true; - } - s = ReadBlock(file, opt, footer.index_handle(), &contents); - if (s.ok()) { - index_block = new Block(contents); - } - } - - if (s.ok()) { - // We've successfully read the footer and the index block: we're - // ready to serve requests. - Rep* rep = new Table::Rep; - rep->options = options; - rep->file = file; - rep->metaindex_handle = footer.metaindex_handle(); - rep->index_block = index_block; - rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0); - rep->filter_data = NULL; - rep->filter = NULL; - *table = new Table(rep); - (*table)->ReadMeta(footer); - } else { - if (index_block) delete index_block; - } - - return s; -} - -void Table::ReadMeta(const Footer& footer) { - if (rep_->options.filter_policy == NULL) { - return; // Do not need any metadata - } - - // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates - // it is an empty block. - ReadOptions opt; - if (rep_->options.paranoid_checks) { - opt.verify_checksums = true; - } - BlockContents contents; - if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) { - // Do not propagate errors since meta info is not needed for operation - return; - } - Block* meta = new Block(contents); - - Iterator* iter = meta->NewIterator(BytewiseComparator()); - std::string key = "filter."; - key.append(rep_->options.filter_policy->Name()); - iter->Seek(key); - if (iter->Valid() && iter->key() == Slice(key)) { - ReadFilter(iter->value()); - } - delete iter; - delete meta; -} - -void Table::ReadFilter(const Slice& filter_handle_value) { - Slice v = filter_handle_value; - BlockHandle filter_handle; - if (!filter_handle.DecodeFrom(&v).ok()) { - return; - } - - // We might want to unify with ReadBlock() if we start - // requiring checksum verification in Table::Open. - ReadOptions opt; - if (rep_->options.paranoid_checks) { - opt.verify_checksums = true; - } - BlockContents block; - if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) { - return; - } - if (block.heap_allocated) { - rep_->filter_data = block.data.data(); // Will need to delete later - } - rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); -} - -Table::~Table() { - delete rep_; -} - -static void DeleteBlock(void* arg, void* ignored) { - delete reinterpret_cast(arg); -} - -static void DeleteCachedBlock(const Slice& key, void* value) { - Block* block = reinterpret_cast(value); - delete block; -} - -static void ReleaseBlock(void* arg, void* h) { - Cache* cache = reinterpret_cast(arg); - Cache::Handle* handle = reinterpret_cast(h); - cache->Release(handle); -} - -// Convert an index iterator value (i.e., an encoded BlockHandle) -// into an iterator over the contents of the corresponding block. -Iterator* Table::BlockReader(void* arg, - const ReadOptions& options, - const Slice& index_value) { - Table* table = reinterpret_cast(arg); - Cache* block_cache = table->rep_->options.block_cache; - Block* block = NULL; - Cache::Handle* cache_handle = NULL; - - BlockHandle handle; - Slice input = index_value; - Status s = handle.DecodeFrom(&input); - // We intentionally allow extra stuff in index_value so that we - // can add more features in the future. - - if (s.ok()) { - BlockContents contents; - if (block_cache != NULL) { - char cache_key_buffer[16]; - EncodeFixed64(cache_key_buffer, table->rep_->cache_id); - EncodeFixed64(cache_key_buffer+8, handle.offset()); - Slice key(cache_key_buffer, sizeof(cache_key_buffer)); - cache_handle = block_cache->Lookup(key); - if (cache_handle != NULL) { - block = reinterpret_cast(block_cache->Value(cache_handle)); - } else { - s = ReadBlock(table->rep_->file, options, handle, &contents); - if (s.ok()) { - block = new Block(contents); - if (contents.cachable && options.fill_cache) { - cache_handle = block_cache->Insert( - key, block, block->size(), &DeleteCachedBlock); - } - } - } - } else { - s = ReadBlock(table->rep_->file, options, handle, &contents); - if (s.ok()) { - block = new Block(contents); - } - } - } - - Iterator* iter; - if (block != NULL) { - iter = block->NewIterator(table->rep_->options.comparator); - if (cache_handle == NULL) { - iter->RegisterCleanup(&DeleteBlock, block, NULL); - } else { - iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); - } - } else { - iter = NewErrorIterator(s); - } - return iter; -} - -Iterator* Table::NewIterator(const ReadOptions& options) const { - return NewTwoLevelIterator( - rep_->index_block->NewIterator(rep_->options.comparator), - &Table::BlockReader, const_cast(this), options); -} - -Status Table::InternalGet(const ReadOptions& options, const Slice& k, - void* arg, - void (*saver)(void*, const Slice&, const Slice&)) { - Status s; - Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); - iiter->Seek(k); - if (iiter->Valid()) { - Slice handle_value = iiter->value(); - FilterBlockReader* filter = rep_->filter; - BlockHandle handle; - if (filter != NULL && - handle.DecodeFrom(&handle_value).ok() && - !filter->KeyMayMatch(handle.offset(), k)) { - // Not found - } else { - Iterator* block_iter = BlockReader(this, options, iiter->value()); - block_iter->Seek(k); - if (block_iter->Valid()) { - (*saver)(arg, block_iter->key(), block_iter->value()); - } - s = block_iter->status(); - delete block_iter; - } - } - if (s.ok()) { - s = iiter->status(); - } - delete iiter; - return s; -} - - -uint64_t Table::ApproximateOffsetOf(const Slice& key) const { - Iterator* index_iter = - rep_->index_block->NewIterator(rep_->options.comparator); - index_iter->Seek(key); - uint64_t result; - if (index_iter->Valid()) { - BlockHandle handle; - Slice input = index_iter->value(); - Status s = handle.DecodeFrom(&input); - if (s.ok()) { - result = handle.offset(); - } else { - // Strange: we can't decode the block handle in the index block. - // We'll just return the offset of the metaindex block, which is - // close to the whole file size for this case. - result = rep_->metaindex_handle.offset(); - } - } else { - // key is past the last key in the file. Approximate the offset - // by returning the offset of the metaindex block (which is - // right near the end of the file). - result = rep_->metaindex_handle.offset(); - } - delete index_iter; - return result; -} - -} // namespace leveldb diff --git a/src/leveldb/table/table_builder.cc b/src/leveldb/table/table_builder.cc deleted file mode 100644 index 62002c84f2..0000000000 --- a/src/leveldb/table/table_builder.cc +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/table_builder.h" - -#include -#include "leveldb/comparator.h" -#include "leveldb/env.h" -#include "leveldb/filter_policy.h" -#include "leveldb/options.h" -#include "table/block_builder.h" -#include "table/filter_block.h" -#include "table/format.h" -#include "util/coding.h" -#include "util/crc32c.h" - -namespace leveldb { - -struct TableBuilder::Rep { - Options options; - Options index_block_options; - WritableFile* file; - uint64_t offset; - Status status; - BlockBuilder data_block; - BlockBuilder index_block; - std::string last_key; - int64_t num_entries; - bool closed; // Either Finish() or Abandon() has been called. - FilterBlockBuilder* filter_block; - - // We do not emit the index entry for a block until we have seen the - // first key for the next data block. This allows us to use shorter - // keys in the index block. For example, consider a block boundary - // between the keys "the quick brown fox" and "the who". We can use - // "the r" as the key for the index block entry since it is >= all - // entries in the first block and < all entries in subsequent - // blocks. - // - // Invariant: r->pending_index_entry is true only if data_block is empty. - bool pending_index_entry; - BlockHandle pending_handle; // Handle to add to index block - - std::string compressed_output; - - Rep(const Options& opt, WritableFile* f) - : options(opt), - index_block_options(opt), - file(f), - offset(0), - data_block(&options), - index_block(&index_block_options), - num_entries(0), - closed(false), - filter_block(opt.filter_policy == NULL ? NULL - : new FilterBlockBuilder(opt.filter_policy)), - pending_index_entry(false) { - index_block_options.block_restart_interval = 1; - } -}; - -TableBuilder::TableBuilder(const Options& options, WritableFile* file) - : rep_(new Rep(options, file)) { - if (rep_->filter_block != NULL) { - rep_->filter_block->StartBlock(0); - } -} - -TableBuilder::~TableBuilder() { - assert(rep_->closed); // Catch errors where caller forgot to call Finish() - delete rep_->filter_block; - delete rep_; -} - -Status TableBuilder::ChangeOptions(const Options& options) { - // Note: if more fields are added to Options, update - // this function to catch changes that should not be allowed to - // change in the middle of building a Table. - if (options.comparator != rep_->options.comparator) { - return Status::InvalidArgument("changing comparator while building table"); - } - - // Note that any live BlockBuilders point to rep_->options and therefore - // will automatically pick up the updated options. - rep_->options = options; - rep_->index_block_options = options; - rep_->index_block_options.block_restart_interval = 1; - return Status::OK(); -} - -void TableBuilder::Add(const Slice& key, const Slice& value) { - Rep* r = rep_; - assert(!r->closed); - if (!ok()) return; - if (r->num_entries > 0) { - assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); - } - - if (r->pending_index_entry) { - assert(r->data_block.empty()); - r->options.comparator->FindShortestSeparator(&r->last_key, key); - std::string handle_encoding; - r->pending_handle.EncodeTo(&handle_encoding); - r->index_block.Add(r->last_key, Slice(handle_encoding)); - r->pending_index_entry = false; - } - - if (r->filter_block != NULL) { - r->filter_block->AddKey(key); - } - - r->last_key.assign(key.data(), key.size()); - r->num_entries++; - r->data_block.Add(key, value); - - const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); - if (estimated_block_size >= r->options.block_size) { - Flush(); - } -} - -void TableBuilder::Flush() { - Rep* r = rep_; - assert(!r->closed); - if (!ok()) return; - if (r->data_block.empty()) return; - assert(!r->pending_index_entry); - WriteBlock(&r->data_block, &r->pending_handle); - if (ok()) { - r->pending_index_entry = true; - r->status = r->file->Flush(); - } - if (r->filter_block != NULL) { - r->filter_block->StartBlock(r->offset); - } -} - -void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { - // File format contains a sequence of blocks where each block has: - // block_data: uint8[n] - // type: uint8 - // crc: uint32 - assert(ok()); - Rep* r = rep_; - Slice raw = block->Finish(); - - Slice block_contents; - CompressionType type = r->options.compression; - // TODO(postrelease): Support more compression options: zlib? - switch (type) { - case kNoCompression: - block_contents = raw; - break; - - case kSnappyCompression: { - std::string* compressed = &r->compressed_output; - if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && - compressed->size() < raw.size() - (raw.size() / 8u)) { - block_contents = *compressed; - } else { - // Snappy not supported, or compressed less than 12.5%, so just - // store uncompressed form - block_contents = raw; - type = kNoCompression; - } - break; - } - } - WriteRawBlock(block_contents, type, handle); - r->compressed_output.clear(); - block->Reset(); -} - -void TableBuilder::WriteRawBlock(const Slice& block_contents, - CompressionType type, - BlockHandle* handle) { - Rep* r = rep_; - handle->set_offset(r->offset); - handle->set_size(block_contents.size()); - r->status = r->file->Append(block_contents); - if (r->status.ok()) { - char trailer[kBlockTrailerSize]; - trailer[0] = type; - uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); - crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type - EncodeFixed32(trailer+1, crc32c::Mask(crc)); - r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); - if (r->status.ok()) { - r->offset += block_contents.size() + kBlockTrailerSize; - } - } -} - -Status TableBuilder::status() const { - return rep_->status; -} - -Status TableBuilder::Finish() { - Rep* r = rep_; - Flush(); - assert(!r->closed); - r->closed = true; - - BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; - - // Write filter block - if (ok() && r->filter_block != NULL) { - WriteRawBlock(r->filter_block->Finish(), kNoCompression, - &filter_block_handle); - } - - // Write metaindex block - if (ok()) { - BlockBuilder meta_index_block(&r->options); - if (r->filter_block != NULL) { - // Add mapping from "filter.Name" to location of filter data - std::string key = "filter."; - key.append(r->options.filter_policy->Name()); - std::string handle_encoding; - filter_block_handle.EncodeTo(&handle_encoding); - meta_index_block.Add(key, handle_encoding); - } - - // TODO(postrelease): Add stats and other meta blocks - WriteBlock(&meta_index_block, &metaindex_block_handle); - } - - // Write index block - if (ok()) { - if (r->pending_index_entry) { - r->options.comparator->FindShortSuccessor(&r->last_key); - std::string handle_encoding; - r->pending_handle.EncodeTo(&handle_encoding); - r->index_block.Add(r->last_key, Slice(handle_encoding)); - r->pending_index_entry = false; - } - WriteBlock(&r->index_block, &index_block_handle); - } - - // Write footer - if (ok()) { - Footer footer; - footer.set_metaindex_handle(metaindex_block_handle); - footer.set_index_handle(index_block_handle); - std::string footer_encoding; - footer.EncodeTo(&footer_encoding); - r->status = r->file->Append(footer_encoding); - if (r->status.ok()) { - r->offset += footer_encoding.size(); - } - } - return r->status; -} - -void TableBuilder::Abandon() { - Rep* r = rep_; - assert(!r->closed); - r->closed = true; -} - -uint64_t TableBuilder::NumEntries() const { - return rep_->num_entries; -} - -uint64_t TableBuilder::FileSize() const { - return rep_->offset; -} - -} // namespace leveldb diff --git a/src/leveldb/table/table_test.cc b/src/leveldb/table/table_test.cc deleted file mode 100644 index c723bf84cf..0000000000 --- a/src/leveldb/table/table_test.cc +++ /dev/null @@ -1,868 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/table.h" - -#include -#include -#include "db/dbformat.h" -#include "db/memtable.h" -#include "db/write_batch_internal.h" -#include "leveldb/db.h" -#include "leveldb/env.h" -#include "leveldb/iterator.h" -#include "leveldb/table_builder.h" -#include "table/block.h" -#include "table/block_builder.h" -#include "table/format.h" -#include "util/random.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -// Return reverse of "key". -// Used to test non-lexicographic comparators. -static std::string Reverse(const Slice& key) { - std::string str(key.ToString()); - std::string rev(""); - for (std::string::reverse_iterator rit = str.rbegin(); - rit != str.rend(); ++rit) { - rev.push_back(*rit); - } - return rev; -} - -namespace { -class ReverseKeyComparator : public Comparator { - public: - virtual const char* Name() const { - return "leveldb.ReverseBytewiseComparator"; - } - - virtual int Compare(const Slice& a, const Slice& b) const { - return BytewiseComparator()->Compare(Reverse(a), Reverse(b)); - } - - virtual void FindShortestSeparator( - std::string* start, - const Slice& limit) const { - std::string s = Reverse(*start); - std::string l = Reverse(limit); - BytewiseComparator()->FindShortestSeparator(&s, l); - *start = Reverse(s); - } - - virtual void FindShortSuccessor(std::string* key) const { - std::string s = Reverse(*key); - BytewiseComparator()->FindShortSuccessor(&s); - *key = Reverse(s); - } -}; -} // namespace -static ReverseKeyComparator reverse_key_comparator; - -static void Increment(const Comparator* cmp, std::string* key) { - if (cmp == BytewiseComparator()) { - key->push_back('\0'); - } else { - assert(cmp == &reverse_key_comparator); - std::string rev = Reverse(*key); - rev.push_back('\0'); - *key = Reverse(rev); - } -} - -// An STL comparator that uses a Comparator -namespace { -struct STLLessThan { - const Comparator* cmp; - - STLLessThan() : cmp(BytewiseComparator()) { } - STLLessThan(const Comparator* c) : cmp(c) { } - bool operator()(const std::string& a, const std::string& b) const { - return cmp->Compare(Slice(a), Slice(b)) < 0; - } -}; -} // namespace - -class StringSink: public WritableFile { - public: - ~StringSink() { } - - const std::string& contents() const { return contents_; } - - virtual Status Close() { return Status::OK(); } - virtual Status Flush() { return Status::OK(); } - virtual Status Sync() { return Status::OK(); } - - virtual Status Append(const Slice& data) { - contents_.append(data.data(), data.size()); - return Status::OK(); - } - - private: - std::string contents_; -}; - - -class StringSource: public RandomAccessFile { - public: - StringSource(const Slice& contents) - : contents_(contents.data(), contents.size()) { - } - - virtual ~StringSource() { } - - uint64_t Size() const { return contents_.size(); } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const { - if (offset > contents_.size()) { - return Status::InvalidArgument("invalid Read offset"); - } - if (offset + n > contents_.size()) { - n = contents_.size() - offset; - } - memcpy(scratch, &contents_[offset], n); - *result = Slice(scratch, n); - return Status::OK(); - } - - private: - std::string contents_; -}; - -typedef std::map KVMap; - -// Helper class for tests to unify the interface between -// BlockBuilder/TableBuilder and Block/Table. -class Constructor { - public: - explicit Constructor(const Comparator* cmp) : data_(STLLessThan(cmp)) { } - virtual ~Constructor() { } - - void Add(const std::string& key, const Slice& value) { - data_[key] = value.ToString(); - } - - // Finish constructing the data structure with all the keys that have - // been added so far. Returns the keys in sorted order in "*keys" - // and stores the key/value pairs in "*kvmap" - void Finish(const Options& options, - std::vector* keys, - KVMap* kvmap) { - *kvmap = data_; - keys->clear(); - for (KVMap::const_iterator it = data_.begin(); - it != data_.end(); - ++it) { - keys->push_back(it->first); - } - data_.clear(); - Status s = FinishImpl(options, *kvmap); - ASSERT_TRUE(s.ok()) << s.ToString(); - } - - // Construct the data structure from the data in "data" - virtual Status FinishImpl(const Options& options, const KVMap& data) = 0; - - virtual Iterator* NewIterator() const = 0; - - virtual const KVMap& data() { return data_; } - - virtual DB* db() const { return NULL; } // Overridden in DBConstructor - - private: - KVMap data_; -}; - -class BlockConstructor: public Constructor { - public: - explicit BlockConstructor(const Comparator* cmp) - : Constructor(cmp), - comparator_(cmp), - block_(NULL) { } - ~BlockConstructor() { - delete block_; - } - virtual Status FinishImpl(const Options& options, const KVMap& data) { - delete block_; - block_ = NULL; - BlockBuilder builder(&options); - - for (KVMap::const_iterator it = data.begin(); - it != data.end(); - ++it) { - builder.Add(it->first, it->second); - } - // Open the block - data_ = builder.Finish().ToString(); - BlockContents contents; - contents.data = data_; - contents.cachable = false; - contents.heap_allocated = false; - block_ = new Block(contents); - return Status::OK(); - } - virtual Iterator* NewIterator() const { - return block_->NewIterator(comparator_); - } - - private: - const Comparator* comparator_; - std::string data_; - Block* block_; - - BlockConstructor(); -}; - -class TableConstructor: public Constructor { - public: - TableConstructor(const Comparator* cmp) - : Constructor(cmp), - source_(NULL), table_(NULL) { - } - ~TableConstructor() { - Reset(); - } - virtual Status FinishImpl(const Options& options, const KVMap& data) { - Reset(); - StringSink sink; - TableBuilder builder(options, &sink); - - for (KVMap::const_iterator it = data.begin(); - it != data.end(); - ++it) { - builder.Add(it->first, it->second); - ASSERT_TRUE(builder.status().ok()); - } - Status s = builder.Finish(); - ASSERT_TRUE(s.ok()) << s.ToString(); - - ASSERT_EQ(sink.contents().size(), builder.FileSize()); - - // Open the table - source_ = new StringSource(sink.contents()); - Options table_options; - table_options.comparator = options.comparator; - return Table::Open(table_options, source_, sink.contents().size(), &table_); - } - - virtual Iterator* NewIterator() const { - return table_->NewIterator(ReadOptions()); - } - - uint64_t ApproximateOffsetOf(const Slice& key) const { - return table_->ApproximateOffsetOf(key); - } - - private: - void Reset() { - delete table_; - delete source_; - table_ = NULL; - source_ = NULL; - } - - StringSource* source_; - Table* table_; - - TableConstructor(); -}; - -// A helper class that converts internal format keys into user keys -class KeyConvertingIterator: public Iterator { - public: - explicit KeyConvertingIterator(Iterator* iter) : iter_(iter) { } - virtual ~KeyConvertingIterator() { delete iter_; } - virtual bool Valid() const { return iter_->Valid(); } - virtual void Seek(const Slice& target) { - ParsedInternalKey ikey(target, kMaxSequenceNumber, kTypeValue); - std::string encoded; - AppendInternalKey(&encoded, ikey); - iter_->Seek(encoded); - } - virtual void SeekToFirst() { iter_->SeekToFirst(); } - virtual void SeekToLast() { iter_->SeekToLast(); } - virtual void Next() { iter_->Next(); } - virtual void Prev() { iter_->Prev(); } - - virtual Slice key() const { - assert(Valid()); - ParsedInternalKey key; - if (!ParseInternalKey(iter_->key(), &key)) { - status_ = Status::Corruption("malformed internal key"); - return Slice("corrupted key"); - } - return key.user_key; - } - - virtual Slice value() const { return iter_->value(); } - virtual Status status() const { - return status_.ok() ? iter_->status() : status_; - } - - private: - mutable Status status_; - Iterator* iter_; - - // No copying allowed - KeyConvertingIterator(const KeyConvertingIterator&); - void operator=(const KeyConvertingIterator&); -}; - -class MemTableConstructor: public Constructor { - public: - explicit MemTableConstructor(const Comparator* cmp) - : Constructor(cmp), - internal_comparator_(cmp) { - memtable_ = new MemTable(internal_comparator_); - memtable_->Ref(); - } - ~MemTableConstructor() { - memtable_->Unref(); - } - virtual Status FinishImpl(const Options& options, const KVMap& data) { - memtable_->Unref(); - memtable_ = new MemTable(internal_comparator_); - memtable_->Ref(); - int seq = 1; - for (KVMap::const_iterator it = data.begin(); - it != data.end(); - ++it) { - memtable_->Add(seq, kTypeValue, it->first, it->second); - seq++; - } - return Status::OK(); - } - virtual Iterator* NewIterator() const { - return new KeyConvertingIterator(memtable_->NewIterator()); - } - - private: - InternalKeyComparator internal_comparator_; - MemTable* memtable_; -}; - -class DBConstructor: public Constructor { - public: - explicit DBConstructor(const Comparator* cmp) - : Constructor(cmp), - comparator_(cmp) { - db_ = NULL; - NewDB(); - } - ~DBConstructor() { - delete db_; - } - virtual Status FinishImpl(const Options& options, const KVMap& data) { - delete db_; - db_ = NULL; - NewDB(); - for (KVMap::const_iterator it = data.begin(); - it != data.end(); - ++it) { - WriteBatch batch; - batch.Put(it->first, it->second); - ASSERT_TRUE(db_->Write(WriteOptions(), &batch).ok()); - } - return Status::OK(); - } - virtual Iterator* NewIterator() const { - return db_->NewIterator(ReadOptions()); - } - - virtual DB* db() const { return db_; } - - private: - void NewDB() { - std::string name = test::TmpDir() + "/table_testdb"; - - Options options; - options.comparator = comparator_; - Status status = DestroyDB(name, options); - ASSERT_TRUE(status.ok()) << status.ToString(); - - options.create_if_missing = true; - options.error_if_exists = true; - options.write_buffer_size = 10000; // Something small to force merging - status = DB::Open(options, name, &db_); - ASSERT_TRUE(status.ok()) << status.ToString(); - } - - const Comparator* comparator_; - DB* db_; -}; - -enum TestType { - TABLE_TEST, - BLOCK_TEST, - MEMTABLE_TEST, - DB_TEST -}; - -struct TestArgs { - TestType type; - bool reverse_compare; - int restart_interval; -}; - -static const TestArgs kTestArgList[] = { - { TABLE_TEST, false, 16 }, - { TABLE_TEST, false, 1 }, - { TABLE_TEST, false, 1024 }, - { TABLE_TEST, true, 16 }, - { TABLE_TEST, true, 1 }, - { TABLE_TEST, true, 1024 }, - - { BLOCK_TEST, false, 16 }, - { BLOCK_TEST, false, 1 }, - { BLOCK_TEST, false, 1024 }, - { BLOCK_TEST, true, 16 }, - { BLOCK_TEST, true, 1 }, - { BLOCK_TEST, true, 1024 }, - - // Restart interval does not matter for memtables - { MEMTABLE_TEST, false, 16 }, - { MEMTABLE_TEST, true, 16 }, - - // Do not bother with restart interval variations for DB - { DB_TEST, false, 16 }, - { DB_TEST, true, 16 }, -}; -static const int kNumTestArgs = sizeof(kTestArgList) / sizeof(kTestArgList[0]); - -class Harness { - public: - Harness() : constructor_(NULL) { } - - void Init(const TestArgs& args) { - delete constructor_; - constructor_ = NULL; - options_ = Options(); - - options_.block_restart_interval = args.restart_interval; - // Use shorter block size for tests to exercise block boundary - // conditions more. - options_.block_size = 256; - if (args.reverse_compare) { - options_.comparator = &reverse_key_comparator; - } - switch (args.type) { - case TABLE_TEST: - constructor_ = new TableConstructor(options_.comparator); - break; - case BLOCK_TEST: - constructor_ = new BlockConstructor(options_.comparator); - break; - case MEMTABLE_TEST: - constructor_ = new MemTableConstructor(options_.comparator); - break; - case DB_TEST: - constructor_ = new DBConstructor(options_.comparator); - break; - } - } - - ~Harness() { - delete constructor_; - } - - void Add(const std::string& key, const std::string& value) { - constructor_->Add(key, value); - } - - void Test(Random* rnd) { - std::vector keys; - KVMap data; - constructor_->Finish(options_, &keys, &data); - - TestForwardScan(keys, data); - TestBackwardScan(keys, data); - TestRandomAccess(rnd, keys, data); - } - - void TestForwardScan(const std::vector& keys, - const KVMap& data) { - Iterator* iter = constructor_->NewIterator(); - ASSERT_TRUE(!iter->Valid()); - iter->SeekToFirst(); - for (KVMap::const_iterator model_iter = data.begin(); - model_iter != data.end(); - ++model_iter) { - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - iter->Next(); - } - ASSERT_TRUE(!iter->Valid()); - delete iter; - } - - void TestBackwardScan(const std::vector& keys, - const KVMap& data) { - Iterator* iter = constructor_->NewIterator(); - ASSERT_TRUE(!iter->Valid()); - iter->SeekToLast(); - for (KVMap::const_reverse_iterator model_iter = data.rbegin(); - model_iter != data.rend(); - ++model_iter) { - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - iter->Prev(); - } - ASSERT_TRUE(!iter->Valid()); - delete iter; - } - - void TestRandomAccess(Random* rnd, - const std::vector& keys, - const KVMap& data) { - static const bool kVerbose = false; - Iterator* iter = constructor_->NewIterator(); - ASSERT_TRUE(!iter->Valid()); - KVMap::const_iterator model_iter = data.begin(); - if (kVerbose) fprintf(stderr, "---\n"); - for (int i = 0; i < 200; i++) { - const int toss = rnd->Uniform(5); - switch (toss) { - case 0: { - if (iter->Valid()) { - if (kVerbose) fprintf(stderr, "Next\n"); - iter->Next(); - ++model_iter; - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - } - break; - } - - case 1: { - if (kVerbose) fprintf(stderr, "SeekToFirst\n"); - iter->SeekToFirst(); - model_iter = data.begin(); - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - break; - } - - case 2: { - std::string key = PickRandomKey(rnd, keys); - model_iter = data.lower_bound(key); - if (kVerbose) fprintf(stderr, "Seek '%s'\n", - EscapeString(key).c_str()); - iter->Seek(Slice(key)); - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - break; - } - - case 3: { - if (iter->Valid()) { - if (kVerbose) fprintf(stderr, "Prev\n"); - iter->Prev(); - if (model_iter == data.begin()) { - model_iter = data.end(); // Wrap around to invalid value - } else { - --model_iter; - } - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - } - break; - } - - case 4: { - if (kVerbose) fprintf(stderr, "SeekToLast\n"); - iter->SeekToLast(); - if (keys.empty()) { - model_iter = data.end(); - } else { - std::string last = data.rbegin()->first; - model_iter = data.lower_bound(last); - } - ASSERT_EQ(ToString(data, model_iter), ToString(iter)); - break; - } - } - } - delete iter; - } - - std::string ToString(const KVMap& data, const KVMap::const_iterator& it) { - if (it == data.end()) { - return "END"; - } else { - return "'" + it->first + "->" + it->second + "'"; - } - } - - std::string ToString(const KVMap& data, - const KVMap::const_reverse_iterator& it) { - if (it == data.rend()) { - return "END"; - } else { - return "'" + it->first + "->" + it->second + "'"; - } - } - - std::string ToString(const Iterator* it) { - if (!it->Valid()) { - return "END"; - } else { - return "'" + it->key().ToString() + "->" + it->value().ToString() + "'"; - } - } - - std::string PickRandomKey(Random* rnd, const std::vector& keys) { - if (keys.empty()) { - return "foo"; - } else { - const int index = rnd->Uniform(keys.size()); - std::string result = keys[index]; - switch (rnd->Uniform(3)) { - case 0: - // Return an existing key - break; - case 1: { - // Attempt to return something smaller than an existing key - if (result.size() > 0 && result[result.size()-1] > '\0') { - result[result.size()-1]--; - } - break; - } - case 2: { - // Return something larger than an existing key - Increment(options_.comparator, &result); - break; - } - } - return result; - } - } - - // Returns NULL if not running against a DB - DB* db() const { return constructor_->db(); } - - private: - Options options_; - Constructor* constructor_; -}; - -// Test empty table/block. -TEST(Harness, Empty) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 1); - Test(&rnd); - } -} - -// Special test for a block with no restart entries. The C++ leveldb -// code never generates such blocks, but the Java version of leveldb -// seems to. -TEST(Harness, ZeroRestartPointsInBlock) { - char data[sizeof(uint32_t)]; - memset(data, 0, sizeof(data)); - BlockContents contents; - contents.data = Slice(data, sizeof(data)); - contents.cachable = false; - contents.heap_allocated = false; - Block block(contents); - Iterator* iter = block.NewIterator(BytewiseComparator()); - iter->SeekToFirst(); - ASSERT_TRUE(!iter->Valid()); - iter->SeekToLast(); - ASSERT_TRUE(!iter->Valid()); - iter->Seek("foo"); - ASSERT_TRUE(!iter->Valid()); - delete iter; -} - -// Test the empty key -TEST(Harness, SimpleEmptyKey) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 1); - Add("", "v"); - Test(&rnd); - } -} - -TEST(Harness, SimpleSingle) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 2); - Add("abc", "v"); - Test(&rnd); - } -} - -TEST(Harness, SimpleMulti) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 3); - Add("abc", "v"); - Add("abcd", "v"); - Add("ac", "v2"); - Test(&rnd); - } -} - -TEST(Harness, SimpleSpecialKey) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 4); - Add("\xff\xff", "v3"); - Test(&rnd); - } -} - -TEST(Harness, Randomized) { - for (int i = 0; i < kNumTestArgs; i++) { - Init(kTestArgList[i]); - Random rnd(test::RandomSeed() + 5); - for (int num_entries = 0; num_entries < 2000; - num_entries += (num_entries < 50 ? 1 : 200)) { - if ((num_entries % 10) == 0) { - fprintf(stderr, "case %d of %d: num_entries = %d\n", - (i + 1), int(kNumTestArgs), num_entries); - } - for (int e = 0; e < num_entries; e++) { - std::string v; - Add(test::RandomKey(&rnd, rnd.Skewed(4)), - test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); - } - Test(&rnd); - } - } -} - -TEST(Harness, RandomizedLongDB) { - Random rnd(test::RandomSeed()); - TestArgs args = { DB_TEST, false, 16 }; - Init(args); - int num_entries = 100000; - for (int e = 0; e < num_entries; e++) { - std::string v; - Add(test::RandomKey(&rnd, rnd.Skewed(4)), - test::RandomString(&rnd, rnd.Skewed(5), &v).ToString()); - } - Test(&rnd); - - // We must have created enough data to force merging - int files = 0; - for (int level = 0; level < config::kNumLevels; level++) { - std::string value; - char name[100]; - snprintf(name, sizeof(name), "leveldb.num-files-at-level%d", level); - ASSERT_TRUE(db()->GetProperty(name, &value)); - files += atoi(value.c_str()); - } - ASSERT_GT(files, 0); -} - -class MemTableTest { }; - -TEST(MemTableTest, Simple) { - InternalKeyComparator cmp(BytewiseComparator()); - MemTable* memtable = new MemTable(cmp); - memtable->Ref(); - WriteBatch batch; - WriteBatchInternal::SetSequence(&batch, 100); - batch.Put(std::string("k1"), std::string("v1")); - batch.Put(std::string("k2"), std::string("v2")); - batch.Put(std::string("k3"), std::string("v3")); - batch.Put(std::string("largekey"), std::string("vlarge")); - ASSERT_TRUE(WriteBatchInternal::InsertInto(&batch, memtable).ok()); - - Iterator* iter = memtable->NewIterator(); - iter->SeekToFirst(); - while (iter->Valid()) { - fprintf(stderr, "key: '%s' -> '%s'\n", - iter->key().ToString().c_str(), - iter->value().ToString().c_str()); - iter->Next(); - } - - delete iter; - memtable->Unref(); -} - -static bool Between(uint64_t val, uint64_t low, uint64_t high) { - bool result = (val >= low) && (val <= high); - if (!result) { - fprintf(stderr, "Value %llu is not in range [%llu, %llu]\n", - (unsigned long long)(val), - (unsigned long long)(low), - (unsigned long long)(high)); - } - return result; -} - -class TableTest { }; - -TEST(TableTest, ApproximateOffsetOfPlain) { - TableConstructor c(BytewiseComparator()); - c.Add("k01", "hello"); - c.Add("k02", "hello2"); - c.Add("k03", std::string(10000, 'x')); - c.Add("k04", std::string(200000, 'x')); - c.Add("k05", std::string(300000, 'x')); - c.Add("k06", "hello3"); - c.Add("k07", std::string(100000, 'x')); - std::vector keys; - KVMap kvmap; - Options options; - options.block_size = 1024; - options.compression = kNoCompression; - c.Finish(options, &keys, &kvmap); - - ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01a"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 10000, 11000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04a"), 210000, 211000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k05"), 210000, 211000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k06"), 510000, 511000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k07"), 510000, 511000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 610000, 612000)); - -} - -static bool SnappyCompressionSupported() { - std::string out; - Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - return port::Snappy_Compress(in.data(), in.size(), &out); -} - -TEST(TableTest, ApproximateOffsetOfCompressed) { - if (!SnappyCompressionSupported()) { - fprintf(stderr, "skipping compression tests\n"); - return; - } - - Random rnd(301); - TableConstructor c(BytewiseComparator()); - std::string tmp; - c.Add("k01", "hello"); - c.Add("k02", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); - c.Add("k03", "hello3"); - c.Add("k04", test::CompressibleString(&rnd, 0.25, 10000, &tmp)); - std::vector keys; - KVMap kvmap; - Options options; - options.block_size = 1024; - options.compression = kSnappyCompression; - c.Finish(options, &keys, &kvmap); - - ASSERT_TRUE(Between(c.ApproximateOffsetOf("abc"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k01"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k02"), 0, 0)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k03"), 2000, 3000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("k04"), 2000, 3000)); - ASSERT_TRUE(Between(c.ApproximateOffsetOf("xyz"), 4000, 6000)); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/table/two_level_iterator.cc b/src/leveldb/table/two_level_iterator.cc deleted file mode 100644 index 7822ebab9c..0000000000 --- a/src/leveldb/table/two_level_iterator.cc +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "table/two_level_iterator.h" - -#include "leveldb/table.h" -#include "table/block.h" -#include "table/format.h" -#include "table/iterator_wrapper.h" - -namespace leveldb { - -namespace { - -typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); - -class TwoLevelIterator: public Iterator { - public: - TwoLevelIterator( - Iterator* index_iter, - BlockFunction block_function, - void* arg, - const ReadOptions& options); - - virtual ~TwoLevelIterator(); - - virtual void Seek(const Slice& target); - virtual void SeekToFirst(); - virtual void SeekToLast(); - virtual void Next(); - virtual void Prev(); - - virtual bool Valid() const { - return data_iter_.Valid(); - } - virtual Slice key() const { - assert(Valid()); - return data_iter_.key(); - } - virtual Slice value() const { - assert(Valid()); - return data_iter_.value(); - } - virtual Status status() const { - // It'd be nice if status() returned a const Status& instead of a Status - if (!index_iter_.status().ok()) { - return index_iter_.status(); - } else if (data_iter_.iter() != NULL && !data_iter_.status().ok()) { - return data_iter_.status(); - } else { - return status_; - } - } - - private: - void SaveError(const Status& s) { - if (status_.ok() && !s.ok()) status_ = s; - } - void SkipEmptyDataBlocksForward(); - void SkipEmptyDataBlocksBackward(); - void SetDataIterator(Iterator* data_iter); - void InitDataBlock(); - - BlockFunction block_function_; - void* arg_; - const ReadOptions options_; - Status status_; - IteratorWrapper index_iter_; - IteratorWrapper data_iter_; // May be NULL - // If data_iter_ is non-NULL, then "data_block_handle_" holds the - // "index_value" passed to block_function_ to create the data_iter_. - std::string data_block_handle_; -}; - -TwoLevelIterator::TwoLevelIterator( - Iterator* index_iter, - BlockFunction block_function, - void* arg, - const ReadOptions& options) - : block_function_(block_function), - arg_(arg), - options_(options), - index_iter_(index_iter), - data_iter_(NULL) { -} - -TwoLevelIterator::~TwoLevelIterator() { -} - -void TwoLevelIterator::Seek(const Slice& target) { - index_iter_.Seek(target); - InitDataBlock(); - if (data_iter_.iter() != NULL) data_iter_.Seek(target); - SkipEmptyDataBlocksForward(); -} - -void TwoLevelIterator::SeekToFirst() { - index_iter_.SeekToFirst(); - InitDataBlock(); - if (data_iter_.iter() != NULL) data_iter_.SeekToFirst(); - SkipEmptyDataBlocksForward(); -} - -void TwoLevelIterator::SeekToLast() { - index_iter_.SeekToLast(); - InitDataBlock(); - if (data_iter_.iter() != NULL) data_iter_.SeekToLast(); - SkipEmptyDataBlocksBackward(); -} - -void TwoLevelIterator::Next() { - assert(Valid()); - data_iter_.Next(); - SkipEmptyDataBlocksForward(); -} - -void TwoLevelIterator::Prev() { - assert(Valid()); - data_iter_.Prev(); - SkipEmptyDataBlocksBackward(); -} - - -void TwoLevelIterator::SkipEmptyDataBlocksForward() { - while (data_iter_.iter() == NULL || !data_iter_.Valid()) { - // Move to next block - if (!index_iter_.Valid()) { - SetDataIterator(NULL); - return; - } - index_iter_.Next(); - InitDataBlock(); - if (data_iter_.iter() != NULL) data_iter_.SeekToFirst(); - } -} - -void TwoLevelIterator::SkipEmptyDataBlocksBackward() { - while (data_iter_.iter() == NULL || !data_iter_.Valid()) { - // Move to next block - if (!index_iter_.Valid()) { - SetDataIterator(NULL); - return; - } - index_iter_.Prev(); - InitDataBlock(); - if (data_iter_.iter() != NULL) data_iter_.SeekToLast(); - } -} - -void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { - if (data_iter_.iter() != NULL) SaveError(data_iter_.status()); - data_iter_.Set(data_iter); -} - -void TwoLevelIterator::InitDataBlock() { - if (!index_iter_.Valid()) { - SetDataIterator(NULL); - } else { - Slice handle = index_iter_.value(); - if (data_iter_.iter() != NULL && handle.compare(data_block_handle_) == 0) { - // data_iter_ is already constructed with this iterator, so - // no need to change anything - } else { - Iterator* iter = (*block_function_)(arg_, options_, handle); - data_block_handle_.assign(handle.data(), handle.size()); - SetDataIterator(iter); - } - } -} - -} // namespace - -Iterator* NewTwoLevelIterator( - Iterator* index_iter, - BlockFunction block_function, - void* arg, - const ReadOptions& options) { - return new TwoLevelIterator(index_iter, block_function, arg, options); -} - -} // namespace leveldb diff --git a/src/leveldb/table/two_level_iterator.h b/src/leveldb/table/two_level_iterator.h deleted file mode 100644 index 629ca34525..0000000000 --- a/src/leveldb/table/two_level_iterator.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ -#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ - -#include "leveldb/iterator.h" - -namespace leveldb { - -struct ReadOptions; - -// Return a new two level iterator. A two-level iterator contains an -// index iterator whose values point to a sequence of blocks where -// each block is itself a sequence of key,value pairs. The returned -// two-level iterator yields the concatenation of all key/value pairs -// in the sequence of blocks. Takes ownership of "index_iter" and -// will delete it when no longer needed. -// -// Uses a supplied function to convert an index_iter value into -// an iterator over the contents of the corresponding block. -extern Iterator* NewTwoLevelIterator( - Iterator* index_iter, - Iterator* (*block_function)( - void* arg, - const ReadOptions& options, - const Slice& index_value), - void* arg, - const ReadOptions& options); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/src/leveldb/util/arena.cc b/src/leveldb/util/arena.cc deleted file mode 100644 index 9367f71492..0000000000 --- a/src/leveldb/util/arena.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/arena.h" -#include - -namespace leveldb { - -static const int kBlockSize = 4096; - -Arena::Arena() { - blocks_memory_ = 0; - alloc_ptr_ = NULL; // First allocation will allocate a block - alloc_bytes_remaining_ = 0; -} - -Arena::~Arena() { - for (size_t i = 0; i < blocks_.size(); i++) { - delete[] blocks_[i]; - } -} - -char* Arena::AllocateFallback(size_t bytes) { - if (bytes > kBlockSize / 4) { - // Object is more than a quarter of our block size. Allocate it separately - // to avoid wasting too much space in leftover bytes. - char* result = AllocateNewBlock(bytes); - return result; - } - - // We waste the remaining space in the current block. - alloc_ptr_ = AllocateNewBlock(kBlockSize); - alloc_bytes_remaining_ = kBlockSize; - - char* result = alloc_ptr_; - alloc_ptr_ += bytes; - alloc_bytes_remaining_ -= bytes; - return result; -} - -char* Arena::AllocateAligned(size_t bytes) { - const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; - assert((align & (align-1)) == 0); // Pointer size should be a power of 2 - size_t current_mod = reinterpret_cast(alloc_ptr_) & (align-1); - size_t slop = (current_mod == 0 ? 0 : align - current_mod); - size_t needed = bytes + slop; - char* result; - if (needed <= alloc_bytes_remaining_) { - result = alloc_ptr_ + slop; - alloc_ptr_ += needed; - alloc_bytes_remaining_ -= needed; - } else { - // AllocateFallback always returned aligned memory - result = AllocateFallback(bytes); - } - assert((reinterpret_cast(result) & (align-1)) == 0); - return result; -} - -char* Arena::AllocateNewBlock(size_t block_bytes) { - char* result = new char[block_bytes]; - blocks_memory_ += block_bytes; - blocks_.push_back(result); - return result; -} - -} // namespace leveldb diff --git a/src/leveldb/util/arena.h b/src/leveldb/util/arena.h deleted file mode 100644 index 73bbf1cb9b..0000000000 --- a/src/leveldb/util/arena.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ -#define STORAGE_LEVELDB_UTIL_ARENA_H_ - -#include -#include -#include -#include - -namespace leveldb { - -class Arena { - public: - Arena(); - ~Arena(); - - // Return a pointer to a newly allocated memory block of "bytes" bytes. - char* Allocate(size_t bytes); - - // Allocate memory with the normal alignment guarantees provided by malloc - char* AllocateAligned(size_t bytes); - - // Returns an estimate of the total memory usage of data allocated - // by the arena (including space allocated but not yet used for user - // allocations). - size_t MemoryUsage() const { - return blocks_memory_ + blocks_.capacity() * sizeof(char*); - } - - private: - char* AllocateFallback(size_t bytes); - char* AllocateNewBlock(size_t block_bytes); - - // Allocation state - char* alloc_ptr_; - size_t alloc_bytes_remaining_; - - // Array of new[] allocated memory blocks - std::vector blocks_; - - // Bytes of memory in blocks allocated so far - size_t blocks_memory_; - - // No copying allowed - Arena(const Arena&); - void operator=(const Arena&); -}; - -inline char* Arena::Allocate(size_t bytes) { - // The semantics of what to return are a bit messy if we allow - // 0-byte allocations, so we disallow them here (we don't need - // them for our internal use). - assert(bytes > 0); - if (bytes <= alloc_bytes_remaining_) { - char* result = alloc_ptr_; - alloc_ptr_ += bytes; - alloc_bytes_remaining_ -= bytes; - return result; - } - return AllocateFallback(bytes); -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/src/leveldb/util/arena_test.cc b/src/leveldb/util/arena_test.cc deleted file mode 100644 index 58e870ec44..0000000000 --- a/src/leveldb/util/arena_test.cc +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/arena.h" - -#include "util/random.h" -#include "util/testharness.h" - -namespace leveldb { - -class ArenaTest { }; - -TEST(ArenaTest, Empty) { - Arena arena; -} - -TEST(ArenaTest, Simple) { - std::vector > allocated; - Arena arena; - const int N = 100000; - size_t bytes = 0; - Random rnd(301); - for (int i = 0; i < N; i++) { - size_t s; - if (i % (N / 10) == 0) { - s = i; - } else { - s = rnd.OneIn(4000) ? rnd.Uniform(6000) : - (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20)); - } - if (s == 0) { - // Our arena disallows size 0 allocations. - s = 1; - } - char* r; - if (rnd.OneIn(10)) { - r = arena.AllocateAligned(s); - } else { - r = arena.Allocate(s); - } - - for (size_t b = 0; b < s; b++) { - // Fill the "i"th allocation with a known bit pattern - r[b] = i % 256; - } - bytes += s; - allocated.push_back(std::make_pair(s, r)); - ASSERT_GE(arena.MemoryUsage(), bytes); - if (i > N/10) { - ASSERT_LE(arena.MemoryUsage(), bytes * 1.10); - } - } - for (size_t i = 0; i < allocated.size(); i++) { - size_t num_bytes = allocated[i].first; - const char* p = allocated[i].second; - for (size_t b = 0; b < num_bytes; b++) { - // Check the "i"th allocation for the known bit pattern - ASSERT_EQ(int(p[b]) & 0xff, i % 256); - } - } -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/bloom.cc b/src/leveldb/util/bloom.cc deleted file mode 100644 index a27a2ace28..0000000000 --- a/src/leveldb/util/bloom.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/filter_policy.h" - -#include "leveldb/slice.h" -#include "util/hash.h" - -namespace leveldb { - -namespace { -static uint32_t BloomHash(const Slice& key) { - return Hash(key.data(), key.size(), 0xbc9f1d34); -} - -class BloomFilterPolicy : public FilterPolicy { - private: - size_t bits_per_key_; - size_t k_; - - public: - explicit BloomFilterPolicy(int bits_per_key) - : bits_per_key_(bits_per_key) { - // We intentionally round down to reduce probing cost a little bit - k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2) - if (k_ < 1) k_ = 1; - if (k_ > 30) k_ = 30; - } - - virtual const char* Name() const { - return "leveldb.BuiltinBloomFilter2"; - } - - virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { - // Compute bloom filter size (in both bits and bytes) - size_t bits = n * bits_per_key_; - - // For small n, we can see a very high false positive rate. Fix it - // by enforcing a minimum bloom filter length. - if (bits < 64) bits = 64; - - size_t bytes = (bits + 7) / 8; - bits = bytes * 8; - - const size_t init_size = dst->size(); - dst->resize(init_size + bytes, 0); - dst->push_back(static_cast(k_)); // Remember # of probes in filter - char* array = &(*dst)[init_size]; - for (size_t i = 0; i < n; i++) { - // Use double-hashing to generate a sequence of hash values. - // See analysis in [Kirsch,Mitzenmacher 2006]. - uint32_t h = BloomHash(keys[i]); - const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits - for (size_t j = 0; j < k_; j++) { - const uint32_t bitpos = h % bits; - array[bitpos/8] |= (1 << (bitpos % 8)); - h += delta; - } - } - } - - virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { - const size_t len = bloom_filter.size(); - if (len < 2) return false; - - const char* array = bloom_filter.data(); - const size_t bits = (len - 1) * 8; - - // Use the encoded k so that we can read filters generated by - // bloom filters created using different parameters. - const size_t k = array[len-1]; - if (k > 30) { - // Reserved for potentially new encodings for short bloom filters. - // Consider it a match. - return true; - } - - uint32_t h = BloomHash(key); - const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits - for (size_t j = 0; j < k; j++) { - const uint32_t bitpos = h % bits; - if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false; - h += delta; - } - return true; - } -}; -} - -const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { - return new BloomFilterPolicy(bits_per_key); -} - -} // namespace leveldb diff --git a/src/leveldb/util/bloom_test.cc b/src/leveldb/util/bloom_test.cc deleted file mode 100644 index 77fb1b3159..0000000000 --- a/src/leveldb/util/bloom_test.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/filter_policy.h" - -#include "util/coding.h" -#include "util/logging.h" -#include "util/testharness.h" -#include "util/testutil.h" - -namespace leveldb { - -static const int kVerbose = 1; - -static Slice Key(int i, char* buffer) { - EncodeFixed32(buffer, i); - return Slice(buffer, sizeof(uint32_t)); -} - -class BloomTest { - private: - const FilterPolicy* policy_; - std::string filter_; - std::vector keys_; - - public: - BloomTest() : policy_(NewBloomFilterPolicy(10)) { } - - ~BloomTest() { - delete policy_; - } - - void Reset() { - keys_.clear(); - filter_.clear(); - } - - void Add(const Slice& s) { - keys_.push_back(s.ToString()); - } - - void Build() { - std::vector key_slices; - for (size_t i = 0; i < keys_.size(); i++) { - key_slices.push_back(Slice(keys_[i])); - } - filter_.clear(); - policy_->CreateFilter(&key_slices[0], key_slices.size(), &filter_); - keys_.clear(); - if (kVerbose >= 2) DumpFilter(); - } - - size_t FilterSize() const { - return filter_.size(); - } - - void DumpFilter() { - fprintf(stderr, "F("); - for (size_t i = 0; i+1 < filter_.size(); i++) { - const unsigned int c = static_cast(filter_[i]); - for (int j = 0; j < 8; j++) { - fprintf(stderr, "%c", (c & (1 <KeyMayMatch(s, filter_); - } - - double FalsePositiveRate() { - char buffer[sizeof(int)]; - int result = 0; - for (int i = 0; i < 10000; i++) { - if (Matches(Key(i + 1000000000, buffer))) { - result++; - } - } - return result / 10000.0; - } -}; - -TEST(BloomTest, EmptyFilter) { - ASSERT_TRUE(! Matches("hello")); - ASSERT_TRUE(! Matches("world")); -} - -TEST(BloomTest, Small) { - Add("hello"); - Add("world"); - ASSERT_TRUE(Matches("hello")); - ASSERT_TRUE(Matches("world")); - ASSERT_TRUE(! Matches("x")); - ASSERT_TRUE(! Matches("foo")); -} - -static int NextLength(int length) { - if (length < 10) { - length += 1; - } else if (length < 100) { - length += 10; - } else if (length < 1000) { - length += 100; - } else { - length += 1000; - } - return length; -} - -TEST(BloomTest, VaryingLengths) { - char buffer[sizeof(int)]; - - // Count number of filters that significantly exceed the false positive rate - int mediocre_filters = 0; - int good_filters = 0; - - for (int length = 1; length <= 10000; length = NextLength(length)) { - Reset(); - for (int i = 0; i < length; i++) { - Add(Key(i, buffer)); - } - Build(); - - ASSERT_LE(FilterSize(), static_cast((length * 10 / 8) + 40)) - << length; - - // All added keys must match - for (int i = 0; i < length; i++) { - ASSERT_TRUE(Matches(Key(i, buffer))) - << "Length " << length << "; key " << i; - } - - // Check false positive rate - double rate = FalsePositiveRate(); - if (kVerbose >= 1) { - fprintf(stderr, "False positives: %5.2f%% @ length = %6d ; bytes = %6d\n", - rate*100.0, length, static_cast(FilterSize())); - } - ASSERT_LE(rate, 0.02); // Must not be over 2% - if (rate > 0.0125) mediocre_filters++; // Allowed, but not too often - else good_filters++; - } - if (kVerbose >= 1) { - fprintf(stderr, "Filters: %d good, %d mediocre\n", - good_filters, mediocre_filters); - } - ASSERT_LE(mediocre_filters, good_filters/5); -} - -// Different bits-per-byte - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/cache.cc b/src/leveldb/util/cache.cc deleted file mode 100644 index 8b197bc02a..0000000000 --- a/src/leveldb/util/cache.cc +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include - -#include "leveldb/cache.h" -#include "port/port.h" -#include "util/hash.h" -#include "util/mutexlock.h" - -namespace leveldb { - -Cache::~Cache() { -} - -namespace { - -// LRU cache implementation - -// An entry is a variable length heap-allocated structure. Entries -// are kept in a circular doubly linked list ordered by access time. -struct LRUHandle { - void* value; - void (*deleter)(const Slice&, void* value); - LRUHandle* next_hash; - LRUHandle* next; - LRUHandle* prev; - size_t charge; // TODO(opt): Only allow uint32_t? - size_t key_length; - uint32_t refs; - uint32_t hash; // Hash of key(); used for fast sharding and comparisons - char key_data[1]; // Beginning of key - - Slice key() const { - // For cheaper lookups, we allow a temporary Handle object - // to store a pointer to a key in "value". - if (next == this) { - return *(reinterpret_cast(value)); - } else { - return Slice(key_data, key_length); - } - } -}; - -// We provide our own simple hash table since it removes a whole bunch -// of porting hacks and is also faster than some of the built-in hash -// table implementations in some of the compiler/runtime combinations -// we have tested. E.g., readrandom speeds up by ~5% over the g++ -// 4.4.3's builtin hashtable. -class HandleTable { - public: - HandleTable() : length_(0), elems_(0), list_(NULL) { Resize(); } - ~HandleTable() { delete[] list_; } - - LRUHandle* Lookup(const Slice& key, uint32_t hash) { - return *FindPointer(key, hash); - } - - LRUHandle* Insert(LRUHandle* h) { - LRUHandle** ptr = FindPointer(h->key(), h->hash); - LRUHandle* old = *ptr; - h->next_hash = (old == NULL ? NULL : old->next_hash); - *ptr = h; - if (old == NULL) { - ++elems_; - if (elems_ > length_) { - // Since each cache entry is fairly large, we aim for a small - // average linked list length (<= 1). - Resize(); - } - } - return old; - } - - LRUHandle* Remove(const Slice& key, uint32_t hash) { - LRUHandle** ptr = FindPointer(key, hash); - LRUHandle* result = *ptr; - if (result != NULL) { - *ptr = result->next_hash; - --elems_; - } - return result; - } - - private: - // The table consists of an array of buckets where each bucket is - // a linked list of cache entries that hash into the bucket. - uint32_t length_; - uint32_t elems_; - LRUHandle** list_; - - // Return a pointer to slot that points to a cache entry that - // matches key/hash. If there is no such cache entry, return a - // pointer to the trailing slot in the corresponding linked list. - LRUHandle** FindPointer(const Slice& key, uint32_t hash) { - LRUHandle** ptr = &list_[hash & (length_ - 1)]; - while (*ptr != NULL && - ((*ptr)->hash != hash || key != (*ptr)->key())) { - ptr = &(*ptr)->next_hash; - } - return ptr; - } - - void Resize() { - uint32_t new_length = 4; - while (new_length < elems_) { - new_length *= 2; - } - LRUHandle** new_list = new LRUHandle*[new_length]; - memset(new_list, 0, sizeof(new_list[0]) * new_length); - uint32_t count = 0; - for (uint32_t i = 0; i < length_; i++) { - LRUHandle* h = list_[i]; - while (h != NULL) { - LRUHandle* next = h->next_hash; - uint32_t hash = h->hash; - LRUHandle** ptr = &new_list[hash & (new_length - 1)]; - h->next_hash = *ptr; - *ptr = h; - h = next; - count++; - } - } - assert(elems_ == count); - delete[] list_; - list_ = new_list; - length_ = new_length; - } -}; - -// A single shard of sharded cache. -class LRUCache { - public: - LRUCache(); - ~LRUCache(); - - // Separate from constructor so caller can easily make an array of LRUCache - void SetCapacity(size_t capacity) { capacity_ = capacity; } - - // Like Cache methods, but with an extra "hash" parameter. - Cache::Handle* Insert(const Slice& key, uint32_t hash, - void* value, size_t charge, - void (*deleter)(const Slice& key, void* value)); - Cache::Handle* Lookup(const Slice& key, uint32_t hash); - void Release(Cache::Handle* handle); - void Erase(const Slice& key, uint32_t hash); - - private: - void LRU_Remove(LRUHandle* e); - void LRU_Append(LRUHandle* e); - void Unref(LRUHandle* e); - - // Initialized before use. - size_t capacity_; - - // mutex_ protects the following state. - port::Mutex mutex_; - size_t usage_; - - // Dummy head of LRU list. - // lru.prev is newest entry, lru.next is oldest entry. - LRUHandle lru_; - - HandleTable table_; -}; - -LRUCache::LRUCache() - : usage_(0) { - // Make empty circular linked list - lru_.next = &lru_; - lru_.prev = &lru_; -} - -LRUCache::~LRUCache() { - for (LRUHandle* e = lru_.next; e != &lru_; ) { - LRUHandle* next = e->next; - assert(e->refs == 1); // Error if caller has an unreleased handle - Unref(e); - e = next; - } -} - -void LRUCache::Unref(LRUHandle* e) { - assert(e->refs > 0); - e->refs--; - if (e->refs <= 0) { - usage_ -= e->charge; - (*e->deleter)(e->key(), e->value); - free(e); - } -} - -void LRUCache::LRU_Remove(LRUHandle* e) { - e->next->prev = e->prev; - e->prev->next = e->next; -} - -void LRUCache::LRU_Append(LRUHandle* e) { - // Make "e" newest entry by inserting just before lru_ - e->next = &lru_; - e->prev = lru_.prev; - e->prev->next = e; - e->next->prev = e; -} - -Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { - MutexLock l(&mutex_); - LRUHandle* e = table_.Lookup(key, hash); - if (e != NULL) { - e->refs++; - LRU_Remove(e); - LRU_Append(e); - } - return reinterpret_cast(e); -} - -void LRUCache::Release(Cache::Handle* handle) { - MutexLock l(&mutex_); - Unref(reinterpret_cast(handle)); -} - -Cache::Handle* LRUCache::Insert( - const Slice& key, uint32_t hash, void* value, size_t charge, - void (*deleter)(const Slice& key, void* value)) { - MutexLock l(&mutex_); - - LRUHandle* e = reinterpret_cast( - malloc(sizeof(LRUHandle)-1 + key.size())); - e->value = value; - e->deleter = deleter; - e->charge = charge; - e->key_length = key.size(); - e->hash = hash; - e->refs = 2; // One from LRUCache, one for the returned handle - memcpy(e->key_data, key.data(), key.size()); - LRU_Append(e); - usage_ += charge; - - LRUHandle* old = table_.Insert(e); - if (old != NULL) { - LRU_Remove(old); - Unref(old); - } - - while (usage_ > capacity_ && lru_.next != &lru_) { - LRUHandle* old = lru_.next; - LRU_Remove(old); - table_.Remove(old->key(), old->hash); - Unref(old); - } - - return reinterpret_cast(e); -} - -void LRUCache::Erase(const Slice& key, uint32_t hash) { - MutexLock l(&mutex_); - LRUHandle* e = table_.Remove(key, hash); - if (e != NULL) { - LRU_Remove(e); - Unref(e); - } -} - -static const int kNumShardBits = 4; -static const int kNumShards = 1 << kNumShardBits; - -class ShardedLRUCache : public Cache { - private: - LRUCache shard_[kNumShards]; - port::Mutex id_mutex_; - uint64_t last_id_; - - static inline uint32_t HashSlice(const Slice& s) { - return Hash(s.data(), s.size(), 0); - } - - static uint32_t Shard(uint32_t hash) { - return hash >> (32 - kNumShardBits); - } - - public: - explicit ShardedLRUCache(size_t capacity) - : last_id_(0) { - const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards; - for (int s = 0; s < kNumShards; s++) { - shard_[s].SetCapacity(per_shard); - } - } - virtual ~ShardedLRUCache() { } - virtual Handle* Insert(const Slice& key, void* value, size_t charge, - void (*deleter)(const Slice& key, void* value)) { - const uint32_t hash = HashSlice(key); - return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); - } - virtual Handle* Lookup(const Slice& key) { - const uint32_t hash = HashSlice(key); - return shard_[Shard(hash)].Lookup(key, hash); - } - virtual void Release(Handle* handle) { - LRUHandle* h = reinterpret_cast(handle); - shard_[Shard(h->hash)].Release(handle); - } - virtual void Erase(const Slice& key) { - const uint32_t hash = HashSlice(key); - shard_[Shard(hash)].Erase(key, hash); - } - virtual void* Value(Handle* handle) { - return reinterpret_cast(handle)->value; - } - virtual uint64_t NewId() { - MutexLock l(&id_mutex_); - return ++(last_id_); - } -}; - -} // end anonymous namespace - -Cache* NewLRUCache(size_t capacity) { - return new ShardedLRUCache(capacity); -} - -} // namespace leveldb diff --git a/src/leveldb/util/cache_test.cc b/src/leveldb/util/cache_test.cc deleted file mode 100644 index 43716715a8..0000000000 --- a/src/leveldb/util/cache_test.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/cache.h" - -#include -#include "util/coding.h" -#include "util/testharness.h" - -namespace leveldb { - -// Conversions between numeric keys/values and the types expected by Cache. -static std::string EncodeKey(int k) { - std::string result; - PutFixed32(&result, k); - return result; -} -static int DecodeKey(const Slice& k) { - assert(k.size() == 4); - return DecodeFixed32(k.data()); -} -static void* EncodeValue(uintptr_t v) { return reinterpret_cast(v); } -static int DecodeValue(void* v) { return reinterpret_cast(v); } - -class CacheTest { - public: - static CacheTest* current_; - - static void Deleter(const Slice& key, void* v) { - current_->deleted_keys_.push_back(DecodeKey(key)); - current_->deleted_values_.push_back(DecodeValue(v)); - } - - static const int kCacheSize = 1000; - std::vector deleted_keys_; - std::vector deleted_values_; - Cache* cache_; - - CacheTest() : cache_(NewLRUCache(kCacheSize)) { - current_ = this; - } - - ~CacheTest() { - delete cache_; - } - - int Lookup(int key) { - Cache::Handle* handle = cache_->Lookup(EncodeKey(key)); - const int r = (handle == NULL) ? -1 : DecodeValue(cache_->Value(handle)); - if (handle != NULL) { - cache_->Release(handle); - } - return r; - } - - void Insert(int key, int value, int charge = 1) { - cache_->Release(cache_->Insert(EncodeKey(key), EncodeValue(value), charge, - &CacheTest::Deleter)); - } - - void Erase(int key) { - cache_->Erase(EncodeKey(key)); - } -}; -CacheTest* CacheTest::current_; - -TEST(CacheTest, HitAndMiss) { - ASSERT_EQ(-1, Lookup(100)); - - Insert(100, 101); - ASSERT_EQ(101, Lookup(100)); - ASSERT_EQ(-1, Lookup(200)); - ASSERT_EQ(-1, Lookup(300)); - - Insert(200, 201); - ASSERT_EQ(101, Lookup(100)); - ASSERT_EQ(201, Lookup(200)); - ASSERT_EQ(-1, Lookup(300)); - - Insert(100, 102); - ASSERT_EQ(102, Lookup(100)); - ASSERT_EQ(201, Lookup(200)); - ASSERT_EQ(-1, Lookup(300)); - - ASSERT_EQ(1, deleted_keys_.size()); - ASSERT_EQ(100, deleted_keys_[0]); - ASSERT_EQ(101, deleted_values_[0]); -} - -TEST(CacheTest, Erase) { - Erase(200); - ASSERT_EQ(0, deleted_keys_.size()); - - Insert(100, 101); - Insert(200, 201); - Erase(100); - ASSERT_EQ(-1, Lookup(100)); - ASSERT_EQ(201, Lookup(200)); - ASSERT_EQ(1, deleted_keys_.size()); - ASSERT_EQ(100, deleted_keys_[0]); - ASSERT_EQ(101, deleted_values_[0]); - - Erase(100); - ASSERT_EQ(-1, Lookup(100)); - ASSERT_EQ(201, Lookup(200)); - ASSERT_EQ(1, deleted_keys_.size()); -} - -TEST(CacheTest, EntriesArePinned) { - Insert(100, 101); - Cache::Handle* h1 = cache_->Lookup(EncodeKey(100)); - ASSERT_EQ(101, DecodeValue(cache_->Value(h1))); - - Insert(100, 102); - Cache::Handle* h2 = cache_->Lookup(EncodeKey(100)); - ASSERT_EQ(102, DecodeValue(cache_->Value(h2))); - ASSERT_EQ(0, deleted_keys_.size()); - - cache_->Release(h1); - ASSERT_EQ(1, deleted_keys_.size()); - ASSERT_EQ(100, deleted_keys_[0]); - ASSERT_EQ(101, deleted_values_[0]); - - Erase(100); - ASSERT_EQ(-1, Lookup(100)); - ASSERT_EQ(1, deleted_keys_.size()); - - cache_->Release(h2); - ASSERT_EQ(2, deleted_keys_.size()); - ASSERT_EQ(100, deleted_keys_[1]); - ASSERT_EQ(102, deleted_values_[1]); -} - -TEST(CacheTest, EvictionPolicy) { - Insert(100, 101); - Insert(200, 201); - - // Frequently used entry must be kept around - for (int i = 0; i < kCacheSize + 100; i++) { - Insert(1000+i, 2000+i); - ASSERT_EQ(2000+i, Lookup(1000+i)); - ASSERT_EQ(101, Lookup(100)); - } - ASSERT_EQ(101, Lookup(100)); - ASSERT_EQ(-1, Lookup(200)); -} - -TEST(CacheTest, HeavyEntries) { - // Add a bunch of light and heavy entries and then count the combined - // size of items still in the cache, which must be approximately the - // same as the total capacity. - const int kLight = 1; - const int kHeavy = 10; - int added = 0; - int index = 0; - while (added < 2*kCacheSize) { - const int weight = (index & 1) ? kLight : kHeavy; - Insert(index, 1000+index, weight); - added += weight; - index++; - } - - int cached_weight = 0; - for (int i = 0; i < index; i++) { - const int weight = (i & 1 ? kLight : kHeavy); - int r = Lookup(i); - if (r >= 0) { - cached_weight += weight; - ASSERT_EQ(1000+i, r); - } - } - ASSERT_LE(cached_weight, kCacheSize + kCacheSize/10); -} - -TEST(CacheTest, NewId) { - uint64_t a = cache_->NewId(); - uint64_t b = cache_->NewId(); - ASSERT_NE(a, b); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/coding.cc b/src/leveldb/util/coding.cc deleted file mode 100644 index 21e3186d5d..0000000000 --- a/src/leveldb/util/coding.cc +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/coding.h" - -namespace leveldb { - -void EncodeFixed32(char* buf, uint32_t value) { - if (port::kLittleEndian) { - memcpy(buf, &value, sizeof(value)); - } else { - buf[0] = value & 0xff; - buf[1] = (value >> 8) & 0xff; - buf[2] = (value >> 16) & 0xff; - buf[3] = (value >> 24) & 0xff; - } -} - -void EncodeFixed64(char* buf, uint64_t value) { - if (port::kLittleEndian) { - memcpy(buf, &value, sizeof(value)); - } else { - buf[0] = value & 0xff; - buf[1] = (value >> 8) & 0xff; - buf[2] = (value >> 16) & 0xff; - buf[3] = (value >> 24) & 0xff; - buf[4] = (value >> 32) & 0xff; - buf[5] = (value >> 40) & 0xff; - buf[6] = (value >> 48) & 0xff; - buf[7] = (value >> 56) & 0xff; - } -} - -void PutFixed32(std::string* dst, uint32_t value) { - char buf[sizeof(value)]; - EncodeFixed32(buf, value); - dst->append(buf, sizeof(buf)); -} - -void PutFixed64(std::string* dst, uint64_t value) { - char buf[sizeof(value)]; - EncodeFixed64(buf, value); - dst->append(buf, sizeof(buf)); -} - -char* EncodeVarint32(char* dst, uint32_t v) { - // Operate on characters as unsigneds - unsigned char* ptr = reinterpret_cast(dst); - static const int B = 128; - if (v < (1<<7)) { - *(ptr++) = v; - } else if (v < (1<<14)) { - *(ptr++) = v | B; - *(ptr++) = v>>7; - } else if (v < (1<<21)) { - *(ptr++) = v | B; - *(ptr++) = (v>>7) | B; - *(ptr++) = v>>14; - } else if (v < (1<<28)) { - *(ptr++) = v | B; - *(ptr++) = (v>>7) | B; - *(ptr++) = (v>>14) | B; - *(ptr++) = v>>21; - } else { - *(ptr++) = v | B; - *(ptr++) = (v>>7) | B; - *(ptr++) = (v>>14) | B; - *(ptr++) = (v>>21) | B; - *(ptr++) = v>>28; - } - return reinterpret_cast(ptr); -} - -void PutVarint32(std::string* dst, uint32_t v) { - char buf[5]; - char* ptr = EncodeVarint32(buf, v); - dst->append(buf, ptr - buf); -} - -char* EncodeVarint64(char* dst, uint64_t v) { - static const int B = 128; - unsigned char* ptr = reinterpret_cast(dst); - while (v >= B) { - *(ptr++) = (v & (B-1)) | B; - v >>= 7; - } - *(ptr++) = static_cast(v); - return reinterpret_cast(ptr); -} - -void PutVarint64(std::string* dst, uint64_t v) { - char buf[10]; - char* ptr = EncodeVarint64(buf, v); - dst->append(buf, ptr - buf); -} - -void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { - PutVarint32(dst, value.size()); - dst->append(value.data(), value.size()); -} - -int VarintLength(uint64_t v) { - int len = 1; - while (v >= 128) { - v >>= 7; - len++; - } - return len; -} - -const char* GetVarint32PtrFallback(const char* p, - const char* limit, - uint32_t* value) { - uint32_t result = 0; - for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { - uint32_t byte = *(reinterpret_cast(p)); - p++; - if (byte & 128) { - // More bytes are present - result |= ((byte & 127) << shift); - } else { - result |= (byte << shift); - *value = result; - return reinterpret_cast(p); - } - } - return NULL; -} - -bool GetVarint32(Slice* input, uint32_t* value) { - const char* p = input->data(); - const char* limit = p + input->size(); - const char* q = GetVarint32Ptr(p, limit, value); - if (q == NULL) { - return false; - } else { - *input = Slice(q, limit - q); - return true; - } -} - -const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { - uint64_t result = 0; - for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { - uint64_t byte = *(reinterpret_cast(p)); - p++; - if (byte & 128) { - // More bytes are present - result |= ((byte & 127) << shift); - } else { - result |= (byte << shift); - *value = result; - return reinterpret_cast(p); - } - } - return NULL; -} - -bool GetVarint64(Slice* input, uint64_t* value) { - const char* p = input->data(); - const char* limit = p + input->size(); - const char* q = GetVarint64Ptr(p, limit, value); - if (q == NULL) { - return false; - } else { - *input = Slice(q, limit - q); - return true; - } -} - -const char* GetLengthPrefixedSlice(const char* p, const char* limit, - Slice* result) { - uint32_t len; - p = GetVarint32Ptr(p, limit, &len); - if (p == NULL) return NULL; - if (p + len > limit) return NULL; - *result = Slice(p, len); - return p + len; -} - -bool GetLengthPrefixedSlice(Slice* input, Slice* result) { - uint32_t len; - if (GetVarint32(input, &len) && - input->size() >= len) { - *result = Slice(input->data(), len); - input->remove_prefix(len); - return true; - } else { - return false; - } -} - -} // namespace leveldb diff --git a/src/leveldb/util/coding.h b/src/leveldb/util/coding.h deleted file mode 100644 index 3993c4a755..0000000000 --- a/src/leveldb/util/coding.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Endian-neutral encoding: -// * Fixed-length numbers are encoded with least-significant byte first -// * In addition we support variable length "varint" encoding -// * Strings are encoded prefixed by their length in varint format - -#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ -#define STORAGE_LEVELDB_UTIL_CODING_H_ - -#include -#include -#include -#include "leveldb/slice.h" -#include "port/port.h" - -namespace leveldb { - -// Standard Put... routines append to a string -extern void PutFixed32(std::string* dst, uint32_t value); -extern void PutFixed64(std::string* dst, uint64_t value); -extern void PutVarint32(std::string* dst, uint32_t value); -extern void PutVarint64(std::string* dst, uint64_t value); -extern void PutLengthPrefixedSlice(std::string* dst, const Slice& value); - -// Standard Get... routines parse a value from the beginning of a Slice -// and advance the slice past the parsed value. -extern bool GetVarint32(Slice* input, uint32_t* value); -extern bool GetVarint64(Slice* input, uint64_t* value); -extern bool GetLengthPrefixedSlice(Slice* input, Slice* result); - -// Pointer-based variants of GetVarint... These either store a value -// in *v and return a pointer just past the parsed value, or return -// NULL on error. These routines only look at bytes in the range -// [p..limit-1] -extern const char* GetVarint32Ptr(const char* p,const char* limit, uint32_t* v); -extern const char* GetVarint64Ptr(const char* p,const char* limit, uint64_t* v); - -// Returns the length of the varint32 or varint64 encoding of "v" -extern int VarintLength(uint64_t v); - -// Lower-level versions of Put... that write directly into a character buffer -// REQUIRES: dst has enough space for the value being written -extern void EncodeFixed32(char* dst, uint32_t value); -extern void EncodeFixed64(char* dst, uint64_t value); - -// Lower-level versions of Put... that write directly into a character buffer -// and return a pointer just past the last byte written. -// REQUIRES: dst has enough space for the value being written -extern char* EncodeVarint32(char* dst, uint32_t value); -extern char* EncodeVarint64(char* dst, uint64_t value); - -// Lower-level versions of Get... that read directly from a character buffer -// without any bounds checking. - -inline uint32_t DecodeFixed32(const char* ptr) { - if (port::kLittleEndian) { - // Load the raw bytes - uint32_t result; - memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load - return result; - } else { - return ((static_cast(static_cast(ptr[0]))) - | (static_cast(static_cast(ptr[1])) << 8) - | (static_cast(static_cast(ptr[2])) << 16) - | (static_cast(static_cast(ptr[3])) << 24)); - } -} - -inline uint64_t DecodeFixed64(const char* ptr) { - if (port::kLittleEndian) { - // Load the raw bytes - uint64_t result; - memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load - return result; - } else { - uint64_t lo = DecodeFixed32(ptr); - uint64_t hi = DecodeFixed32(ptr + 4); - return (hi << 32) | lo; - } -} - -// Internal routine for use by fallback path of GetVarint32Ptr -extern const char* GetVarint32PtrFallback(const char* p, - const char* limit, - uint32_t* value); -inline const char* GetVarint32Ptr(const char* p, - const char* limit, - uint32_t* value) { - if (p < limit) { - uint32_t result = *(reinterpret_cast(p)); - if ((result & 128) == 0) { - *value = result; - return p + 1; - } - } - return GetVarint32PtrFallback(p, limit, value); -} - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/src/leveldb/util/coding_test.cc b/src/leveldb/util/coding_test.cc deleted file mode 100644 index 521541ea61..0000000000 --- a/src/leveldb/util/coding_test.cc +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/coding.h" - -#include "util/testharness.h" - -namespace leveldb { - -class Coding { }; - -TEST(Coding, Fixed32) { - std::string s; - for (uint32_t v = 0; v < 100000; v++) { - PutFixed32(&s, v); - } - - const char* p = s.data(); - for (uint32_t v = 0; v < 100000; v++) { - uint32_t actual = DecodeFixed32(p); - ASSERT_EQ(v, actual); - p += sizeof(uint32_t); - } -} - -TEST(Coding, Fixed64) { - std::string s; - for (int power = 0; power <= 63; power++) { - uint64_t v = static_cast(1) << power; - PutFixed64(&s, v - 1); - PutFixed64(&s, v + 0); - PutFixed64(&s, v + 1); - } - - const char* p = s.data(); - for (int power = 0; power <= 63; power++) { - uint64_t v = static_cast(1) << power; - uint64_t actual; - actual = DecodeFixed64(p); - ASSERT_EQ(v-1, actual); - p += sizeof(uint64_t); - - actual = DecodeFixed64(p); - ASSERT_EQ(v+0, actual); - p += sizeof(uint64_t); - - actual = DecodeFixed64(p); - ASSERT_EQ(v+1, actual); - p += sizeof(uint64_t); - } -} - -// Test that encoding routines generate little-endian encodings -TEST(Coding, EncodingOutput) { - std::string dst; - PutFixed32(&dst, 0x04030201); - ASSERT_EQ(4, dst.size()); - ASSERT_EQ(0x01, static_cast(dst[0])); - ASSERT_EQ(0x02, static_cast(dst[1])); - ASSERT_EQ(0x03, static_cast(dst[2])); - ASSERT_EQ(0x04, static_cast(dst[3])); - - dst.clear(); - PutFixed64(&dst, 0x0807060504030201ull); - ASSERT_EQ(8, dst.size()); - ASSERT_EQ(0x01, static_cast(dst[0])); - ASSERT_EQ(0x02, static_cast(dst[1])); - ASSERT_EQ(0x03, static_cast(dst[2])); - ASSERT_EQ(0x04, static_cast(dst[3])); - ASSERT_EQ(0x05, static_cast(dst[4])); - ASSERT_EQ(0x06, static_cast(dst[5])); - ASSERT_EQ(0x07, static_cast(dst[6])); - ASSERT_EQ(0x08, static_cast(dst[7])); -} - -TEST(Coding, Varint32) { - std::string s; - for (uint32_t i = 0; i < (32 * 32); i++) { - uint32_t v = (i / 32) << (i % 32); - PutVarint32(&s, v); - } - - const char* p = s.data(); - const char* limit = p + s.size(); - for (uint32_t i = 0; i < (32 * 32); i++) { - uint32_t expected = (i / 32) << (i % 32); - uint32_t actual; - const char* start = p; - p = GetVarint32Ptr(p, limit, &actual); - ASSERT_TRUE(p != NULL); - ASSERT_EQ(expected, actual); - ASSERT_EQ(VarintLength(actual), p - start); - } - ASSERT_EQ(p, s.data() + s.size()); -} - -TEST(Coding, Varint64) { - // Construct the list of values to check - std::vector values; - // Some special values - values.push_back(0); - values.push_back(100); - values.push_back(~static_cast(0)); - values.push_back(~static_cast(0) - 1); - for (uint32_t k = 0; k < 64; k++) { - // Test values near powers of two - const uint64_t power = 1ull << k; - values.push_back(power); - values.push_back(power-1); - values.push_back(power+1); - } - - std::string s; - for (size_t i = 0; i < values.size(); i++) { - PutVarint64(&s, values[i]); - } - - const char* p = s.data(); - const char* limit = p + s.size(); - for (size_t i = 0; i < values.size(); i++) { - ASSERT_TRUE(p < limit); - uint64_t actual; - const char* start = p; - p = GetVarint64Ptr(p, limit, &actual); - ASSERT_TRUE(p != NULL); - ASSERT_EQ(values[i], actual); - ASSERT_EQ(VarintLength(actual), p - start); - } - ASSERT_EQ(p, limit); - -} - -TEST(Coding, Varint32Overflow) { - uint32_t result; - std::string input("\x81\x82\x83\x84\x85\x11"); - ASSERT_TRUE(GetVarint32Ptr(input.data(), input.data() + input.size(), &result) - == NULL); -} - -TEST(Coding, Varint32Truncation) { - uint32_t large_value = (1u << 31) + 100; - std::string s; - PutVarint32(&s, large_value); - uint32_t result; - for (size_t len = 0; len < s.size() - 1; len++) { - ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL); - } - ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL); - ASSERT_EQ(large_value, result); -} - -TEST(Coding, Varint64Overflow) { - uint64_t result; - std::string input("\x81\x82\x83\x84\x85\x81\x82\x83\x84\x85\x11"); - ASSERT_TRUE(GetVarint64Ptr(input.data(), input.data() + input.size(), &result) - == NULL); -} - -TEST(Coding, Varint64Truncation) { - uint64_t large_value = (1ull << 63) + 100ull; - std::string s; - PutVarint64(&s, large_value); - uint64_t result; - for (size_t len = 0; len < s.size() - 1; len++) { - ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL); - } - ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL); - ASSERT_EQ(large_value, result); -} - -TEST(Coding, Strings) { - std::string s; - PutLengthPrefixedSlice(&s, Slice("")); - PutLengthPrefixedSlice(&s, Slice("foo")); - PutLengthPrefixedSlice(&s, Slice("bar")); - PutLengthPrefixedSlice(&s, Slice(std::string(200, 'x'))); - - Slice input(s); - Slice v; - ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); - ASSERT_EQ("", v.ToString()); - ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); - ASSERT_EQ("foo", v.ToString()); - ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); - ASSERT_EQ("bar", v.ToString()); - ASSERT_TRUE(GetLengthPrefixedSlice(&input, &v)); - ASSERT_EQ(std::string(200, 'x'), v.ToString()); - ASSERT_EQ("", input.ToString()); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/comparator.cc b/src/leveldb/util/comparator.cc deleted file mode 100644 index 4b7b5724ef..0000000000 --- a/src/leveldb/util/comparator.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include "leveldb/comparator.h" -#include "leveldb/slice.h" -#include "port/port.h" -#include "util/logging.h" - -namespace leveldb { - -Comparator::~Comparator() { } - -namespace { -class BytewiseComparatorImpl : public Comparator { - public: - BytewiseComparatorImpl() { } - - virtual const char* Name() const { - return "leveldb.BytewiseComparator"; - } - - virtual int Compare(const Slice& a, const Slice& b) const { - return a.compare(b); - } - - virtual void FindShortestSeparator( - std::string* start, - const Slice& limit) const { - // Find length of common prefix - size_t min_length = std::min(start->size(), limit.size()); - size_t diff_index = 0; - while ((diff_index < min_length) && - ((*start)[diff_index] == limit[diff_index])) { - diff_index++; - } - - if (diff_index >= min_length) { - // Do not shorten if one string is a prefix of the other - } else { - uint8_t diff_byte = static_cast((*start)[diff_index]); - if (diff_byte < static_cast(0xff) && - diff_byte + 1 < static_cast(limit[diff_index])) { - (*start)[diff_index]++; - start->resize(diff_index + 1); - assert(Compare(*start, limit) < 0); - } - } - } - - virtual void FindShortSuccessor(std::string* key) const { - // Find first character that can be incremented - size_t n = key->size(); - for (size_t i = 0; i < n; i++) { - const uint8_t byte = (*key)[i]; - if (byte != static_cast(0xff)) { - (*key)[i] = byte + 1; - key->resize(i+1); - return; - } - } - // *key is a run of 0xffs. Leave it alone. - } -}; -} // namespace - -static port::OnceType once = LEVELDB_ONCE_INIT; -static const Comparator* bytewise; - -static void InitModule() { - bytewise = new BytewiseComparatorImpl; -} - -const Comparator* BytewiseComparator() { - port::InitOnce(&once, InitModule); - return bytewise; -} - -} // namespace leveldb diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc deleted file mode 100644 index 6db9e77077..0000000000 --- a/src/leveldb/util/crc32c.cc +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// A portable implementation of crc32c, optimized to handle -// four bytes at a time. - -#include "util/crc32c.h" - -#include -#include "util/coding.h" - -namespace leveldb { -namespace crc32c { - -static const uint32_t table0_[256] = { - 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, - 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, - 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, - 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, - 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, - 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, - 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, - 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, - 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, - 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, - 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, - 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, - 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, - 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, - 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, - 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, - 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, - 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, - 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, - 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, - 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, - 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, - 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, - 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, - 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, - 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, - 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, - 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, - 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, - 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, - 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, - 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, - 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, - 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, - 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, - 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, - 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, - 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, - 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, - 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, - 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, - 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, - 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, - 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, - 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, - 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, - 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, - 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, - 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, - 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, - 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, - 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, - 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, - 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, - 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, - 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, - 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, - 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, - 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, - 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, - 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, - 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, - 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, - 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351 -}; -static const uint32_t table1_[256] = { - 0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899, - 0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945, - 0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21, - 0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd, - 0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918, - 0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4, - 0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0, - 0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c, - 0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b, - 0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47, - 0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823, - 0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff, - 0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a, - 0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6, - 0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2, - 0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e, - 0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d, - 0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41, - 0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25, - 0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9, - 0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c, - 0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0, - 0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4, - 0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78, - 0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f, - 0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43, - 0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27, - 0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb, - 0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e, - 0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2, - 0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6, - 0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a, - 0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260, - 0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc, - 0x66d73941, 0x7575a136, 0x419209af, 0x523091d8, - 0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004, - 0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1, - 0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d, - 0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059, - 0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185, - 0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162, - 0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be, - 0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da, - 0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306, - 0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3, - 0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f, - 0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b, - 0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287, - 0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464, - 0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8, - 0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc, - 0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600, - 0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5, - 0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439, - 0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d, - 0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781, - 0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766, - 0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba, - 0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de, - 0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502, - 0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7, - 0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b, - 0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f, - 0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483 -}; -static const uint32_t table2_[256] = { - 0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073, - 0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469, - 0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6, - 0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac, - 0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9, - 0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3, - 0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c, - 0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726, - 0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67, - 0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d, - 0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2, - 0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8, - 0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed, - 0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7, - 0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828, - 0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32, - 0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa, - 0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0, - 0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f, - 0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75, - 0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20, - 0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a, - 0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5, - 0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff, - 0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe, - 0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4, - 0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b, - 0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161, - 0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634, - 0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e, - 0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1, - 0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb, - 0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730, - 0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a, - 0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5, - 0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def, - 0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba, - 0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0, - 0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f, - 0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065, - 0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24, - 0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e, - 0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1, - 0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb, - 0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae, - 0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4, - 0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b, - 0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71, - 0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9, - 0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3, - 0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c, - 0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36, - 0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63, - 0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79, - 0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6, - 0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc, - 0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd, - 0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7, - 0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238, - 0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622, - 0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177, - 0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d, - 0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2, - 0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8 -}; -static const uint32_t table3_[256] = { - 0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939, - 0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca, - 0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf, - 0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c, - 0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804, - 0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7, - 0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2, - 0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11, - 0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2, - 0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41, - 0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54, - 0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7, - 0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f, - 0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c, - 0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69, - 0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a, - 0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de, - 0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d, - 0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538, - 0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb, - 0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3, - 0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610, - 0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405, - 0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6, - 0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255, - 0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6, - 0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3, - 0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040, - 0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368, - 0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b, - 0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e, - 0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d, - 0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006, - 0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5, - 0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0, - 0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213, - 0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b, - 0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8, - 0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd, - 0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e, - 0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d, - 0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e, - 0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b, - 0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698, - 0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0, - 0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443, - 0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656, - 0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5, - 0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1, - 0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12, - 0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07, - 0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4, - 0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc, - 0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f, - 0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a, - 0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9, - 0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a, - 0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99, - 0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c, - 0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f, - 0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57, - 0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4, - 0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1, - 0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842 -}; - -// Used to fetch a naturally-aligned 32-bit word in little endian byte-order -static inline uint32_t LE_LOAD32(const uint8_t *p) { - return DecodeFixed32(reinterpret_cast(p)); -} - -uint32_t Extend(uint32_t crc, const char* buf, size_t size) { - const uint8_t *p = reinterpret_cast(buf); - const uint8_t *e = p + size; - uint32_t l = crc ^ 0xffffffffu; - -#define STEP1 do { \ - int c = (l & 0xff) ^ *p++; \ - l = table0_[c] ^ (l >> 8); \ -} while (0) -#define STEP4 do { \ - uint32_t c = l ^ LE_LOAD32(p); \ - p += 4; \ - l = table3_[c & 0xff] ^ \ - table2_[(c >> 8) & 0xff] ^ \ - table1_[(c >> 16) & 0xff] ^ \ - table0_[c >> 24]; \ -} while (0) - - // Point x at first 4-byte aligned byte in string. This might be - // just past the end of the string. - const uintptr_t pval = reinterpret_cast(p); - const uint8_t* x = reinterpret_cast(((pval + 3) >> 2) << 2); - if (x <= e) { - // Process bytes until finished or p is 4-byte aligned - while (p != x) { - STEP1; - } - } - // Process bytes 16 at a time - while ((e-p) >= 16) { - STEP4; STEP4; STEP4; STEP4; - } - // Process bytes 4 at a time - while ((e-p) >= 4) { - STEP4; - } - // Process the last few bytes - while (p != e) { - STEP1; - } -#undef STEP4 -#undef STEP1 - return l ^ 0xffffffffu; -} - -} // namespace crc32c -} // namespace leveldb diff --git a/src/leveldb/util/crc32c.h b/src/leveldb/util/crc32c.h deleted file mode 100644 index 1d7e5c075d..0000000000 --- a/src/leveldb/util/crc32c.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ -#define STORAGE_LEVELDB_UTIL_CRC32C_H_ - -#include -#include - -namespace leveldb { -namespace crc32c { - -// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the -// crc32c of some string A. Extend() is often used to maintain the -// crc32c of a stream of data. -extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n); - -// Return the crc32c of data[0,n-1] -inline uint32_t Value(const char* data, size_t n) { - return Extend(0, data, n); -} - -static const uint32_t kMaskDelta = 0xa282ead8ul; - -// Return a masked representation of crc. -// -// Motivation: it is problematic to compute the CRC of a string that -// contains embedded CRCs. Therefore we recommend that CRCs stored -// somewhere (e.g., in files) should be masked before being stored. -inline uint32_t Mask(uint32_t crc) { - // Rotate right by 15 bits and add a constant. - return ((crc >> 15) | (crc << 17)) + kMaskDelta; -} - -// Return the crc whose masked representation is masked_crc. -inline uint32_t Unmask(uint32_t masked_crc) { - uint32_t rot = masked_crc - kMaskDelta; - return ((rot >> 17) | (rot << 15)); -} - -} // namespace crc32c -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/src/leveldb/util/crc32c_test.cc b/src/leveldb/util/crc32c_test.cc deleted file mode 100644 index 4b957ee120..0000000000 --- a/src/leveldb/util/crc32c_test.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/crc32c.h" -#include "util/testharness.h" - -namespace leveldb { -namespace crc32c { - -class CRC { }; - -TEST(CRC, StandardResults) { - // From rfc3720 section B.4. - char buf[32]; - - memset(buf, 0, sizeof(buf)); - ASSERT_EQ(0x8a9136aa, Value(buf, sizeof(buf))); - - memset(buf, 0xff, sizeof(buf)); - ASSERT_EQ(0x62a8ab43, Value(buf, sizeof(buf))); - - for (int i = 0; i < 32; i++) { - buf[i] = i; - } - ASSERT_EQ(0x46dd794e, Value(buf, sizeof(buf))); - - for (int i = 0; i < 32; i++) { - buf[i] = 31 - i; - } - ASSERT_EQ(0x113fdb5c, Value(buf, sizeof(buf))); - - unsigned char data[48] = { - 0x01, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x18, - 0x28, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }; - ASSERT_EQ(0xd9963a56, Value(reinterpret_cast(data), sizeof(data))); -} - -TEST(CRC, Values) { - ASSERT_NE(Value("a", 1), Value("foo", 3)); -} - -TEST(CRC, Extend) { - ASSERT_EQ(Value("hello world", 11), - Extend(Value("hello ", 6), "world", 5)); -} - -TEST(CRC, Mask) { - uint32_t crc = Value("foo", 3); - ASSERT_NE(crc, Mask(crc)); - ASSERT_NE(crc, Mask(Mask(crc))); - ASSERT_EQ(crc, Unmask(Mask(crc))); - ASSERT_EQ(crc, Unmask(Unmask(Mask(Mask(crc))))); -} - -} // namespace crc32c -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/env.cc b/src/leveldb/util/env.cc deleted file mode 100644 index c2600e964a..0000000000 --- a/src/leveldb/util/env.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/env.h" - -namespace leveldb { - -Env::~Env() { -} - -SequentialFile::~SequentialFile() { -} - -RandomAccessFile::~RandomAccessFile() { -} - -WritableFile::~WritableFile() { -} - -Logger::~Logger() { -} - -FileLock::~FileLock() { -} - -void Log(Logger* info_log, const char* format, ...) { - if (info_log != NULL) { - va_list ap; - va_start(ap, format); - info_log->Logv(format, ap); - va_end(ap); - } -} - -static Status DoWriteStringToFile(Env* env, const Slice& data, - const std::string& fname, - bool should_sync) { - WritableFile* file; - Status s = env->NewWritableFile(fname, &file); - if (!s.ok()) { - return s; - } - s = file->Append(data); - if (s.ok() && should_sync) { - s = file->Sync(); - } - if (s.ok()) { - s = file->Close(); - } - delete file; // Will auto-close if we did not close above - if (!s.ok()) { - env->DeleteFile(fname); - } - return s; -} - -Status WriteStringToFile(Env* env, const Slice& data, - const std::string& fname) { - return DoWriteStringToFile(env, data, fname, false); -} - -Status WriteStringToFileSync(Env* env, const Slice& data, - const std::string& fname) { - return DoWriteStringToFile(env, data, fname, true); -} - -Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { - data->clear(); - SequentialFile* file; - Status s = env->NewSequentialFile(fname, &file); - if (!s.ok()) { - return s; - } - static const int kBufferSize = 8192; - char* space = new char[kBufferSize]; - while (true) { - Slice fragment; - s = file->Read(kBufferSize, &fragment, space); - if (!s.ok()) { - break; - } - data->append(fragment.data(), fragment.size()); - if (fragment.empty()) { - break; - } - } - delete[] space; - delete file; - return s; -} - -EnvWrapper::~EnvWrapper() { -} - -} // namespace leveldb diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc deleted file mode 100644 index ba2667864a..0000000000 --- a/src/leveldb/util/env_posix.cc +++ /dev/null @@ -1,608 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -#if !defined(LEVELDB_PLATFORM_WINDOWS) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "leveldb/env.h" -#include "leveldb/slice.h" -#include "port/port.h" -#include "util/logging.h" -#include "util/mutexlock.h" -#include "util/posix_logger.h" - -namespace leveldb { - -namespace { - -static Status IOError(const std::string& context, int err_number) { - return Status::IOError(context, strerror(err_number)); -} - -class PosixSequentialFile: public SequentialFile { - private: - std::string filename_; - FILE* file_; - - public: - PosixSequentialFile(const std::string& fname, FILE* f) - : filename_(fname), file_(f) { } - virtual ~PosixSequentialFile() { fclose(file_); } - - virtual Status Read(size_t n, Slice* result, char* scratch) { - Status s; - size_t r = fread_unlocked(scratch, 1, n, file_); - *result = Slice(scratch, r); - if (r < n) { - if (feof(file_)) { - // We leave status as ok if we hit the end of the file - } else { - // A partial read with an error: return a non-ok status - s = IOError(filename_, errno); - } - } - return s; - } - - virtual Status Skip(uint64_t n) { - if (fseek(file_, n, SEEK_CUR)) { - return IOError(filename_, errno); - } - return Status::OK(); - } -}; - -// pread() based random-access -class PosixRandomAccessFile: public RandomAccessFile { - private: - std::string filename_; - int fd_; - - public: - PosixRandomAccessFile(const std::string& fname, int fd) - : filename_(fname), fd_(fd) { } - virtual ~PosixRandomAccessFile() { close(fd_); } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const { - Status s; - ssize_t r = pread(fd_, scratch, n, static_cast(offset)); - *result = Slice(scratch, (r < 0) ? 0 : r); - if (r < 0) { - // An error: return a non-ok status - s = IOError(filename_, errno); - } - return s; - } -}; - -// Helper class to limit mmap file usage so that we do not end up -// running out virtual memory or running into kernel performance -// problems for very large databases. -class MmapLimiter { - public: - // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes. - MmapLimiter() { - SetAllowed(sizeof(void*) >= 8 ? 1000 : 0); - } - - // If another mmap slot is available, acquire it and return true. - // Else return false. - bool Acquire() { - if (GetAllowed() <= 0) { - return false; - } - MutexLock l(&mu_); - intptr_t x = GetAllowed(); - if (x <= 0) { - return false; - } else { - SetAllowed(x - 1); - return true; - } - } - - // Release a slot acquired by a previous call to Acquire() that returned true. - void Release() { - MutexLock l(&mu_); - SetAllowed(GetAllowed() + 1); - } - - private: - port::Mutex mu_; - port::AtomicPointer allowed_; - - intptr_t GetAllowed() const { - return reinterpret_cast(allowed_.Acquire_Load()); - } - - // REQUIRES: mu_ must be held - void SetAllowed(intptr_t v) { - allowed_.Release_Store(reinterpret_cast(v)); - } - - MmapLimiter(const MmapLimiter&); - void operator=(const MmapLimiter&); -}; - -// mmap() based random-access -class PosixMmapReadableFile: public RandomAccessFile { - private: - std::string filename_; - void* mmapped_region_; - size_t length_; - MmapLimiter* limiter_; - - public: - // base[0,length-1] contains the mmapped contents of the file. - PosixMmapReadableFile(const std::string& fname, void* base, size_t length, - MmapLimiter* limiter) - : filename_(fname), mmapped_region_(base), length_(length), - limiter_(limiter) { - } - - virtual ~PosixMmapReadableFile() { - munmap(mmapped_region_, length_); - limiter_->Release(); - } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, - char* scratch) const { - Status s; - if (offset + n > length_) { - *result = Slice(); - s = IOError(filename_, EINVAL); - } else { - *result = Slice(reinterpret_cast(mmapped_region_) + offset, n); - } - return s; - } -}; - -class PosixWritableFile : public WritableFile { - private: - std::string filename_; - FILE* file_; - - public: - PosixWritableFile(const std::string& fname, FILE* f) - : filename_(fname), file_(f) { } - - ~PosixWritableFile() { - if (file_ != NULL) { - // Ignoring any potential errors - fclose(file_); - } - } - - virtual Status Append(const Slice& data) { - size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); - if (r != data.size()) { - return IOError(filename_, errno); - } - return Status::OK(); - } - - virtual Status Close() { - Status result; - if (fclose(file_) != 0) { - result = IOError(filename_, errno); - } - file_ = NULL; - return result; - } - - virtual Status Flush() { - if (fflush_unlocked(file_) != 0) { - return IOError(filename_, errno); - } - return Status::OK(); - } - - Status SyncDirIfManifest() { - const char* f = filename_.c_str(); - const char* sep = strrchr(f, '/'); - Slice basename; - std::string dir; - if (sep == NULL) { - dir = "."; - basename = f; - } else { - dir = std::string(f, sep - f); - basename = sep + 1; - } - Status s; - if (basename.starts_with("MANIFEST")) { - int fd = open(dir.c_str(), O_RDONLY); - if (fd < 0) { - s = IOError(dir, errno); - } else { - if (fsync(fd) < 0) { - s = IOError(dir, errno); - } - close(fd); - } - } - return s; - } - - virtual Status Sync() { - // Ensure new files referred to by the manifest are in the filesystem. - Status s = SyncDirIfManifest(); - if (!s.ok()) { - return s; - } - if (fflush_unlocked(file_) != 0 || - fdatasync(fileno(file_)) != 0) { - s = Status::IOError(filename_, strerror(errno)); - } - return s; - } -}; - -static int LockOrUnlock(int fd, bool lock) { - errno = 0; - struct flock f; - memset(&f, 0, sizeof(f)); - f.l_type = (lock ? F_WRLCK : F_UNLCK); - f.l_whence = SEEK_SET; - f.l_start = 0; - f.l_len = 0; // Lock/unlock entire file - return fcntl(fd, F_SETLK, &f); -} - -class PosixFileLock : public FileLock { - public: - int fd_; - std::string name_; -}; - -// Set of locked files. We keep a separate set instead of just -// relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide -// any protection against multiple uses from the same process. -class PosixLockTable { - private: - port::Mutex mu_; - std::set locked_files_; - public: - bool Insert(const std::string& fname) { - MutexLock l(&mu_); - return locked_files_.insert(fname).second; - } - void Remove(const std::string& fname) { - MutexLock l(&mu_); - locked_files_.erase(fname); - } -}; - -class PosixEnv : public Env { - public: - PosixEnv(); - virtual ~PosixEnv() { - char msg[] = "Destroying Env::Default()\n"; - fwrite(msg, 1, sizeof(msg), stderr); - abort(); - } - - virtual Status NewSequentialFile(const std::string& fname, - SequentialFile** result) { - FILE* f = fopen(fname.c_str(), "r"); - if (f == NULL) { - *result = NULL; - return IOError(fname, errno); - } else { - *result = new PosixSequentialFile(fname, f); - return Status::OK(); - } - } - - virtual Status NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result) { - *result = NULL; - Status s; - int fd = open(fname.c_str(), O_RDONLY); - if (fd < 0) { - s = IOError(fname, errno); - } else if (mmap_limit_.Acquire()) { - uint64_t size; - s = GetFileSize(fname, &size); - if (s.ok()) { - void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (base != MAP_FAILED) { - *result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_); - } else { - s = IOError(fname, errno); - } - } - close(fd); - if (!s.ok()) { - mmap_limit_.Release(); - } - } else { - *result = new PosixRandomAccessFile(fname, fd); - } - return s; - } - - virtual Status NewWritableFile(const std::string& fname, - WritableFile** result) { - Status s; - FILE* f = fopen(fname.c_str(), "w"); - if (f == NULL) { - *result = NULL; - s = IOError(fname, errno); - } else { - *result = new PosixWritableFile(fname, f); - } - return s; - } - - virtual bool FileExists(const std::string& fname) { - return access(fname.c_str(), F_OK) == 0; - } - - virtual Status GetChildren(const std::string& dir, - std::vector* result) { - result->clear(); - DIR* d = opendir(dir.c_str()); - if (d == NULL) { - return IOError(dir, errno); - } - struct dirent* entry; - while ((entry = readdir(d)) != NULL) { - result->push_back(entry->d_name); - } - closedir(d); - return Status::OK(); - } - - virtual Status DeleteFile(const std::string& fname) { - Status result; - if (unlink(fname.c_str()) != 0) { - result = IOError(fname, errno); - } - return result; - } - - virtual Status CreateDir(const std::string& name) { - Status result; - if (mkdir(name.c_str(), 0755) != 0) { - result = IOError(name, errno); - } - return result; - } - - virtual Status DeleteDir(const std::string& name) { - Status result; - if (rmdir(name.c_str()) != 0) { - result = IOError(name, errno); - } - return result; - } - - virtual Status GetFileSize(const std::string& fname, uint64_t* size) { - Status s; - struct stat sbuf; - if (stat(fname.c_str(), &sbuf) != 0) { - *size = 0; - s = IOError(fname, errno); - } else { - *size = sbuf.st_size; - } - return s; - } - - virtual Status RenameFile(const std::string& src, const std::string& target) { - Status result; - if (rename(src.c_str(), target.c_str()) != 0) { - result = IOError(src, errno); - } - return result; - } - - virtual Status LockFile(const std::string& fname, FileLock** lock) { - *lock = NULL; - Status result; - int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644); - if (fd < 0) { - result = IOError(fname, errno); - } else if (!locks_.Insert(fname)) { - close(fd); - result = Status::IOError("lock " + fname, "already held by process"); - } else if (LockOrUnlock(fd, true) == -1) { - result = IOError("lock " + fname, errno); - close(fd); - locks_.Remove(fname); - } else { - PosixFileLock* my_lock = new PosixFileLock; - my_lock->fd_ = fd; - my_lock->name_ = fname; - *lock = my_lock; - } - return result; - } - - virtual Status UnlockFile(FileLock* lock) { - PosixFileLock* my_lock = reinterpret_cast(lock); - Status result; - if (LockOrUnlock(my_lock->fd_, false) == -1) { - result = IOError("unlock", errno); - } - locks_.Remove(my_lock->name_); - close(my_lock->fd_); - delete my_lock; - return result; - } - - virtual void Schedule(void (*function)(void*), void* arg); - - virtual void StartThread(void (*function)(void* arg), void* arg); - - virtual Status GetTestDirectory(std::string* result) { - const char* env = getenv("TEST_TMPDIR"); - if (env && env[0] != '\0') { - *result = env; - } else { - char buf[100]; - snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid())); - *result = buf; - } - // Directory may already exist - CreateDir(*result); - return Status::OK(); - } - - static uint64_t gettid() { - pthread_t tid = pthread_self(); - uint64_t thread_id = 0; - memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid))); - return thread_id; - } - - virtual Status NewLogger(const std::string& fname, Logger** result) { - FILE* f = fopen(fname.c_str(), "w"); - if (f == NULL) { - *result = NULL; - return IOError(fname, errno); - } else { - *result = new PosixLogger(f, &PosixEnv::gettid); - return Status::OK(); - } - } - - virtual uint64_t NowMicros() { - struct timeval tv; - gettimeofday(&tv, NULL); - return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; - } - - virtual void SleepForMicroseconds(int micros) { - usleep(micros); - } - - private: - void PthreadCall(const char* label, int result) { - if (result != 0) { - fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); - abort(); - } - } - - // BGThread() is the body of the background thread - void BGThread(); - static void* BGThreadWrapper(void* arg) { - reinterpret_cast(arg)->BGThread(); - return NULL; - } - - pthread_mutex_t mu_; - pthread_cond_t bgsignal_; - pthread_t bgthread_; - bool started_bgthread_; - - // Entry per Schedule() call - struct BGItem { void* arg; void (*function)(void*); }; - typedef std::deque BGQueue; - BGQueue queue_; - - PosixLockTable locks_; - MmapLimiter mmap_limit_; -}; - -PosixEnv::PosixEnv() : started_bgthread_(false) { - PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL)); - PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL)); -} - -void PosixEnv::Schedule(void (*function)(void*), void* arg) { - PthreadCall("lock", pthread_mutex_lock(&mu_)); - - // Start background thread if necessary - if (!started_bgthread_) { - started_bgthread_ = true; - PthreadCall( - "create thread", - pthread_create(&bgthread_, NULL, &PosixEnv::BGThreadWrapper, this)); - } - - // If the queue is currently empty, the background thread may currently be - // waiting. - if (queue_.empty()) { - PthreadCall("signal", pthread_cond_signal(&bgsignal_)); - } - - // Add to priority queue - queue_.push_back(BGItem()); - queue_.back().function = function; - queue_.back().arg = arg; - - PthreadCall("unlock", pthread_mutex_unlock(&mu_)); -} - -void PosixEnv::BGThread() { - while (true) { - // Wait until there is an item that is ready to run - PthreadCall("lock", pthread_mutex_lock(&mu_)); - while (queue_.empty()) { - PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_)); - } - - void (*function)(void*) = queue_.front().function; - void* arg = queue_.front().arg; - queue_.pop_front(); - - PthreadCall("unlock", pthread_mutex_unlock(&mu_)); - (*function)(arg); - } -} - -namespace { -struct StartThreadState { - void (*user_function)(void*); - void* arg; -}; -} -static void* StartThreadWrapper(void* arg) { - StartThreadState* state = reinterpret_cast(arg); - state->user_function(state->arg); - delete state; - return NULL; -} - -void PosixEnv::StartThread(void (*function)(void* arg), void* arg) { - pthread_t t; - StartThreadState* state = new StartThreadState; - state->user_function = function; - state->arg = arg; - PthreadCall("start thread", - pthread_create(&t, NULL, &StartThreadWrapper, state)); -} - -} // namespace - -static pthread_once_t once = PTHREAD_ONCE_INIT; -static Env* default_env; -static void InitDefaultEnv() { default_env = new PosixEnv; } - -Env* Env::Default() { - pthread_once(&once, InitDefaultEnv); - return default_env; -} - -} // namespace leveldb - -#endif diff --git a/src/leveldb/util/env_test.cc b/src/leveldb/util/env_test.cc deleted file mode 100644 index b72cb44384..0000000000 --- a/src/leveldb/util/env_test.cc +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/env.h" - -#include "port/port.h" -#include "util/testharness.h" - -namespace leveldb { - -static const int kDelayMicros = 100000; - -class EnvPosixTest { - private: - port::Mutex mu_; - std::string events_; - - public: - Env* env_; - EnvPosixTest() : env_(Env::Default()) { } -}; - -static void SetBool(void* ptr) { - reinterpret_cast(ptr)->NoBarrier_Store(ptr); -} - -TEST(EnvPosixTest, RunImmediately) { - port::AtomicPointer called (NULL); - env_->Schedule(&SetBool, &called); - Env::Default()->SleepForMicroseconds(kDelayMicros); - ASSERT_TRUE(called.NoBarrier_Load() != NULL); -} - -TEST(EnvPosixTest, RunMany) { - port::AtomicPointer last_id (NULL); - - struct CB { - port::AtomicPointer* last_id_ptr; // Pointer to shared slot - uintptr_t id; // Order# for the execution of this callback - - CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { } - - static void Run(void* v) { - CB* cb = reinterpret_cast(v); - void* cur = cb->last_id_ptr->NoBarrier_Load(); - ASSERT_EQ(cb->id-1, reinterpret_cast(cur)); - cb->last_id_ptr->Release_Store(reinterpret_cast(cb->id)); - } - }; - - // Schedule in different order than start time - CB cb1(&last_id, 1); - CB cb2(&last_id, 2); - CB cb3(&last_id, 3); - CB cb4(&last_id, 4); - env_->Schedule(&CB::Run, &cb1); - env_->Schedule(&CB::Run, &cb2); - env_->Schedule(&CB::Run, &cb3); - env_->Schedule(&CB::Run, &cb4); - - Env::Default()->SleepForMicroseconds(kDelayMicros); - void* cur = last_id.Acquire_Load(); - ASSERT_EQ(4, reinterpret_cast(cur)); -} - -struct State { - port::Mutex mu; - int val; - int num_running; -}; - -static void ThreadBody(void* arg) { - State* s = reinterpret_cast(arg); - s->mu.Lock(); - s->val += 1; - s->num_running -= 1; - s->mu.Unlock(); -} - -TEST(EnvPosixTest, StartThread) { - State state; - state.val = 0; - state.num_running = 3; - for (int i = 0; i < 3; i++) { - env_->StartThread(&ThreadBody, &state); - } - while (true) { - state.mu.Lock(); - int num = state.num_running; - state.mu.Unlock(); - if (num == 0) { - break; - } - Env::Default()->SleepForMicroseconds(kDelayMicros); - } - ASSERT_EQ(state.val, 3); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc deleted file mode 100644 index e11a96b791..0000000000 --- a/src/leveldb/util/env_win.cc +++ /dev/null @@ -1,873 +0,0 @@ -// This file contains source that originates from: -// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/env_win32.h -// http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/port_win32.cc -// Those files dont' have any explict license headers but the -// project (http://code.google.com/p/leveldbwin/) lists the 'New BSD License' -// as the license. -#if defined(LEVELDB_PLATFORM_WINDOWS) -#include - - -#include "leveldb/env.h" - -#include "port/port.h" -#include "leveldb/slice.h" -#include "util/logging.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef max -#undef max -#endif - -#ifndef va_copy -#define va_copy(d,s) ((d) = (s)) -#endif - -#if defined DeleteFile -#undef DeleteFile -#endif - -//Declarations -namespace leveldb -{ - -namespace Win32 -{ - -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -std::string GetCurrentDir(); -std::wstring GetCurrentDirW(); - -static const std::string CurrentDir = GetCurrentDir(); -static const std::wstring CurrentDirW = GetCurrentDirW(); - -std::string& ModifyPath(std::string& path); -std::wstring& ModifyPath(std::wstring& path); - -std::string GetLastErrSz(); -std::wstring GetLastErrSzW(); - -size_t GetPageSize(); - -typedef void (*ScheduleProc)(void*) ; - -struct WorkItemWrapper -{ - WorkItemWrapper(ScheduleProc proc_,void* content_); - ScheduleProc proc; - void* pContent; -}; - -DWORD WINAPI WorkItemWrapperProc(LPVOID pContent); - -class Win32SequentialFile : public SequentialFile -{ -public: - friend class Win32Env; - virtual ~Win32SequentialFile(); - virtual Status Read(size_t n, Slice* result, char* scratch); - virtual Status Skip(uint64_t n); - BOOL isEnable(); -private: - BOOL _Init(); - void _CleanUp(); - Win32SequentialFile(const std::string& fname); - std::string _filename; - ::HANDLE _hFile; - DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile); -}; - -class Win32RandomAccessFile : public RandomAccessFile -{ -public: - friend class Win32Env; - virtual ~Win32RandomAccessFile(); - virtual Status Read(uint64_t offset, size_t n, Slice* result,char* scratch) const; - BOOL isEnable(); -private: - BOOL _Init(LPCWSTR path); - void _CleanUp(); - Win32RandomAccessFile(const std::string& fname); - HANDLE _hFile; - const std::string _filename; - DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile); -}; - -class Win32WritableFile : public WritableFile -{ -public: - Win32WritableFile(const std::string& fname); - ~Win32WritableFile(); - - virtual Status Append(const Slice& data); - virtual Status Close(); - virtual Status Flush(); - virtual Status Sync(); - BOOL isEnable(); -private: - std::string filename_; - ::HANDLE _hFile; -}; - -class Win32FileLock : public FileLock -{ -public: - friend class Win32Env; - virtual ~Win32FileLock(); - BOOL isEnable(); -private: - BOOL _Init(LPCWSTR path); - void _CleanUp(); - Win32FileLock(const std::string& fname); - HANDLE _hFile; - std::string _filename; - DISALLOW_COPY_AND_ASSIGN(Win32FileLock); -}; - -class Win32Logger : public Logger -{ -public: - friend class Win32Env; - virtual ~Win32Logger(); - virtual void Logv(const char* format, va_list ap); -private: - explicit Win32Logger(WritableFile* pFile); - WritableFile* _pFileProxy; - DISALLOW_COPY_AND_ASSIGN(Win32Logger); -}; - -class Win32Env : public Env -{ -public: - Win32Env(); - virtual ~Win32Env(); - virtual Status NewSequentialFile(const std::string& fname, - SequentialFile** result); - - virtual Status NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result); - virtual Status NewWritableFile(const std::string& fname, - WritableFile** result); - - virtual bool FileExists(const std::string& fname); - - virtual Status GetChildren(const std::string& dir, - std::vector* result); - - virtual Status DeleteFile(const std::string& fname); - - virtual Status CreateDir(const std::string& dirname); - - virtual Status DeleteDir(const std::string& dirname); - - virtual Status GetFileSize(const std::string& fname, uint64_t* file_size); - - virtual Status RenameFile(const std::string& src, - const std::string& target); - - virtual Status LockFile(const std::string& fname, FileLock** lock); - - virtual Status UnlockFile(FileLock* lock); - - virtual void Schedule( - void (*function)(void* arg), - void* arg); - - virtual void StartThread(void (*function)(void* arg), void* arg); - - virtual Status GetTestDirectory(std::string* path); - - //virtual void Logv(WritableFile* log, const char* format, va_list ap); - - virtual Status NewLogger(const std::string& fname, Logger** result); - - virtual uint64_t NowMicros(); - - virtual void SleepForMicroseconds(int micros); -}; - -void ToWidePath(const std::string& value, std::wstring& target) { - wchar_t buffer[MAX_PATH]; - MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH); - target = buffer; -} - -void ToNarrowPath(const std::wstring& value, std::string& target) { - char buffer[MAX_PATH]; - WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL); - target = buffer; -} - -std::string GetCurrentDir() -{ - CHAR path[MAX_PATH]; - ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH); - *strrchr(path,'\\') = 0; - return std::string(path); -} - -std::wstring GetCurrentDirW() -{ - WCHAR path[MAX_PATH]; - ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH); - *wcsrchr(path,L'\\') = 0; - return std::wstring(path); -} - -std::string& ModifyPath(std::string& path) -{ - if(path[0] == '/' || path[0] == '\\'){ - path = CurrentDir + path; - } - std::replace(path.begin(),path.end(),'/','\\'); - - return path; -} - -std::wstring& ModifyPath(std::wstring& path) -{ - if(path[0] == L'/' || path[0] == L'\\'){ - path = CurrentDirW + path; - } - std::replace(path.begin(),path.end(),L'/',L'\\'); - return path; -} - -std::string GetLastErrSz() -{ - LPWSTR lpMsgBuf; - FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - 0, // Default language - (LPWSTR) &lpMsgBuf, - 0, - NULL - ); - std::string Err; - ToNarrowPath(lpMsgBuf, Err); - LocalFree( lpMsgBuf ); - return Err; -} - -std::wstring GetLastErrSzW() -{ - LPVOID lpMsgBuf; - FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - 0, // Default language - (LPWSTR) &lpMsgBuf, - 0, - NULL - ); - std::wstring Err = (LPCWSTR)lpMsgBuf; - LocalFree(lpMsgBuf); - return Err; -} - -WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) : - proc(proc_),pContent(content_) -{ - -} - -DWORD WINAPI WorkItemWrapperProc(LPVOID pContent) -{ - WorkItemWrapper* item = static_cast(pContent); - ScheduleProc TempProc = item->proc; - void* arg = item->pContent; - delete item; - TempProc(arg); - return 0; -} - -size_t GetPageSize() -{ - SYSTEM_INFO si; - GetSystemInfo(&si); - return std::max(si.dwPageSize,si.dwAllocationGranularity); -} - -const size_t g_PageSize = GetPageSize(); - - -Win32SequentialFile::Win32SequentialFile( const std::string& fname ) : - _filename(fname),_hFile(NULL) -{ - _Init(); -} - -Win32SequentialFile::~Win32SequentialFile() -{ - _CleanUp(); -} - -Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch ) -{ - Status sRet; - DWORD hasRead = 0; - if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){ - *result = Slice(scratch,hasRead); - } else { - sRet = Status::IOError(_filename, Win32::GetLastErrSz() ); - } - return sRet; -} - -Status Win32SequentialFile::Skip( uint64_t n ) -{ - Status sRet; - LARGE_INTEGER Move,NowPointer; - Move.QuadPart = n; - if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){ - sRet = Status::IOError(_filename,Win32::GetLastErrSz()); - } - return sRet; -} - -BOOL Win32SequentialFile::isEnable() -{ - return _hFile ? TRUE : FALSE; -} - -BOOL Win32SequentialFile::_Init() -{ - std::wstring path; - ToWidePath(_filename, path); - _hFile = CreateFileW(path.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - return _hFile ? TRUE : FALSE; -} - -void Win32SequentialFile::_CleanUp() -{ - if(_hFile){ - CloseHandle(_hFile); - _hFile = NULL; - } -} - -Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) : - _filename(fname),_hFile(NULL) -{ - std::wstring path; - ToWidePath(fname, path); - _Init( path.c_str() ); -} - -Win32RandomAccessFile::~Win32RandomAccessFile() -{ - _CleanUp(); -} - -Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const -{ - Status sRet; - OVERLAPPED ol = {0}; - ZeroMemory(&ol,sizeof(ol)); - ol.Offset = (DWORD)offset; - ol.OffsetHigh = (DWORD)(offset >> 32); - DWORD hasRead = 0; - if(!ReadFile(_hFile,scratch,n,&hasRead,&ol)) - sRet = Status::IOError(_filename,Win32::GetLastErrSz()); - else - *result = Slice(scratch,hasRead); - return sRet; -} - -BOOL Win32RandomAccessFile::_Init( LPCWSTR path ) -{ - BOOL bRet = FALSE; - if(!_hFile) - _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL); - if(!_hFile || _hFile == INVALID_HANDLE_VALUE ) - _hFile = NULL; - else - bRet = TRUE; - return bRet; -} - -BOOL Win32RandomAccessFile::isEnable() -{ - return _hFile ? TRUE : FALSE; -} - -void Win32RandomAccessFile::_CleanUp() -{ - if(_hFile){ - ::CloseHandle(_hFile); - _hFile = NULL; - } -} - -Win32WritableFile::Win32WritableFile(const std::string& fname) - : filename_(fname) -{ - std::wstring path; - ToWidePath(fname, path); - DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS; - _hFile = CreateFileW(path.c_str(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, - NULL, - Flag, - FILE_ATTRIBUTE_NORMAL, - NULL); - // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use -} - -Win32WritableFile::~Win32WritableFile() -{ - if (_hFile != INVALID_HANDLE_VALUE) - Close(); -} - -Status Win32WritableFile::Append(const Slice& data) -{ - DWORD r = 0; - if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) { - return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz()); - } - return Status::OK(); -} - -Status Win32WritableFile::Close() -{ - if (!CloseHandle(_hFile)) { - return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz()); - } - _hFile = INVALID_HANDLE_VALUE; - return Status::OK(); -} - -Status Win32WritableFile::Flush() -{ - // Nothing to do here, there are no application-side buffers - return Status::OK(); -} - -Status Win32WritableFile::Sync() -{ - if (!FlushFileBuffers(_hFile)) { - return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz()); - } - return Status::OK(); -} - -BOOL Win32WritableFile::isEnable() -{ - return _hFile != INVALID_HANDLE_VALUE; -} - -Win32FileLock::Win32FileLock( const std::string& fname ) : - _hFile(NULL),_filename(fname) -{ - std::wstring path; - ToWidePath(fname, path); - _Init(path.c_str()); -} - -Win32FileLock::~Win32FileLock() -{ - _CleanUp(); -} - -BOOL Win32FileLock::_Init( LPCWSTR path ) -{ - BOOL bRet = FALSE; - if(!_hFile) - _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); - if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){ - _hFile = NULL; - } - else - bRet = TRUE; - return bRet; -} - -void Win32FileLock::_CleanUp() -{ - ::CloseHandle(_hFile); - _hFile = NULL; -} - -BOOL Win32FileLock::isEnable() -{ - return _hFile ? TRUE : FALSE; -} - -Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile) -{ - assert(_pFileProxy); -} - -Win32Logger::~Win32Logger() -{ - if(_pFileProxy) - delete _pFileProxy; -} - -void Win32Logger::Logv( const char* format, va_list ap ) -{ - uint64_t thread_id = ::GetCurrentThreadId(); - - // We try twice: the first time with a fixed-size stack allocated buffer, - // and the second time with a much larger dynamically allocated buffer. - char buffer[500]; - for (int iter = 0; iter < 2; iter++) { - char* base; - int bufsize; - if (iter == 0) { - bufsize = sizeof(buffer); - base = buffer; - } else { - bufsize = 30000; - base = new char[bufsize]; - } - char* p = base; - char* limit = base + bufsize; - - SYSTEMTIME st; - GetLocalTime(&st); - p += snprintf(p, limit - p, - "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", - int(st.wYear), - int(st.wMonth), - int(st.wDay), - int(st.wHour), - int(st.wMinute), - int(st.wMinute), - int(st.wMilliseconds), - static_cast(thread_id)); - - // Print the message - if (p < limit) { - va_list backup_ap; - va_copy(backup_ap, ap); - p += vsnprintf(p, limit - p, format, backup_ap); - va_end(backup_ap); - } - - // Truncate to available space if necessary - if (p >= limit) { - if (iter == 0) { - continue; // Try again with larger buffer - } else { - p = limit - 1; - } - } - - // Add newline if necessary - if (p == base || p[-1] != '\n') { - *p++ = '\n'; - } - - assert(p <= limit); - DWORD hasWritten = 0; - if(_pFileProxy){ - _pFileProxy->Append(Slice(base, p - base)); - _pFileProxy->Flush(); - } - if (base != buffer) { - delete[] base; - } - break; - } -} - -bool Win32Env::FileExists(const std::string& fname) -{ - std::string path = fname; - std::wstring wpath; - ToWidePath(ModifyPath(path), wpath); - return ::PathFileExistsW(wpath.c_str()) ? true : false; -} - -Status Win32Env::GetChildren(const std::string& dir, std::vector* result) -{ - Status sRet; - ::WIN32_FIND_DATAW wfd; - std::string path = dir; - ModifyPath(path); - path += "\\*.*"; - std::wstring wpath; - ToWidePath(path, wpath); - - ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd); - if(hFind && hFind != INVALID_HANDLE_VALUE){ - BOOL hasNext = TRUE; - std::string child; - while(hasNext){ - ToNarrowPath(wfd.cFileName, child); - if(child != ".." && child != ".") { - result->push_back(child); - } - hasNext = ::FindNextFileW(hFind,&wfd); - } - ::FindClose(hFind); - } - else - sRet = Status::IOError(dir,"Could not get children."); - return sRet; -} - -void Win32Env::SleepForMicroseconds( int micros ) -{ - ::Sleep((micros + 999) /1000); -} - - -Status Win32Env::DeleteFile( const std::string& fname ) -{ - Status sRet; - std::string path = fname; - std::wstring wpath; - ToWidePath(ModifyPath(path), wpath); - - if(!::DeleteFileW(wpath.c_str())) { - sRet = Status::IOError(path, "Could not delete file."); - } - return sRet; -} - -Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size ) -{ - Status sRet; - std::string path = fname; - std::wstring wpath; - ToWidePath(ModifyPath(path), wpath); - - HANDLE file = ::CreateFileW(wpath.c_str(), - GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); - LARGE_INTEGER li; - if(::GetFileSizeEx(file,&li)){ - *file_size = (uint64_t)li.QuadPart; - }else - sRet = Status::IOError(path,"Could not get the file size."); - CloseHandle(file); - return sRet; -} - -Status Win32Env::RenameFile( const std::string& src, const std::string& target ) -{ - Status sRet; - std::string src_path = src; - std::wstring wsrc_path; - ToWidePath(ModifyPath(src_path), wsrc_path); - std::string target_path = target; - std::wstring wtarget_path; - ToWidePath(ModifyPath(target_path), wtarget_path); - - if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){ - DWORD err = GetLastError(); - if(err == 0x000000b7){ - if(!::DeleteFileW(wtarget_path.c_str() ) ) - sRet = Status::IOError(src, "Could not rename file."); - else if(!::MoveFileW(wsrc_path.c_str(), - wtarget_path.c_str() ) ) - sRet = Status::IOError(src, "Could not rename file."); - } - } - return sRet; -} - -Status Win32Env::LockFile( const std::string& fname, FileLock** lock ) -{ - Status sRet; - std::string path = fname; - ModifyPath(path); - Win32FileLock* _lock = new Win32FileLock(path); - if(!_lock->isEnable()){ - delete _lock; - *lock = NULL; - sRet = Status::IOError(path, "Could not lock file."); - } - else - *lock = _lock; - return sRet; -} - -Status Win32Env::UnlockFile( FileLock* lock ) -{ - Status sRet; - delete lock; - return sRet; -} - -void Win32Env::Schedule( void (*function)(void* arg), void* arg ) -{ - QueueUserWorkItem(Win32::WorkItemWrapperProc, - new Win32::WorkItemWrapper(function,arg), - WT_EXECUTEDEFAULT); -} - -void Win32Env::StartThread( void (*function)(void* arg), void* arg ) -{ - ::_beginthread(function,0,arg); -} - -Status Win32Env::GetTestDirectory( std::string* path ) -{ - Status sRet; - WCHAR TempPath[MAX_PATH]; - ::GetTempPathW(MAX_PATH,TempPath); - ToNarrowPath(TempPath, *path); - path->append("leveldb\\test\\"); - ModifyPath(*path); - return sRet; -} - -uint64_t Win32Env::NowMicros() -{ -#ifndef USE_VISTA_API -#define GetTickCount64 GetTickCount -#endif - return (uint64_t)(GetTickCount64()*1000); -} - -static Status CreateDirInner( const std::string& dirname ) -{ - Status sRet; - DWORD attr = ::GetFileAttributes(dirname.c_str()); - if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist: - std::size_t slash = dirname.find_last_of("\\"); - if (slash != std::string::npos){ - sRet = CreateDirInner(dirname.substr(0, slash)); - if (!sRet.ok()) return sRet; - } - BOOL result = ::CreateDirectory(dirname.c_str(), NULL); - if (result == FALSE) { - sRet = Status::IOError(dirname, "Could not create directory."); - return sRet; - } - } - return sRet; -} - -Status Win32Env::CreateDir( const std::string& dirname ) -{ - std::string path = dirname; - if(path[path.length() - 1] != '\\'){ - path += '\\'; - } - ModifyPath(path); - - return CreateDirInner(path); -} - -Status Win32Env::DeleteDir( const std::string& dirname ) -{ - Status sRet; - std::wstring path; - ToWidePath(dirname, path); - ModifyPath(path); - if(!::RemoveDirectoryW( path.c_str() ) ){ - sRet = Status::IOError(dirname, "Could not delete directory."); - } - return sRet; -} - -Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result ) -{ - Status sRet; - std::string path = fname; - ModifyPath(path); - Win32SequentialFile* pFile = new Win32SequentialFile(path); - if(pFile->isEnable()){ - *result = pFile; - }else { - delete pFile; - sRet = Status::IOError(path, Win32::GetLastErrSz()); - } - return sRet; -} - -Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result ) -{ - Status sRet; - std::string path = fname; - Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path)); - if(!pFile->isEnable()){ - delete pFile; - *result = NULL; - sRet = Status::IOError(path, Win32::GetLastErrSz()); - }else - *result = pFile; - return sRet; -} - -Status Win32Env::NewLogger( const std::string& fname, Logger** result ) -{ - Status sRet; - std::string path = fname; - Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path)); - if(!pMapFile->isEnable()){ - delete pMapFile; - *result = NULL; - sRet = Status::IOError(path,"could not create a logger."); - }else - *result = new Win32Logger(pMapFile); - return sRet; -} - -Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result ) -{ - Status sRet; - std::string path = fname; - Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path)); - if(!pFile->isEnable()){ - *result = NULL; - sRet = Status::IOError(fname,Win32::GetLastErrSz()); - }else - *result = pFile; - return sRet; -} - -Win32Env::Win32Env() -{ - -} - -Win32Env::~Win32Env() -{ - -} - - -} // Win32 namespace - -static port::OnceType once = LEVELDB_ONCE_INIT; -static Env* default_env; -static void InitDefaultEnv() { default_env = new Win32::Win32Env(); } - -Env* Env::Default() { - port::InitOnce(&once, InitDefaultEnv); - return default_env; -} - -} // namespace leveldb - -#endif // defined(LEVELDB_PLATFORM_WINDOWS) diff --git a/src/leveldb/util/filter_policy.cc b/src/leveldb/util/filter_policy.cc deleted file mode 100644 index 7b045c8c91..0000000000 --- a/src/leveldb/util/filter_policy.cc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2012 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/filter_policy.h" - -namespace leveldb { - -FilterPolicy::~FilterPolicy() { } - -} // namespace leveldb diff --git a/src/leveldb/util/hash.cc b/src/leveldb/util/hash.cc deleted file mode 100644 index ed439ce7a2..0000000000 --- a/src/leveldb/util/hash.cc +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include "util/coding.h" -#include "util/hash.h" - -// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through -// between switch labels. The real definition should be provided externally. -// This one is a fallback version for unsupported compilers. -#ifndef FALLTHROUGH_INTENDED -#define FALLTHROUGH_INTENDED do { } while (0) -#endif - -namespace leveldb { - -uint32_t Hash(const char* data, size_t n, uint32_t seed) { - // Similar to murmur hash - const uint32_t m = 0xc6a4a793; - const uint32_t r = 24; - const char* limit = data + n; - uint32_t h = seed ^ (n * m); - - // Pick up four bytes at a time - while (data + 4 <= limit) { - uint32_t w = DecodeFixed32(data); - data += 4; - h += w; - h *= m; - h ^= (h >> 16); - } - - // Pick up remaining bytes - switch (limit - data) { - case 3: - h += static_cast(data[2]) << 16; - FALLTHROUGH_INTENDED; - case 2: - h += static_cast(data[1]) << 8; - FALLTHROUGH_INTENDED; - case 1: - h += static_cast(data[0]); - h *= m; - h ^= (h >> r); - break; - } - return h; -} - - -} // namespace leveldb diff --git a/src/leveldb/util/hash.h b/src/leveldb/util/hash.h deleted file mode 100644 index 8889d56be8..0000000000 --- a/src/leveldb/util/hash.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Simple hash function used for internal data structures - -#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ -#define STORAGE_LEVELDB_UTIL_HASH_H_ - -#include -#include - -namespace leveldb { - -extern uint32_t Hash(const char* data, size_t n, uint32_t seed); - -} - -#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/src/leveldb/util/hash_test.cc b/src/leveldb/util/hash_test.cc deleted file mode 100644 index eaa1c92c23..0000000000 --- a/src/leveldb/util/hash_test.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/hash.h" -#include "util/testharness.h" - -namespace leveldb { - -class HASH { }; - -TEST(HASH, SignedUnsignedIssue) { - const unsigned char data1[1] = {0x62}; - const unsigned char data2[2] = {0xc3, 0x97}; - const unsigned char data3[3] = {0xe2, 0x99, 0xa5}; - const unsigned char data4[4] = {0xe1, 0x80, 0xb9, 0x32}; - const unsigned char data5[48] = { - 0x01, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x00, 0x18, - 0x28, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }; - - ASSERT_EQ(Hash(0, 0, 0xbc9f1d34), 0xbc9f1d34); - ASSERT_EQ( - Hash(reinterpret_cast(data1), sizeof(data1), 0xbc9f1d34), - 0xef1345c4); - ASSERT_EQ( - Hash(reinterpret_cast(data2), sizeof(data2), 0xbc9f1d34), - 0x5b663814); - ASSERT_EQ( - Hash(reinterpret_cast(data3), sizeof(data3), 0xbc9f1d34), - 0x323c078f); - ASSERT_EQ( - Hash(reinterpret_cast(data4), sizeof(data4), 0xbc9f1d34), - 0xed21633a); - ASSERT_EQ( - Hash(reinterpret_cast(data5), sizeof(data5), 0x12345678), - 0xf333dabb); -} - -} // namespace leveldb - -int main(int argc, char** argv) { - return leveldb::test::RunAllTests(); -} diff --git a/src/leveldb/util/histogram.cc b/src/leveldb/util/histogram.cc deleted file mode 100644 index bb95f583ea..0000000000 --- a/src/leveldb/util/histogram.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include -#include "port/port.h" -#include "util/histogram.h" - -namespace leveldb { - -const double Histogram::kBucketLimit[kNumBuckets] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 45, - 50, 60, 70, 80, 90, 100, 120, 140, 160, 180, 200, 250, 300, 350, 400, 450, - 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000, - 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000, 10000, 12000, 14000, - 16000, 18000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 60000, - 70000, 80000, 90000, 100000, 120000, 140000, 160000, 180000, 200000, - 250000, 300000, 350000, 400000, 450000, 500000, 600000, 700000, 800000, - 900000, 1000000, 1200000, 1400000, 1600000, 1800000, 2000000, 2500000, - 3000000, 3500000, 4000000, 4500000, 5000000, 6000000, 7000000, 8000000, - 9000000, 10000000, 12000000, 14000000, 16000000, 18000000, 20000000, - 25000000, 30000000, 35000000, 40000000, 45000000, 50000000, 60000000, - 70000000, 80000000, 90000000, 100000000, 120000000, 140000000, 160000000, - 180000000, 200000000, 250000000, 300000000, 350000000, 400000000, - 450000000, 500000000, 600000000, 700000000, 800000000, 900000000, - 1000000000, 1200000000, 1400000000, 1600000000, 1800000000, 2000000000, - 2500000000.0, 3000000000.0, 3500000000.0, 4000000000.0, 4500000000.0, - 5000000000.0, 6000000000.0, 7000000000.0, 8000000000.0, 9000000000.0, - 1e200, -}; - -void Histogram::Clear() { - min_ = kBucketLimit[kNumBuckets-1]; - max_ = 0; - num_ = 0; - sum_ = 0; - sum_squares_ = 0; - for (int i = 0; i < kNumBuckets; i++) { - buckets_[i] = 0; - } -} - -void Histogram::Add(double value) { - // Linear search is fast enough for our usage in db_bench - int b = 0; - while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) { - b++; - } - buckets_[b] += 1.0; - if (min_ > value) min_ = value; - if (max_ < value) max_ = value; - num_++; - sum_ += value; - sum_squares_ += (value * value); -} - -void Histogram::Merge(const Histogram& other) { - if (other.min_ < min_) min_ = other.min_; - if (other.max_ > max_) max_ = other.max_; - num_ += other.num_; - sum_ += other.sum_; - sum_squares_ += other.sum_squares_; - for (int b = 0; b < kNumBuckets; b++) { - buckets_[b] += other.buckets_[b]; - } -} - -double Histogram::Median() const { - return Percentile(50.0); -} - -double Histogram::Percentile(double p) const { - double threshold = num_ * (p / 100.0); - double sum = 0; - for (int b = 0; b < kNumBuckets; b++) { - sum += buckets_[b]; - if (sum >= threshold) { - // Scale linearly within this bucket - double left_point = (b == 0) ? 0 : kBucketLimit[b-1]; - double right_point = kBucketLimit[b]; - double left_sum = sum - buckets_[b]; - double right_sum = sum; - double pos = (threshold - left_sum) / (right_sum - left_sum); - double r = left_point + (right_point - left_point) * pos; - if (r < min_) r = min_; - if (r > max_) r = max_; - return r; - } - } - return max_; -} - -double Histogram::Average() const { - if (num_ == 0.0) return 0; - return sum_ / num_; -} - -double Histogram::StandardDeviation() const { - if (num_ == 0.0) return 0; - double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); - return sqrt(variance); -} - -std::string Histogram::ToString() const { - std::string r; - char buf[200]; - snprintf(buf, sizeof(buf), - "Count: %.0f Average: %.4f StdDev: %.2f\n", - num_, Average(), StandardDeviation()); - r.append(buf); - snprintf(buf, sizeof(buf), - "Min: %.4f Median: %.4f Max: %.4f\n", - (num_ == 0.0 ? 0.0 : min_), Median(), max_); - r.append(buf); - r.append("------------------------------------------------------\n"); - const double mult = 100.0 / num_; - double sum = 0; - for (int b = 0; b < kNumBuckets; b++) { - if (buckets_[b] <= 0.0) continue; - sum += buckets_[b]; - snprintf(buf, sizeof(buf), - "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ", - ((b == 0) ? 0.0 : kBucketLimit[b-1]), // left - kBucketLimit[b], // right - buckets_[b], // count - mult * buckets_[b], // percentage - mult * sum); // cumulative percentage - r.append(buf); - - // Add hash marks based on percentage; 20 marks for 100%. - int marks = static_cast(20*(buckets_[b] / num_) + 0.5); - r.append(marks, '#'); - r.push_back('\n'); - } - return r; -} - -} // namespace leveldb diff --git a/src/leveldb/util/histogram.h b/src/leveldb/util/histogram.h deleted file mode 100644 index 1ef9f3c8ab..0000000000 --- a/src/leveldb/util/histogram.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ -#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ - -#include - -namespace leveldb { - -class Histogram { - public: - Histogram() { } - ~Histogram() { } - - void Clear(); - void Add(double value); - void Merge(const Histogram& other); - - std::string ToString() const; - - private: - double min_; - double max_; - double num_; - double sum_; - double sum_squares_; - - enum { kNumBuckets = 154 }; - static const double kBucketLimit[kNumBuckets]; - double buckets_[kNumBuckets]; - - double Median() const; - double Percentile(double p) const; - double Average() const; - double StandardDeviation() const; -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/src/leveldb/util/logging.cc b/src/leveldb/util/logging.cc deleted file mode 100644 index ca6b324403..0000000000 --- a/src/leveldb/util/logging.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/logging.h" - -#include -#include -#include -#include -#include "leveldb/env.h" -#include "leveldb/slice.h" - -namespace leveldb { - -void AppendNumberTo(std::string* str, uint64_t num) { - char buf[30]; - snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num); - str->append(buf); -} - -void AppendEscapedStringTo(std::string* str, const Slice& value) { - for (size_t i = 0; i < value.size(); i++) { - char c = value[i]; - if (c >= ' ' && c <= '~') { - str->push_back(c); - } else { - char buf[10]; - snprintf(buf, sizeof(buf), "\\x%02x", - static_cast(c) & 0xff); - str->append(buf); - } - } -} - -std::string NumberToString(uint64_t num) { - std::string r; - AppendNumberTo(&r, num); - return r; -} - -std::string EscapeString(const Slice& value) { - std::string r; - AppendEscapedStringTo(&r, value); - return r; -} - -bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { - uint64_t v = 0; - int digits = 0; - while (!in->empty()) { - char c = (*in)[0]; - if (c >= '0' && c <= '9') { - ++digits; - const int delta = (c - '0'); - static const uint64_t kMaxUint64 = ~static_cast(0); - if (v > kMaxUint64/10 || - (v == kMaxUint64/10 && delta > kMaxUint64%10)) { - // Overflow - return false; - } - v = (v * 10) + delta; - in->remove_prefix(1); - } else { - break; - } - } - *val = v; - return (digits > 0); -} - -} // namespace leveldb diff --git a/src/leveldb/util/logging.h b/src/leveldb/util/logging.h deleted file mode 100644 index 1b450d2480..0000000000 --- a/src/leveldb/util/logging.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Must not be included from any .h files to avoid polluting the namespace -// with macros. - -#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ -#define STORAGE_LEVELDB_UTIL_LOGGING_H_ - -#include -#include -#include -#include "port/port.h" - -namespace leveldb { - -class Slice; -class WritableFile; - -// Append a human-readable printout of "num" to *str -extern void AppendNumberTo(std::string* str, uint64_t num); - -// Append a human-readable printout of "value" to *str. -// Escapes any non-printable characters found in "value". -extern void AppendEscapedStringTo(std::string* str, const Slice& value); - -// Return a human-readable printout of "num" -extern std::string NumberToString(uint64_t num); - -// Return a human-readable version of "value". -// Escapes any non-printable characters found in "value". -extern std::string EscapeString(const Slice& value); - -// Parse a human-readable number from "*in" into *value. On success, -// advances "*in" past the consumed number and sets "*val" to the -// numeric value. Otherwise, returns false and leaves *in in an -// unspecified state. -extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val); - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/src/leveldb/util/mutexlock.h b/src/leveldb/util/mutexlock.h deleted file mode 100644 index 1ff5a9efa1..0000000000 --- a/src/leveldb/util/mutexlock.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ -#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ - -#include "port/port.h" -#include "port/thread_annotations.h" - -namespace leveldb { - -// Helper class that locks a mutex on construction and unlocks the mutex when -// the destructor of the MutexLock object is invoked. -// -// Typical usage: -// -// void MyClass::MyMethod() { -// MutexLock l(&mu_); // mu_ is an instance variable -// ... some complex code, possibly with multiple return paths ... -// } - -class SCOPED_LOCKABLE MutexLock { - public: - explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) - : mu_(mu) { - this->mu_->Lock(); - } - ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); } - - private: - port::Mutex *const mu_; - // No copying allowed - MutexLock(const MutexLock&); - void operator=(const MutexLock&); -}; - -} // namespace leveldb - - -#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/src/leveldb/util/options.cc b/src/leveldb/util/options.cc deleted file mode 100644 index 76af5b9302..0000000000 --- a/src/leveldb/util/options.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "leveldb/options.h" - -#include "leveldb/comparator.h" -#include "leveldb/env.h" - -namespace leveldb { - -Options::Options() - : comparator(BytewiseComparator()), - create_if_missing(false), - error_if_exists(false), - paranoid_checks(false), - env(Env::Default()), - info_log(NULL), - write_buffer_size(4<<20), - max_open_files(1000), - block_cache(NULL), - block_size(4096), - block_restart_interval(16), - compression(kSnappyCompression), - filter_policy(NULL) { -} - - -} // namespace leveldb diff --git a/src/leveldb/util/posix_logger.h b/src/leveldb/util/posix_logger.h deleted file mode 100644 index c063c2b7cb..0000000000 --- a/src/leveldb/util/posix_logger.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. -// -// Logger implementation that can be shared by all environments -// where enough Posix functionality is available. - -#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ -#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ - -#include -#include -#include -#include -#include "leveldb/env.h" - -namespace leveldb { - -class PosixLogger : public Logger { - private: - FILE* file_; - uint64_t (*gettid_)(); // Return the thread id for the current thread - public: - PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { } - virtual ~PosixLogger() { - fclose(file_); - } - virtual void Logv(const char* format, va_list ap) { - const uint64_t thread_id = (*gettid_)(); - - // We try twice: the first time with a fixed-size stack allocated buffer, - // and the second time with a much larger dynamically allocated buffer. - char buffer[500]; - for (int iter = 0; iter < 2; iter++) { - char* base; - int bufsize; - if (iter == 0) { - bufsize = sizeof(buffer); - base = buffer; - } else { - bufsize = 30000; - base = new char[bufsize]; - } - char* p = base; - char* limit = base + bufsize; - - struct timeval now_tv; - gettimeofday(&now_tv, NULL); - const time_t seconds = now_tv.tv_sec; - struct tm t; - localtime_r(&seconds, &t); - p += snprintf(p, limit - p, - "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ", - t.tm_year + 1900, - t.tm_mon + 1, - t.tm_mday, - t.tm_hour, - t.tm_min, - t.tm_sec, - static_cast(now_tv.tv_usec), - static_cast(thread_id)); - - // Print the message - if (p < limit) { - va_list backup_ap; - va_copy(backup_ap, ap); - p += vsnprintf(p, limit - p, format, backup_ap); - va_end(backup_ap); - } - - // Truncate to available space if necessary - if (p >= limit) { - if (iter == 0) { - continue; // Try again with larger buffer - } else { - p = limit - 1; - } - } - - // Add newline if necessary - if (p == base || p[-1] != '\n') { - *p++ = '\n'; - } - - assert(p <= limit); - fwrite(base, 1, p - base, file_); - fflush(file_); - if (base != buffer) { - delete[] base; - } - break; - } - } -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/src/leveldb/util/random.h b/src/leveldb/util/random.h deleted file mode 100644 index ddd51b1c7b..0000000000 --- a/src/leveldb/util/random.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ -#define STORAGE_LEVELDB_UTIL_RANDOM_H_ - -#include - -namespace leveldb { - -// A very simple random number generator. Not especially good at -// generating truly random bits, but good enough for our needs in this -// package. -class Random { - private: - uint32_t seed_; - public: - explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { - // Avoid bad seeds. - if (seed_ == 0 || seed_ == 2147483647L) { - seed_ = 1; - } - } - uint32_t Next() { - static const uint32_t M = 2147483647L; // 2^31-1 - static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 - // We are computing - // seed_ = (seed_ * A) % M, where M = 2^31-1 - // - // seed_ must not be zero or M, or else all subsequent computed values - // will be zero or M respectively. For all other values, seed_ will end - // up cycling through every number in [1,M-1] - uint64_t product = seed_ * A; - - // Compute (product % M) using the fact that ((x << 31) % M) == x. - seed_ = static_cast((product >> 31) + (product & M)); - // The first reduction may overflow by 1 bit, so we may need to - // repeat. mod == M is not possible; using > allows the faster - // sign-bit-based test. - if (seed_ > M) { - seed_ -= M; - } - return seed_; - } - // Returns a uniformly distributed value in the range [0..n-1] - // REQUIRES: n > 0 - uint32_t Uniform(int n) { return Next() % n; } - - // Randomly returns true ~"1/n" of the time, and false otherwise. - // REQUIRES: n > 0 - bool OneIn(int n) { return (Next() % n) == 0; } - - // Skewed: pick "base" uniformly from range [0,max_log] and then - // return "base" random bits. The effect is to pick a number in the - // range [0,2^max_log-1] with exponential bias towards smaller numbers. - uint32_t Skewed(int max_log) { - return Uniform(1 << Uniform(max_log + 1)); - } -}; - -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/src/leveldb/util/status.cc b/src/leveldb/util/status.cc deleted file mode 100644 index a44f35b314..0000000000 --- a/src/leveldb/util/status.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include -#include "port/port.h" -#include "leveldb/status.h" - -namespace leveldb { - -const char* Status::CopyState(const char* state) { - uint32_t size; - memcpy(&size, state, sizeof(size)); - char* result = new char[size + 5]; - memcpy(result, state, size + 5); - return result; -} - -Status::Status(Code code, const Slice& msg, const Slice& msg2) { - assert(code != kOk); - const uint32_t len1 = msg.size(); - const uint32_t len2 = msg2.size(); - const uint32_t size = len1 + (len2 ? (2 + len2) : 0); - char* result = new char[size + 5]; - memcpy(result, &size, sizeof(size)); - result[4] = static_cast(code); - memcpy(result + 5, msg.data(), len1); - if (len2) { - result[5 + len1] = ':'; - result[6 + len1] = ' '; - memcpy(result + 7 + len1, msg2.data(), len2); - } - state_ = result; -} - -std::string Status::ToString() const { - if (state_ == NULL) { - return "OK"; - } else { - char tmp[30]; - const char* type; - switch (code()) { - case kOk: - type = "OK"; - break; - case kNotFound: - type = "NotFound: "; - break; - case kCorruption: - type = "Corruption: "; - break; - case kNotSupported: - type = "Not implemented: "; - break; - case kInvalidArgument: - type = "Invalid argument: "; - break; - case kIOError: - type = "IO error: "; - break; - default: - snprintf(tmp, sizeof(tmp), "Unknown code(%d): ", - static_cast(code())); - type = tmp; - break; - } - std::string result(type); - uint32_t length; - memcpy(&length, state_, sizeof(length)); - result.append(state_ + 5, length); - return result; - } -} - -} // namespace leveldb diff --git a/src/leveldb/util/testharness.cc b/src/leveldb/util/testharness.cc deleted file mode 100644 index 402fab34d7..0000000000 --- a/src/leveldb/util/testharness.cc +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/testharness.h" - -#include -#include -#include -#include - -namespace leveldb { -namespace test { - -namespace { -struct Test { - const char* base; - const char* name; - void (*func)(); -}; -std::vector* tests; -} - -bool RegisterTest(const char* base, const char* name, void (*func)()) { - if (tests == NULL) { - tests = new std::vector; - } - Test t; - t.base = base; - t.name = name; - t.func = func; - tests->push_back(t); - return true; -} - -int RunAllTests() { - const char* matcher = getenv("LEVELDB_TESTS"); - - int num = 0; - if (tests != NULL) { - for (size_t i = 0; i < tests->size(); i++) { - const Test& t = (*tests)[i]; - if (matcher != NULL) { - std::string name = t.base; - name.push_back('.'); - name.append(t.name); - if (strstr(name.c_str(), matcher) == NULL) { - continue; - } - } - fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); - (*t.func)(); - ++num; - } - } - fprintf(stderr, "==== PASSED %d tests\n", num); - return 0; -} - -std::string TmpDir() { - std::string dir; - Status s = Env::Default()->GetTestDirectory(&dir); - ASSERT_TRUE(s.ok()) << s.ToString(); - return dir; -} - -int RandomSeed() { - const char* env = getenv("TEST_RANDOM_SEED"); - int result = (env != NULL ? atoi(env) : 301); - if (result <= 0) { - result = 301; - } - return result; -} - -} // namespace test -} // namespace leveldb diff --git a/src/leveldb/util/testharness.h b/src/leveldb/util/testharness.h deleted file mode 100644 index da4fe68bb4..0000000000 --- a/src/leveldb/util/testharness.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ -#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ - -#include -#include -#include -#include "leveldb/env.h" -#include "leveldb/slice.h" -#include "util/random.h" - -namespace leveldb { -namespace test { - -// Run some of the tests registered by the TEST() macro. If the -// environment variable "LEVELDB_TESTS" is not set, runs all tests. -// Otherwise, runs only the tests whose name contains the value of -// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: -// TEST(Foo, Hello) { ... } -// TEST(Foo, World) { ... } -// LEVELDB_TESTS=Hello will run the first test -// LEVELDB_TESTS=o will run both tests -// LEVELDB_TESTS=Junk will run no tests -// -// Returns 0 if all tests pass. -// Dies or returns a non-zero value if some test fails. -extern int RunAllTests(); - -// Return the directory to use for temporary storage. -extern std::string TmpDir(); - -// Return a randomization seed for this run. Typically returns the -// same number on repeated invocations of this binary, but automated -// runs may be able to vary the seed. -extern int RandomSeed(); - -// An instance of Tester is allocated to hold temporary state during -// the execution of an assertion. -class Tester { - private: - bool ok_; - const char* fname_; - int line_; - std::stringstream ss_; - - public: - Tester(const char* f, int l) - : ok_(true), fname_(f), line_(l) { - } - - ~Tester() { - if (!ok_) { - fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); - exit(1); - } - } - - Tester& Is(bool b, const char* msg) { - if (!b) { - ss_ << " Assertion failure " << msg; - ok_ = false; - } - return *this; - } - - Tester& IsOk(const Status& s) { - if (!s.ok()) { - ss_ << " " << s.ToString(); - ok_ = false; - } - return *this; - } - -#define BINARY_OP(name,op) \ - template \ - Tester& name(const X& x, const Y& y) { \ - if (! (x op y)) { \ - ss_ << " failed: " << x << (" " #op " ") << y; \ - ok_ = false; \ - } \ - return *this; \ - } - - BINARY_OP(IsEq, ==) - BINARY_OP(IsNe, !=) - BINARY_OP(IsGe, >=) - BINARY_OP(IsGt, >) - BINARY_OP(IsLe, <=) - BINARY_OP(IsLt, <) -#undef BINARY_OP - - // Attach the specified value to the error message if an error has occurred - template - Tester& operator<<(const V& value) { - if (!ok_) { - ss_ << " " << value; - } - return *this; - } -}; - -#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) -#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) -#define ASSERT_EQ(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a),(b)) -#define ASSERT_NE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a),(b)) -#define ASSERT_GE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a),(b)) -#define ASSERT_GT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a),(b)) -#define ASSERT_LE(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a),(b)) -#define ASSERT_LT(a,b) ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a),(b)) - -#define TCONCAT(a,b) TCONCAT1(a,b) -#define TCONCAT1(a,b) a##b - -#define TEST(base,name) \ -class TCONCAT(_Test_,name) : public base { \ - public: \ - void _Run(); \ - static void _RunIt() { \ - TCONCAT(_Test_,name) t; \ - t._Run(); \ - } \ -}; \ -bool TCONCAT(_Test_ignored_,name) = \ - ::leveldb::test::RegisterTest(#base, #name, &TCONCAT(_Test_,name)::_RunIt); \ -void TCONCAT(_Test_,name)::_Run() - -// Register the specified test. Typically not used directly, but -// invoked via the macro expansion of TEST. -extern bool RegisterTest(const char* base, const char* name, void (*func)()); - - -} // namespace test -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/src/leveldb/util/testutil.cc b/src/leveldb/util/testutil.cc deleted file mode 100644 index bee56bf75f..0000000000 --- a/src/leveldb/util/testutil.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "util/testutil.h" - -#include "util/random.h" - -namespace leveldb { -namespace test { - -Slice RandomString(Random* rnd, int len, std::string* dst) { - dst->resize(len); - for (int i = 0; i < len; i++) { - (*dst)[i] = static_cast(' ' + rnd->Uniform(95)); // ' ' .. '~' - } - return Slice(*dst); -} - -std::string RandomKey(Random* rnd, int len) { - // Make sure to generate a wide variety of characters so we - // test the boundary conditions for short-key optimizations. - static const char kTestChars[] = { - '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff' - }; - std::string result; - for (int i = 0; i < len; i++) { - result += kTestChars[rnd->Uniform(sizeof(kTestChars))]; - } - return result; -} - - -extern Slice CompressibleString(Random* rnd, double compressed_fraction, - size_t len, std::string* dst) { - int raw = static_cast(len * compressed_fraction); - if (raw < 1) raw = 1; - std::string raw_data; - RandomString(rnd, raw, &raw_data); - - // Duplicate the random data until we have filled "len" bytes - dst->clear(); - while (dst->size() < len) { - dst->append(raw_data); - } - dst->resize(len); - return Slice(*dst); -} - -} // namespace test -} // namespace leveldb diff --git a/src/leveldb/util/testutil.h b/src/leveldb/util/testutil.h deleted file mode 100644 index adad3fc1ea..0000000000 --- a/src/leveldb/util/testutil.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ -#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ - -#include "leveldb/env.h" -#include "leveldb/slice.h" -#include "util/random.h" - -namespace leveldb { -namespace test { - -// Store in *dst a random string of length "len" and return a Slice that -// references the generated data. -extern Slice RandomString(Random* rnd, int len, std::string* dst); - -// Return a random key with the specified length that may contain interesting -// characters (e.g. \x00, \xff, etc.). -extern std::string RandomKey(Random* rnd, int len); - -// Store in *dst a string of length "len" that will compress to -// "N*compressed_fraction" bytes and return a Slice that references -// the generated data. -extern Slice CompressibleString(Random* rnd, double compressed_fraction, - size_t len, std::string* dst); - -// A wrapper that allows injection of errors. -class ErrorEnv : public EnvWrapper { - public: - bool writable_file_error_; - int num_writable_file_errors_; - - ErrorEnv() : EnvWrapper(Env::Default()), - writable_file_error_(false), - num_writable_file_errors_(0) { } - - virtual Status NewWritableFile(const std::string& fname, - WritableFile** result) { - if (writable_file_error_) { - ++num_writable_file_errors_; - *result = NULL; - return Status::IOError(fname, "fake error"); - } - return target()->NewWritableFile(fname, result); - } -}; - -} // namespace test -} // namespace leveldb - -#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/src/logging.h b/src/logging.h new file mode 100644 index 0000000000..c65c781cf1 --- /dev/null +++ b/src/logging.h @@ -0,0 +1,124 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_LOGGING_H +#define ALIAS_LOGGING_H + +#include +#include +#include +#include +#include +#include +#include + +namespace BCLog { + +enum LogFlags : uint32_t { + NONE = 0, + NET = (1 << 0), + TOR = (1 << 1), + MEMPOOL = (1 << 2), + HTTP = (1 << 3), + BENCH = (1 << 4), + ZMQ = (1 << 5), + WALLETDB = (1 << 6), + RPC = (1 << 7), + ESTIMATEFEE = (1 << 8), + ADDRMAN = (1 << 9), + SELECTCOINS = (1 << 10), + REINDEX = (1 << 11), + CMPCTBLOCK = (1 << 12), + RAND = (1 << 13), + PRUNE = (1 << 14), + PROXY = (1 << 15), + MEMPOOLREJ = (1 << 16), + LIBEVENT = (1 << 17), + COINDB = (1 << 18), + QT = (1 << 19), + LEVELDB = (1 << 20), + STAKING = (1 << 21), + SMSG = (1 << 22), + ANON = (1 << 23), + HDWALLET = (1 << 24), + ALL = ~(uint32_t)0, +}; + +enum class Level { + Trace, + Debug, + Info, + Warning, + Error, +}; + +class Logger { +public: + bool m_print_to_console{false}; + bool m_print_to_file{true}; + bool m_log_timestamps{true}; + bool m_log_time_micros{false}; + bool m_log_threadnames{false}; + bool m_log_sourcelocations{false}; + std::atomic m_reopen_file{false}; + std::atomic m_categories{0}; + Level m_log_level{Level::Debug}; + + void EnableCategory(LogFlags category); + void DisableCategory(LogFlags category); + bool WillLogCategory(LogFlags category) const; + bool WillLogCategoryLevel(LogFlags category, Level level) const; + + std::string LogCategoriesString() const; + bool SetLogLevel(const std::string& level); + + bool StartLogging(); + void DisconnectTestLogger(); + + void LogPrintStr(const std::string& str, const std::string& log_prefix = "", const std::string& file = "", int line = 0); + + bool Enabled() const { + return m_print_to_console || m_print_to_file; + } + + std::list> PushBackCallback(std::function callback); + void DeleteCallback(std::list>::iterator it); + +private: + mutable std::mutex m_cs; + FILE* m_file{nullptr}; + std::list> m_print_callbacks; + std::string m_buffer; + bool m_buffering{true}; + + std::string GetTimestamp() const; + void Flush(); +}; + +} // namespace BCLog + +BCLog::Logger& LogInstance(); + +static inline bool LogAcceptCategory(BCLog::LogFlags flag, BCLog::Level level) { + return LogInstance().WillLogCategoryLevel(flag, level); +} + +static inline bool LogAcceptCategory(BCLog::LogFlags flag) { + return LogInstance().WillLogCategory(flag); +} + +bool GetLogCategory(BCLog::LogFlags& flag, const std::string& category); +std::string GetLogCategoryString(BCLog::LogFlags flag); + +template +static inline void LogPrint(BCLog::LogFlags category, const char* fmt, const Args&... args); + +template +static inline void LogPrintLevel(BCLog::LogFlags category, BCLog::Level level, const char* fmt, const Args&... args); + +#define LogPrintf(...) LogPrint(BCLog::NONE, __VA_ARGS__) +#define LogPrintfLevel(level, ...) LogPrintLevel(BCLog::NONE, level, __VA_ARGS__) + +#endif // ALIAS_LOGGING_H diff --git a/src/lz4/CMakeLists.txt b/src/lz4/CMakeLists.txt new file mode 100644 index 0000000000..ef8a83385c --- /dev/null +++ b/src/lz4/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(aliaswallet_lib + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/lz4.h + + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/lz4.c + ) diff --git a/src/main.cpp b/src/main.cpp index fdbdf99432..755642ec85 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include -#include -#include +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "alert.h" #include "checkpoints.h" @@ -13,12 +12,14 @@ #include "txdb.h" #include "net.h" #include "init.h" -#include "ui_interface.h" +#include "interface.h" #include "kernel.h" -#include "smessage.h" +#include "validation_connectblock_alias.h" +#include "validation_alias.h" +#include "util/fs.h" - -using namespace std; +#include +#include // // Global state @@ -31,21 +32,21 @@ CCriticalSection cs_main; CTxMemPool mempool; +CChain chainActive; std::map mapBlockIndex; std::map mapBlockThinIndex; std::set > setStakeSeen; -unsigned int nStakeMinAge = 8 * 60 * 60; // 8 hours +unsigned int nStakeMinAge = 8 * 60 * 60; // 8 hour unsigned int nModifierInterval = 10 * 60; // time to elapse before new modifier is computed -int nCoinbaseMaturity = 120; -int nStakeMinConfirmations = 450; -CBlockIndex* pindexGenesisBlock = NULL; +int nCoinbaseMaturity = 100; // 100 blocks depth for newly generated PoW coins +CBlockIndex* pindexGenesisBlock = nullptr; -CBlockThinIndex* pindexGenesisBlockThin = NULL; -CBlockThinIndex* pindexRear = NULL; +CBlockThinIndex* pindexGenesisBlockThin = nullptr; +CBlockThinIndex* pindexRear = nullptr; int nBestHeight = -1; int nHeightFilteredNeeded = -1; @@ -54,7 +55,7 @@ uint256 nBestChainTrust = 0; uint256 nBestInvalidTrust = 0; uint256 hashBestChain = 0; -CBlockIndex* pindexBest = NULL; +CBlockIndex* pindexBest = nullptr; CBlockThinIndex* pindexBestHeader; int64_t nTimeBestReceived = 0; @@ -64,7 +65,10 @@ CMedianFilter cPeerBlockCounts(5, 0); // Amount of blocks that other nodes std::map mapOrphanBlockThins; +bool fStaleAnonCache = true; +int nMaxAnonBlockCache = 1000; std::map mapAnonOutputStats; // display only, not 100% accurate, height could become inaccurate due to undos +std::map> mapAnonBlockStats; std::multimap mapOrphanBlockThinsByPrev; @@ -84,10 +88,10 @@ std::vector vIncomingMerkleBlocks; // blocks with txns att // Constant stuff for coinbase transactions we create: CScript COINBASE_FLAGS; -const string strMessageMagic = "ShadowCoin Signed Message:\n"; +const string strMessageMagic = "Alias Signed Message:\n"; // Settings -int64_t nTransactionFee = MIN_TX_FEE; +int64_t nTransactionFee = nMinTxFee; int64_t nReserveBalance = 0; int64_t nMinimumInputValue = 0; @@ -118,25 +122,27 @@ void UnregisterWallet(CWallet* pwalletIn) // check whether the passed transaction is from us bool static IsFromMe(CTransaction& tx) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { if (pwallet->IsFromMe(tx)) return true; + } return false; } // get the wallet transaction with the given hash (if it exists) bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - if (pwallet->GetTransaction(hashTx,wtx)) + for (CWallet* pwallet : setpwalletRegistered) { + if (pwallet->GetTransaction(hashTx, wtx)) return true; + } return false; } // erases transaction with the given hash from all wallets //void static EraseFromWallets(uint256 hash) //{ -// BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) +// for (CWallet* pwallet : setpwalletRegistered) // pwallet->EraseFromWallet(hash); //} @@ -146,89 +152,87 @@ void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate, if (!fConnect) { // ppcoin: wallets need to refund inputs when disconnecting coinstake - if (tx.IsCoinStake()) + if (tx.nVersion == ANON_TXN_VERSION) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { + pwallet->UndoAnonTransaction(tx, nullptr, !pwallet->IsFromMe(tx)); + } + } + else if (tx.IsCoinStake()) + { + for (CWallet* pwallet : setpwalletRegistered) { if (pwallet->IsFromMe(tx)) pwallet->DisableTransaction(tx); }; - }; - - if (tx.nVersion == ANON_TXN_VERSION) - { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - pwallet->UndoAnonTransaction(tx); - }; + } return; }; uint256 hash = tx.GetHash(); - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->AddToWalletIfInvolvingMe(tx, hash, pblock, fUpdate); + } } void SyncWithWalletsThin(const CTransaction& tx, const uint256& blockhash, bool fUpdate, bool fConnect) { - if (!fConnect) - { - // ppcoin: wallets need to refund inputs when disconnecting coinstake - if (tx.IsCoinStake()) - { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - { + if (!fConnect) { + if (tx.IsCoinStake()) { + for (CWallet* pwallet : setpwalletRegistered) { if (pwallet->IsFromMe(tx)) pwallet->DisableTransaction(tx); - }; - }; + } + } return; - }; + } uint256 hash = tx.GetHash(); - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->AddToWalletIfInvolvingMe(tx, hash, &blockhash, fUpdate); + } } -// notify wallets about a new best chain void static SetBestChain(const CBlockLocator& loc) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->SetBestChain(loc); + } } -// notify wallets about a new best chain void static SetBestThinChain(const CBlockThinLocator& loc) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->SetBestThinChain(loc); + } } -// notify wallets about an updated transaction void static UpdatedTransaction(const uint256& hashTx) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->UpdatedTransaction(hashTx); + } } -// dump all wallets void static PrintWallets(const CBlock& block) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->PrintWallet(block); + } } -// notify wallets about an incoming inventory (for request counts) void static Inventory(const uint256& hash) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->Inventory(hash); + } } -// ask wallets to resend their transactions void ResendWalletTransactions(bool fForce) { - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) { pwallet->ResendWalletTransactions(fForce); + } } bool SetHeightFilteredNeeded() @@ -339,7 +343,7 @@ bool AddDataToMerkleFilters(const std::vector& vData) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) pnode->PushMessage("filteradd", vData); } @@ -380,8 +384,8 @@ bool GetCoinAgeThin(CTransaction txCoinStake, uint64_t& nCoinAge, std::vector::iterator it = vWtxPrev.begin(); it != vWtxPrev.end(); ++it) { @@ -480,7 +484,7 @@ bool AddOrphanTx(const CTransaction& tx) }; mapOrphanTransactions[hash] = tx; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash); LogPrintf("stored orphan tx %s (mapsz %u)\n", hash.ToString().substr(0,10).c_str(), @@ -494,7 +498,7 @@ void static EraseOrphanTx(uint256 hash) return; const CTransaction& tx = mapOrphanTransactions[hash]; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash); if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty()) @@ -560,15 +564,15 @@ bool CTransaction::IsStandard() const && nVersion != ANON_TXN_VERSION) return false; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) { if (txin.IsAnonInput()) { - int nRingSize = txin.ExtractRingSize(); + uint32_t nRingSize = (uint32_t)txin.ExtractRingSize(); + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(nTime); if (nVersion != ANON_TXN_VERSION - || nRingSize < 1 - || nRingSize > (Params().IsProtocolV3(pindexBest->nHeight) ? (int)MAX_RING_SIZE : (int)MAX_RING_SIZE_OLD) + || nRingSize < nMinRingSize || nRingSize > nMaxRingSize || txin.scriptSig.size() > sizeof(COutPoint) + 2 + (33 + 32 + 32) * nRingSize) { LogPrintf("IsStandard() anon txin failed.\n"); @@ -592,7 +596,7 @@ bool CTransaction::IsStandard() const unsigned int nTxnOut = 0; txnouttype whichType; - BOOST_FOREACH(const CTxOut& txout, vout) + for (const CTxOut& txout : vout) { if (nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) @@ -730,12 +734,12 @@ bool CTransaction::HasStealthOutput() const unsigned int CTransaction::GetLegacySigOpCount() const { unsigned int nSigOps = 0; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) { nSigOps += txin.scriptSig.GetSigOpCount(false); }; - BOOST_FOREACH(const CTxOut& txout, vout) + for (const CTxOut& txout : vout) { nSigOps += txout.scriptPubKey.GetSigOpCount(false); }; @@ -748,7 +752,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) AssertLockHeld(cs_main); CBlock blockTmp; - if (pblock == NULL) + if (pblock == nullptr) { // Load the block this tx is in CTxIndex txindex; @@ -820,7 +824,7 @@ bool CTransaction::CheckTransaction() const // Check for duplicate inputs set vInOutPoints; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) { if (nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -846,15 +850,18 @@ bool CTransaction::CheckTransaction() const if (nVersion == ANON_TXN_VERSION) { - // -- Check for duplicate anon outputs + // -- Check for duplicate anon outputs and max anon output size // NOTE: is this necessary, duplicate coins would not be spendable anyway? set vAnonOutPubkeys; CPubKey pkTest; - BOOST_FOREACH(const CTxOut& txout, vout) + for (const CTxOut& txout : vout) { if (!txout.IsAnonOutput()) continue; + if (Params().IsForkV3(nTime) && txout.nValue > nMaxAnonOutput) + return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue of anon output higher than nMaxAnonOutput")); + const CScript &s = txout.scriptPubKey; pkTest = CPubKey(&s[2+1], 33); if (vAnonOutPubkeys.count(pkTest)) @@ -870,7 +877,7 @@ bool CTransaction::CheckTransaction() const return DoS(100, error("CTransaction::CheckTransaction() : coinbase script size is invalid")); } else { - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) if (txin.prevout.IsNull()) return DoS(10, error("CTransaction::CheckTransaction() : prevout is null")); }; @@ -881,18 +888,12 @@ bool CTransaction::CheckTransaction() const int64_t CTransaction::GetMinFee(unsigned int nBlockSize, enum GetMinFee_mode mode, unsigned int nBytes) const { - // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE for standard txns, and MIN_TX_FEE_ANON for anon txns - - // -- force GMF_ANON if anon txn - if (nVersion == ANON_TXN_VERSION) - mode = GMF_ANON; - + // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE for standard txns int64_t nBaseFee; switch (mode) { - case GMF_RELAY: nBaseFee = MIN_RELAY_TX_FEE; break; - case GMF_ANON: nBaseFee = MIN_TX_FEE_ANON; break; - default: nBaseFee = MIN_TX_FEE; break; + case GMF_RELAY: nBaseFee = nMinRelayTxFee; break; + default: nBaseFee = nMinTxFee; break; }; unsigned int nNewBlockSize = nBlockSize + nBytes; @@ -901,13 +902,13 @@ int64_t CTransaction::GetMinFee(unsigned int nBlockSize, enum GetMinFee_mode mod // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 if (nMinFee < nBaseFee) { - BOOST_FOREACH(const CTxOut& txout, vout) + for (const CTxOut& txout : vout) if (txout.nValue < CENT) nMinFee = nBaseFee; }; // Raise the price as the block approaches full - if (mode != GMF_ANON && nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) + if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) { if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) return MAX_MONEY; @@ -1002,8 +1003,6 @@ bool AcceptToMemoryPool(CTxMemPool &pool, CTransaction &tx, CTxDB &txdb, bool *p }; nFees += nSumAnon; - - feeMode = GMF_ANON; }; @@ -1027,7 +1026,7 @@ bool AcceptToMemoryPool(CTxMemPool &pool, CTransaction &tx, CTxDB &txdb, bool *p // Continuously rate-limit free transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (nFees < MIN_RELAY_TX_FEE) + if (nFees < nMinRelayTxFee) { static CCriticalSection csFreeLimiter; static double dFreeCount; @@ -1071,7 +1070,7 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb) { { // Add previous supporting transactions first - BOOST_FOREACH(CMerkleTx& tx, vtxPrev) + for (CMerkleTx& tx : vtxPrev) { if (!(tx.IsCoinBase() || tx.IsCoinStake())) { @@ -1124,12 +1123,12 @@ int CTxIndex::GetDepthInMainChainFromIndex() const } // Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock -bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool includemempool) { { - LOCK(cs_main); - if (mempool.lookup(hash, tx)) + if(includemempool && mempool.lookup(hash, tx)) return true; + CTxDB txdb("r"); CTxIndex txindex; if (tx.ReadFromDisk(txdb, COutPoint(hash, 0), txindex)) @@ -1143,6 +1142,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock) return false; } + bool GetTransactionBlockHash(const uint256 &hash, uint256 &hashBlock) { { @@ -1207,7 +1207,7 @@ bool TxnHashInSystem(CTxDB* ptxdb, uint256& txnHash) // CBlockThin and CBlockThinIndex // -static CBlockThinIndex* pblockHeaderIndexFBBHLast = NULL; +static CBlockThinIndex* pblockHeaderIndexFBBHLast = nullptr; CBlockThinIndex* FindBlockThinByHeight(int nHeight) { CBlockThinIndex *pblockindex; @@ -1217,7 +1217,7 @@ CBlockThinIndex* FindBlockThinByHeight(int nHeight) pblockindex = pindexBestHeader; if (!pblockindex) - return NULL; + return nullptr; if (pblockHeaderIndexFBBHLast && abs(nHeight - pblockindex->nHeight) > abs(nHeight - pblockHeaderIndexFBBHLast->nHeight)) pblockindex = pblockHeaderIndexFBBHLast; @@ -1233,10 +1233,10 @@ CBlockThinIndex* FindBlockThinByHeight(int nHeight) pblockindex = pblockindex->pnext; if (!pblockindex) - return NULL; + return nullptr; if (pblockindex->nHeight != nHeight) - return NULL; + return nullptr; pblockHeaderIndexFBBHLast = pblockindex; return pblockindex; @@ -1248,7 +1248,7 @@ void static InvalidHeaderChainFound(CBlockThinIndex* pindexNew) { nBestInvalidTrust = pindexNew->nChainTrust; //CTxDB().WriteBestInvalidTrust(CBigNum(nBestInvalidTrust)); - uiInterface.NotifyBlocksChanged(); + // uiInterface.NotifyBlocksChanged(); }; uint256 nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust; @@ -1301,7 +1301,7 @@ bool static ReorganizeHeaders(CTxDB& txdb, CBlockThinIndex* pindexNew) // Disconnect shorter branch list vResurrect; - BOOST_FOREACH(CBlockThinIndex* pindex, vDisconnect) + for (CBlockThinIndex* pindex : vDisconnect) { CBlockThin block = pindex->GetBlockThin(); @@ -1349,7 +1349,7 @@ bool static ReorganizeHeaders(CTxDB& txdb, CBlockThinIndex* pindexNew) }; // Queue memory transactions to delete - //BOOST_FOREACH(const CTransaction& tx, block.vtx) + //for (const CTransaction& tx : block.vtx) // vDelete.push_back(tx); }; @@ -1361,21 +1361,21 @@ bool static ReorganizeHeaders(CTxDB& txdb, CBlockThinIndex* pindexNew) return error("ReorganizeHeaders() : TxnCommit failed"); // Disconnect shorter branch - BOOST_FOREACH(CBlockThinIndex* pindex, vDisconnect) + for (CBlockThinIndex* pindex : vDisconnect) if (pindex->pprev) - pindex->pprev->pnext = NULL; + pindex->pprev->pnext = nullptr; // Connect longer branch - BOOST_FOREACH(CBlockThinIndex* pindex, vConnect) + for (CBlockThinIndex* pindex : vConnect) if (pindex->pprev) pindex->pprev->pnext = pindex; // Resurrect memory transactions that were in the disconnected branch - BOOST_FOREACH(CTransaction& tx, vResurrect) + for (CTransaction& tx : vResurrect) AcceptToMemoryPool(mempool, tx, txdb); // Delete redundant memory transactions that are in the connected branch - BOOST_FOREACH(CTransaction& tx, vDelete) + for (CTransaction& tx : vDelete) { mempool.remove(tx); mempool.removeConflicts(tx); @@ -1520,7 +1520,7 @@ bool CBlockThin::AddToBlockThinIndex(unsigned int nFile, unsigned int nBlockPos, const uint256* pRemHash = pindexRear->phashBlock; pindexRear = pindexRear->pnext; - pindexRear->pprev = NULL; + pindexRear->pprev = nullptr; std::map::iterator mi = mapBlockThinIndex.find(*pRemHash); @@ -1531,8 +1531,8 @@ bool CBlockThin::AddToBlockThinIndex(unsigned int nFile, unsigned int nBlockPos, }; }; - - uiInterface.NotifyBlocksChanged(); + BlockChangedEvent blockChangedEvent = {nBestHeight, GetNumBlocksOfPeers(), IsInitialBlockDownload(), pindexBestHeader->GetBlockTime()}; + uiInterface.NotifyBlocksChanged(blockChangedEvent); return true; } @@ -1583,7 +1583,7 @@ bool CBlockThin::DisconnectBlockThin(CTxDB& txdb, CBlockThinIndex* pindex) continue; // -- mark input outputs as unspent - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { std::map::iterator miIn = pwalletMain->mapWallet.find(txin.prevout.hash); if (miIn == pwalletMain->mapWallet.end()) @@ -1631,7 +1631,7 @@ bool CBlockThin::ConnectBlockThin(CTxDB& txdb, CBlockThinIndex* pindex, bool fJu continue; // -- mark input outputs as spent - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { std::map::iterator miIn = pwalletMain->mapWallet.find(txin.prevout.hash); if (miIn == pwalletMain->mapWallet.end()) @@ -1657,7 +1657,7 @@ bool CBlockThin::SetBestThinChain(CTxDB& txdb, CBlockThinIndex* pindexNew) if (!txdb.TxnBegin()) return error("SetBestThinChain() : TxnBegin failed"); - if (pindexGenesisBlockThin == NULL && hash == Params().HashGenesisBlock()) + if (pindexGenesisBlockThin == nullptr && hash == Params().HashGenesisBlock()) { txdb.WriteHashBestHeaderChain(hash); if (!txdb.TxnCommit()) @@ -1724,7 +1724,7 @@ bool CBlockThin::SetBestThinChain(CTxDB& txdb, CBlockThinIndex* pindexNew) // New best block hashBestChain = hash; pindexBestHeader = pindexNew; - //pblockindexFBBHLast = NULL; + //pblockindexFBBHLast = nullptr; nBestHeight = pindexBestHeader->nHeight; nBestChainTrust = pindexBestHeader->nChainTrust; nTimeBestReceived = GetTime(); @@ -1776,7 +1776,7 @@ CBlockIndex* FindBlockByHeight(int nHeight) pblockindex = pblockindex->pnext; if (pblockindex->nHeight != nHeight) - return NULL; + return nullptr; pblockindexFBBHLast = pblockindex; return pblockindex; @@ -1851,6 +1851,7 @@ const COrphanBlock* AddOrphanBlock(const CBlock* pblock) orphan->hashBlock = pblock->GetHash(); orphan->hashPrev = pblock->hashPrevBlock; orphan->stake = pblock->GetProofOfStake(); + orphan->nTime = pblock->nTime; nOrphanBlocksSize += orphan->vchBlock.size(); mapOrphanBlocks.insert(make_pair(pblock->GetHash(), orphan)); mapOrphanBlocksByPrev.insert(make_pair(orphan->hashPrev, orphan)); @@ -1861,9 +1862,39 @@ const COrphanBlock* AddOrphanBlock(const CBlock* pblock) return orphan; } -// Remove a random orphan block (which does not have any dependent orphans). +// Remove a random orphan block (which does not have any dependent orphans). Remove all due checkpoint obsolete orphans. void static PruneOrphanBlocks() { + const CBlockIndex* pcheckpoint = Checkpoints::AutoSelectSyncCheckpoint(); + for (auto it = mapOrphanBlocks.begin(); it != mapOrphanBlocks.end(); ++it) + { + // Block is obsolete due to checkpoint, delete all predecessors. + if (it->second->nTime < pcheckpoint->nTime) + { + map::iterator it2 = mapOrphanBlocks.find(it->second->hashPrev); + while (it2 != mapOrphanBlocks.end()) + { + if (fDebug) + LogPrintf("PruneOrphanBlocks: Delete obsolete orphan %s with time %d (checkpoint time %d)\n", it2->second->hashBlock.GetHex(), it2->second->nTime, pcheckpoint->nTime); + + uint256 hashPrev = it2->second->hashPrev; + for(auto itPrev = mapOrphanBlocksByPrev.find(hashPrev); itPrev != mapOrphanBlocksByPrev.end(); ++itPrev) + { + if(itPrev->second == it2->second) + { + itPrev = mapOrphanBlocksByPrev.erase(itPrev); + break; + } + } + setStakeSeenOrphan.erase(it2->second->stake); + nOrphanBlocksSize -= it2->second->vchBlock.size(); + delete it2->second; + mapOrphanBlocks.erase(it2); + it2 = mapOrphanBlocks.find(hashPrev); + } + } + } + size_t nMaxOrphanBlocksSize = GetArg("-maxorphanblocksmib", DEFAULT_MAX_ORPHAN_BLOCKS) * ((size_t) 1 << 20); while (nOrphanBlocksSize > nMaxOrphanBlocksSize) { @@ -1889,7 +1920,7 @@ void static PruneOrphanBlocks() } } -static const int64_t nTargetTimespan = 16 * 60; // 16 mins +static const int64_t nTargetTimespan = 24 * 60 * 60; // 24 hours // ppcoin: find last block index up to pindex @@ -1912,17 +1943,17 @@ unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfS CBigNum bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit(pindexLast->nHeight) : Params().ProofOfWorkLimit(); - if (pindexLast == NULL) + if (pindexLast == nullptr) return bnTargetLimit.GetCompact(); // genesis block const CBlockIndex* pindexPrev = GetLastBlockIndex(pindexLast, fProofOfStake); - if (pindexPrev->pprev == NULL) + if (pindexPrev->pprev == nullptr) return bnTargetLimit.GetCompact(); // first block const CBlockIndex* pindexPrevPrev = GetLastBlockIndex(pindexPrev->pprev, fProofOfStake); - if (pindexPrevPrev->pprev == NULL) + if (pindexPrevPrev->pprev == nullptr) return bnTargetLimit.GetCompact(); // second block - int64_t nTargetSpacing = GetTargetSpacing(pindexLast->nHeight); + int64_t nTargetSpacing = GetTargetSpacing(pindexLast->nHeight, pindexLast->GetBlockTime()); int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime(); if (nActualSpacing < 0) nActualSpacing = nTargetSpacing; @@ -1949,20 +1980,20 @@ unsigned int GetNextTargetRequiredThin(const CBlockThinIndex* pindexLast, bool f { CBigNum bnTargetLimit = fProofOfStake ? Params().ProofOfStakeLimit(pindexLast->nHeight) : Params().ProofOfWorkLimit(); - if (pindexLast == NULL) + if (pindexLast == nullptr) return bnTargetLimit.GetCompact(); // genesis block const CBlockThinIndex* pindexPrev = GetLastBlockThinIndex(pindexLast, fProofOfStake); - if (pindexPrev->pprev == NULL) + if (pindexPrev->pprev == nullptr) return bnTargetLimit.GetCompact(); // first block const CBlockThinIndex* pindexPrevPrev = GetLastBlockThinIndex(pindexPrev->pprev, fProofOfStake); - if (pindexPrevPrev->pprev == NULL) + if (pindexPrevPrev->pprev == nullptr) return bnTargetLimit.GetCompact(); // second block - int64_t nTargetSpacing = GetTargetSpacing(pindexLast->nHeight); + int64_t nTargetSpacing = GetTargetSpacing(pindexLast->nHeight, pindexLast->GetBlockTime()); int64_t nActualSpacing = pindexPrev->GetBlockTime() - pindexPrevPrev->GetBlockTime(); if (nActualSpacing < 0) nActualSpacing = nTargetSpacing; @@ -2007,7 +2038,7 @@ bool IsInitialBlockDownload() { LOCK(cs_main); - if (pindexBest == NULL || nBestHeight < Checkpoints::GetTotalBlocksEstimate()) + if (pindexBest == nullptr || nBestHeight < Checkpoints::GetTotalBlocksEstimate()) return true; static int64_t nLastUpdate; @@ -2029,7 +2060,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) { nBestInvalidTrust = pindexNew->nChainTrust; CTxDB().WriteBestInvalidTrust(CBigNum(nBestInvalidTrust)); - uiInterface.NotifyBlocksChanged(); + // uiInterface.NotifyBlocksChanged(); }; uint256 nBestInvalidBlockTrust = pindexNew->nChainTrust - pindexNew->pprev->nChainTrust; @@ -2044,6 +2075,8 @@ void static InvalidChainFound(CBlockIndex* pindexNew) CBigNum(pindexBest->nChainTrust).ToString().c_str(), nBestBlockTrust.Get64(), DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); + + pwalletMain->CacheAnonStats(nBestHeight); } @@ -2077,8 +2110,11 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb) // Relinquish previous transactions' spent pointers if (!IsCoinBase()) { - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) { + if (txin.IsAnonInput()) + continue; + COutPoint prevout = txin.prevout; // Get prev txindex from disk @@ -2190,13 +2226,18 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTes return true; } -static bool CheckAnonInputAB(CTxDB &txdb, const CTxIn &txin, int i, int nRingSize, std::vector &vchImage, uint256 &preimage, int64_t &nCoinValue) +bool CTransaction::CheckAnonInputAB(CTxDB &txdb, const CTxIn &txin, int i, int nRingSize, const std::vector &vchImage, int64_t &nCoinValue) const { const CScript &s = txin.scriptSig; + if (s.size() != 2 + EC_SECRET_SIZE + (EC_SECRET_SIZE + EC_COMPRESSED_SIZE) * nRingSize) + { + LogPrintf("CheckAnonInputAB(): Error input %d scriptSig size does not match for ringsize %d.\n", i, nRingSize); + return false; + } + CPubKey pkRingCoin; CAnonOutput ao; - CTxIndex txindex; ec_point pSigC; pSigC.resize(EC_SECRET_SIZE); @@ -2222,15 +2263,28 @@ static bool CheckAnonInputAB(CTxDB &txdb, const CTxIn &txin, int i, int nRingSiz return false; }; + int minBlockHeight = ao.fCoinStake || IsAnonCoinStake() ? Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; if (ao.nBlockHeight == 0 - || nBestHeight - ao.nBlockHeight < MIN_ANON_SPEND_DEPTH) + || nBestHeight - ao.nBlockHeight + 1 < minBlockHeight) // ao confirmed in last block has depth of 1 { - LogPrintf("CheckAnonInputsAB(): Error input %d, element %d depth < MIN_ANON_SPEND_DEPTH.\n", i, ri); + LogPrintf("CheckAnonInputsAB(): Error input %d, element %d depth < %d (nBestHeight:%d ao.nBlockHeight:%d ao.fCoinstake:%s).\n", + i, ri, minBlockHeight, nBestHeight, ao.nBlockHeight, ao.fCoinStake); return false; }; + + if (Params().IsForkV3(nTime) && nCoinValue <= nMaxAnonOutput && ao.nCompromised > 0) + { + LogPrintf("CheckAnonInputsAB(): Error input %d, element %d is compromised.\n", i, ri); + return false; + } + + int nCompromisedHeight = mapAnonOutputStats[nCoinValue].nCompromisedHeight; + if (nCompromisedHeight != 0 && nCompromisedHeight - MIN_ANON_SPEND_DEPTH >= ao.nBlockHeight) + LogPrintf("CheckAnonInputsAB(): Warn tx %s, input %d, element %d does use a mixin which is compromised by ALL SPENT (ao.nValue:%d, ao.nBlockHeight:%d, nCompromisedHeight:%d).\n", + GetHash().ToString(), i, ri, ao.nValue, ao.nBlockHeight, nCompromisedHeight); }; - if (verifyRingSignatureAB(vchImage, preimage, nRingSize, pPubkeys, pSigC, pSigS) != 0) + if (verifyRingSignatureAB(vchImage, nRingSize, pPubkeys, pSigC, pSigS) != 0) { LogPrintf("CheckAnonInputsAB(): Error input %d verifyRingSignatureAB() failed.\n", i); return false; @@ -2297,11 +2351,11 @@ bool CTransaction::CheckAnonInputs(CTxDB& txdb, int64_t& nSumValue, bool& fInval }; int64_t nCoinValue = -1; - int nRingSize = txin.ExtractRingSize(); - if (nRingSize < 1 - ||nRingSize > (Params().IsProtocolV3(pindexBest->nHeight) ? (int)MAX_RING_SIZE : (int)MAX_RING_SIZE_OLD)) + uint32_t nRingSize = (uint32_t)txin.ExtractRingSize(); + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(nTime); + if (nRingSize < nMinRingSize || nRingSize > nMaxRingSize) { - LogPrintf("CheckAnonInputs(): Error input %d ringsize %d not in range [%d, %d].\n", i, nRingSize, MIN_RING_SIZE, MAX_RING_SIZE); + LogPrintf("CheckAnonInputs(): Error input %d ringsize %d not in range [%d, %d].\n", i, nRingSize, nMinRingSize, nMaxRingSize); fInvalid = true; return false; }; @@ -2309,60 +2363,60 @@ bool CTransaction::CheckAnonInputs(CTxDB& txdb, int64_t& nSumValue, bool& fInval if (nRingSize > 1 && s.size() == 2 + EC_SECRET_SIZE + (EC_SECRET_SIZE + EC_COMPRESSED_SIZE) * nRingSize) { // ringsig AB - if (!CheckAnonInputAB(txdb, txin, i, nRingSize, vchImage, preimage, nCoinValue)) + if (!CheckAnonInputAB(txdb, txin, i, nRingSize, vchImage, nCoinValue)) { fInvalid = true; return false; }; - - nSumValue += nCoinValue; - continue; - }; - - if (s.size() < 2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE + EC_SECRET_SIZE) * nRingSize) - { - LogPrintf("CheckAnonInputs(): Error input %d scriptSig too small.\n", i); - fInvalid = true; return false; - }; - - - CPubKey pkRingCoin; - CAnonOutput ao; - CTxIndex txindex; - const unsigned char* pPubkeys = &s[2]; - const unsigned char* pSigc = &s[2 + EC_COMPRESSED_SIZE * nRingSize]; - const unsigned char* pSigr = &s[2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE) * nRingSize]; - for (int ri = 0; ri < nRingSize; ++ri) + } + else { - pkRingCoin = CPubKey(&pPubkeys[ri * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); - if (!txdb.ReadAnonOutput(pkRingCoin, ao)) + if (s.size() < 2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE + EC_SECRET_SIZE) * nRingSize) { - LogPrintf("CheckAnonInputs(): Error input %d, element %d AnonOutput %s not found.\n", i, ri, HexStr(pkRingCoin).c_str()); + LogPrintf("CheckAnonInputs(): Error input %d scriptSig too small.\n", i); fInvalid = true; return false; }; - if (nCoinValue == -1) - { - nCoinValue = ao.nValue; - } else - if (nCoinValue != ao.nValue) + + CPubKey pkRingCoin; + CAnonOutput ao; + const unsigned char* pPubkeys = &s[2]; + const unsigned char* pSigc = &s[2 + EC_COMPRESSED_SIZE * nRingSize]; + const unsigned char* pSigr = &s[2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE) * nRingSize]; + for (int ri = 0; ri < nRingSize; ++ri) { - LogPrintf("CheckAnonInputs(): Error input %d, element %d ring amount mismatch %d, %d.\n", i, ri, nCoinValue, ao.nValue); - fInvalid = true; return false; + pkRingCoin = CPubKey(&pPubkeys[ri * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); + if (!txdb.ReadAnonOutput(pkRingCoin, ao)) + { + LogPrintf("CheckAnonInputs(): Error input %d, element %d AnonOutput %s not found.\n", i, ri, HexStr(pkRingCoin).c_str()); + fInvalid = true; return false; + }; + + if (nCoinValue == -1) + { + nCoinValue = ao.nValue; + } else + if (nCoinValue != ao.nValue) + { + LogPrintf("CheckAnonInputs(): Error input %d, element %d ring amount mismatch %d, %d.\n", i, ri, nCoinValue, ao.nValue); + fInvalid = true; return false; + }; + + int minBlockHeight = ao.fCoinStake || IsAnonCoinStake() ? Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; + if (ao.nBlockHeight == 0 + || nBestHeight - ao.nBlockHeight + 1 < minBlockHeight) // ao confirmed in last block has depth of 1 + { + LogPrintf("CheckAnonInputs(): Error input %d, element %d depth < %d (nBestHeight:%d ao.nBlockHeight:%d ao.fCoinstake:%d).\n", + i, ri, minBlockHeight, nBestHeight, ao.nBlockHeight, ao.fCoinStake); + fInvalid = true; return false; + }; }; - if (ao.nBlockHeight == 0 - || nBestHeight - ao.nBlockHeight < MIN_ANON_SPEND_DEPTH) + if (verifyRingSignature(vchImage, preimage, nRingSize, pPubkeys, pSigc, pSigr) != 0) { - LogPrintf("CheckAnonInputs(): Error input %d, element %d depth < MIN_ANON_SPEND_DEPTH.\n", i, ri); + LogPrintf("CheckAnonInputs(): Error input %d verifyRingSignature() failed.\n", i); fInvalid = true; return false; }; - }; - - if (verifyRingSignature(vchImage, preimage, nRingSize, pPubkeys, pSigc, pSigr) != 0) - { - LogPrintf("CheckAnonInputs(): Error input %d verifyRingSignature() failed.\n", i); - fInvalid = true; return false; - }; + } nSumValue += nCoinValue; }; @@ -2444,20 +2498,20 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs, map= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) return DoS(100, error("ConnectInputs() : %s prevout.n out of range %d %u %u prev tx %s\n%s", GetHash().ToString(), prevout.n, txPrev.vout.size(), txindex.vSpent.size(), prevout.hash.ToString(), txPrev.ToString())); - // If prev is coinbase or coinstake, check that it's matured - if (txPrev.IsCoinBase() || txPrev.IsCoinStake()) - { - int nSpendDepth; - if (IsConfirmedInNPrevBlocks(txindex, pindexBlock, nCoinbaseMaturity, nSpendDepth)) - return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", nSpendDepth); - } - // ppcoin: check transaction timestamp if (txPrev.nTime > nTime) return DoS(100, error("ConnectInputs() : transaction timestamp earlier than input transaction")); if (Params().IsProtocolV3(pindexBlock->nHeight)) { + // If prev is coinbase or coinstake, check that it's matured + if (txPrev.IsCoinBase() || txPrev.IsCoinStake()) + { + int nSpendDepth; + if (IsConfirmedInNPrevBlocks(txindex, pindexBlock, Params().GetStakeMinConfirmations(nTime) -1 , nSpendDepth)) + return error("ConnectInputs() : tried to spend %s at depth %d", txPrev.IsCoinBase() ? "coinbase" : "coinstake", nSpendDepth + 1); + } + if (txPrev.vout[prevout.n].IsEmpty()) return DoS(1, error("ConnectInputs() : special marker is not spendable")); } @@ -2532,8 +2586,9 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, MapPrevTx inputs, mapRemoveAnonStats(txdb, pindex->nHeight)) + return error("DiconnectBlock() : RemoveAnonStats failed."); + return true; } +void static validateAnonCache(int nBlockHeight) +{ + // -- validate cache against persisted data + std::list lOutputCounts; + if (pwalletMain->CountAllAnonOutputs(lOutputCounts, nBlockHeight) != 0) + { + LogPrintf("RemoveAnonStats(%d) Error: CountAllAnonOutputs() failed.\n", nBlockHeight); + }; + for (const auto & anonOutputStat : lOutputCounts) + { + if (mapAnonOutputStats[anonOutputStat.nValue].nExists != anonOutputStat.nExists) + LogPrintf("ConnectBlock(%d) [%d] Cache Stale: nExists cache %d <> %d persisted.\n", + nBestHeight, anonOutputStat.nValue, mapAnonOutputStats[anonOutputStat.nValue].nExists, anonOutputStat.nExists); + if (mapAnonOutputStats[anonOutputStat.nValue].nSpends != anonOutputStat.nSpends) + LogPrintf("ConnectBlock(%d) [%d] Cache Stale: nSpends cache %d <> %d persisted.\n", + nBestHeight, anonOutputStat.nValue, mapAnonOutputStats[anonOutputStat.nValue].nSpends, anonOutputStat.nSpends); + if (mapAnonOutputStats[anonOutputStat.nValue].nMature != anonOutputStat.nMature) + LogPrintf("ConnectBlock(%d) [%d] Cache Stale: nMature cache %d <> %d persisted.\n", + nBestHeight, anonOutputStat.nValue, mapAnonOutputStats[anonOutputStat.nValue].nMature, anonOutputStat.nMature); + if (mapAnonOutputStats[anonOutputStat.nValue].nMixins != anonOutputStat.nMixins) + LogPrintf("ConnectBlock(%d) [%d] Cache Stale: nMixins cache %d <> %d persisted.\n", + nBestHeight, anonOutputStat.nValue, mapAnonOutputStats[anonOutputStat.nValue].nMixins, anonOutputStat.nMixins); + if (mapAnonOutputStats[anonOutputStat.nValue].nMixinsStaking != anonOutputStat.nMixinsStaking) + LogPrintf("ConnectBlock(%d) [%d] Cache Stale: nMixinsStaking cache %d <> %d persisted.\n", + nBestHeight, anonOutputStat.nValue, mapAnonOutputStats[anonOutputStat.nValue].nMixinsStaking, anonOutputStat.nMixinsStaking); + } +} + bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) { // Check it again in case a previous version let a bad block in, but skip BlockSig checking @@ -2614,6 +2700,13 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) else nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - (2 * GetSizeOfCompactSize(0)) + GetSizeOfCompactSize(vtx.size()); + // Init anon cache if needed - using helper function + if (!AliasConnectBlock::CheckAnonCacheEarly(pindex)) + { + LogPrintf("ConnectBlock() : CheckAnonCacheEarly failed.\n"); + // Continue anyway - cache check is not critical for block validation + } + map mapQueuedChanges; int64_t nFees = 0; int64_t nAnonIn = 0; @@ -2622,7 +2715,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) int64_t nValueOut = 0; int64_t nStakeReward = 0; unsigned int nSigOps = 0; - BOOST_FOREACH(CTransaction& tx, vtx) + for (CTransaction& tx : vtx) { uint256 hashTx = tx.GetHash(); @@ -2641,7 +2734,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) CTxIndex txindexOld; if (txdb.ReadTxIndex(hashTx, txindexOld)) { - BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent) + for (CDiskTxPos& pos : txindexOld.vSpent) if (pos.IsNull()) return false; } @@ -2673,22 +2766,27 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) int64_t nTxValueIn = tx.GetValueIn(mapInputs); int64_t nTxValueOut = tx.GetValueOut(); + // Use helper function for anon transaction processing if (tx.nVersion == ANON_TXN_VERSION) { - int64_t nTxAnonIn; - - BOOST_FOREACH(const CTxOut& txout, tx.vout) - if (txout.IsAnonOutput()) - nAnonOut += txout.nValue; - + int64_t nTxAnonIn = 0; + int64_t nTxAnonOut = 0; + + // Use helper function to process anon transaction + // Note: We need to adapt to old error handling style + bool fInvalid = false; if (!tx.CheckAnonInputs(txdb, nTxAnonIn, fInvalid, true)) { if (fInvalid) return error("ConnectBlock() : CheckAnonInputs found invalid tx %s", tx.GetHash().ToString().substr(0,10).c_str()); return false; - }; - + } + + // Count anon outputs using helper + nTxAnonOut = AliasValidation::CountAnonOutputs(tx); + nAnonIn += nTxAnonIn; + nAnonOut += nTxAnonOut; nTxValueIn += nTxAnonIn; } @@ -2720,20 +2818,57 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) if (IsProofOfStake()) { // ppcoin: coin stake tx earns reward instead of paying fee - uint64_t nCoinAge; - if (!vtx[1].GetCoinAge(txdb, pindex->pprev, nCoinAge)) + uint64_t nCoinAge = 0; + if (!Params().IsProtocolV3(pindex->pprev->nHeight) && !vtx[1].GetCoinAge(txdb, pindex->pprev, nCoinAge)) return error("ConnectBlock() : %s unable to get coin age for coinstake", vtx[1].GetHash().ToString()); - int64_t nCalculatedStakeReward = Params().GetProofOfStakeReward(pindex->pprev, nCoinAge, nFees); + // Use helper function for stake reward validation + // Note: We need to adapt BlockValidationState to old error handling + // For now, keep the old validation but use helper for calculation + int64_t nCalculatedStakeReward; + if (IsProofOfAnonStake()) // Use existing method on CBlock + { + nCalculatedStakeReward = Params().GetProofOfAnonStakeReward(pindex->pprev, nFees); + } + else + { + nCalculatedStakeReward = Params().GetProofOfStakeReward(pindex->pprev, nCoinAge, nFees); + } if (nStakeReward > nCalculatedStakeReward) return DoS(100, error("ConnectBlock() : coinstake pays too much(actual=%d vs calculated=%d)", nStakeReward, nCalculatedStakeReward)); + + // Use helper function for dev contribution check + bool fSupplyIncrease = Params().IsForkV4SupplyIncrease(pindex->pprev); + if (fSupplyIncrease || (Params().IsForkV2(nTime) && pindex->nHeight % 6 == 0)) { + CBitcoinAddress address(fSupplyIncrease ? Params().GetSupplyIncreaseAddress() : Params().GetDevContributionAddress()); + CScript scriptPubKey; + scriptPubKey.SetDestination(address.Get()); + + bool containsDonation = false; + + //the donation can be at i = 2 or above. so we start looking for it there + for (int i = 2; i < vtx[1].vout.size(); i++) { + if (vtx[1].vout[i].scriptPubKey == scriptPubKey) { + if (vtx[1].vout[i].nValue >= nCalculatedStakeReward) { + //we found a donation. Stop searching + containsDonation = true; + break; + } + } + } + if (!containsDonation) { + LogPrintf("ConnectBlock() : stake does not pay to address %s\n", address.ToString().c_str()); + return DoS(100, error("ConnectBlock() : stake does not pay to address %s in trx\n%s\n", address.ToString().c_str(), vtx[1].ToString())); + } + } } // ppcoin: track money supply and mint amount info pindex->nMint = nValueOut - nValueIn + nFees; pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn; - pindex->nAnonSupply = (pindex->pprev? pindex->pprev->nAnonSupply : 0) + nAnonOut - nAnonIn; + // Use helper function to update anon supply + AliasConnectBlock::UpdateAliasBlockIndex(pindex, nAnonOut, nAnonIn); if (!txdb.WriteBlockIndex(CDiskBlockIndex(pindex))) return error("ConnectBlock() : WriteBlockIndex for pindex failed"); @@ -2758,8 +2893,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) } // Watch for transactions paying to me - BOOST_FOREACH(CTransaction& tx, vtx) - SyncWithWallets(tx, this, true); + for (CTransaction& tx : vtx) + SyncWithWallets(tx, this, true); // calls ProcessAnonTransaction() which persists anons also in txDB + + // Update anon cache with stats of connected block (added in ProcessAnonTransaction()) + if (!pwalletMain->UpdateAnonStats(txdb, pindex->nHeight)) + return error("ConnectBlock() : UpdateAnonStats failed."); return true; } @@ -2798,7 +2937,7 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) // Disconnect shorter branch list vResurrect; - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) + for (CBlockIndex* pindex : vDisconnect) { CBlock block; if (!block.ReadFromDisk(pindex)) @@ -2829,7 +2968,7 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) } // Queue memory transactions to delete - BOOST_FOREACH(const CTransaction& tx, block.vtx) + for (const CTransaction& tx : block.vtx) vDelete.push_back(tx); } if (!txdb.WriteHashBestChain(pindexNew->GetBlockHash())) @@ -2840,21 +2979,21 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) return error("Reorganize() : TxnCommit failed"); // Disconnect shorter branch - BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) + for (CBlockIndex* pindex : vDisconnect) if (pindex->pprev) - pindex->pprev->pnext = NULL; + pindex->pprev->pnext = nullptr; // Connect longer branch - BOOST_FOREACH(CBlockIndex* pindex, vConnect) + for (CBlockIndex* pindex : vConnect) if (pindex->pprev) pindex->pprev->pnext = pindex; // Resurrect memory transactions that were in the disconnected branch - BOOST_FOREACH(CTransaction& tx, vResurrect) + for (CTransaction& tx : vResurrect) AcceptToMemoryPool(mempool, tx, txdb); // Delete redundant memory transactions that are in the connected branch - BOOST_FOREACH(CTransaction& tx, vDelete) { + for (CTransaction& tx : vDelete) { mempool.remove(tx); mempool.removeConflicts(tx); } @@ -2884,7 +3023,7 @@ bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew) pindexNew->pprev->pnext = pindexNew; // Delete redundant memory transactions - BOOST_FOREACH(CTransaction& tx, vtx) + for (CTransaction& tx : vtx) mempool.remove(tx); return true; @@ -2897,7 +3036,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) if (!txdb.TxnBegin()) return error("SetBestChain() : TxnBegin failed"); - if (pindexGenesisBlock == NULL && hash == Params().HashGenesisBlock()) + if (pindexGenesisBlock == nullptr && hash == Params().HashGenesisBlock()) { txdb.WriteHashBestChain(hash); if (!txdb.TxnCommit()) @@ -2966,11 +3105,19 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) // New best block hashBestChain = hash; pindexBest = pindexNew; - pblockindexFBBHLast = NULL; + pblockindexFBBHLast = nullptr; nBestHeight = pindexBest->nHeight; nBestChainTrust = pindexNew->nChainTrust; nTimeBestReceived = GetTime(); mempool.AddTransactionsUpdated(1); + chainActive.SetTip(pindexNew); + + if (fStaleAnonCache) + { + LogPrintf("SetBestChain() : Stale anon cache => rebuild.\n"); + if (!pwalletMain->CacheAnonStats(nBestHeight)) + LogPrintf("CacheAnonStats() failed.\n"); + } uint256 nBestBlockTrust = pindexBest->nHeight != 0 ? (pindexBest->nChainTrust - pindexBest->pprev->nChainTrust) : pindexBest->nChainTrust; @@ -2985,7 +3132,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) { int nUpgraded = 0; const CBlockIndex* pindex = pindexBest; - for (int i = 0; i < 100 && pindex != NULL; i++) + for (int i = 0; i < 100 && pindex != nullptr; i++) { if (pindex->nVersion > CBlock::CURRENT_VERSION) ++nUpgraded; @@ -3009,48 +3156,48 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew) return true; } -int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const +std::pair CMerkleTx::GetDepthAndHeightInMainChainINTERNAL(CBlockIndex* &pindexRet) const { if (hashBlock == 0 || nIndex == -1) - return 0; + return std::make_pair(0, -1); AssertLockHeld(cs_main); // Find the block it claims to be in map::iterator mi = mapBlockIndex.find(hashBlock); if (mi == mapBlockIndex.end()) - return 0; + return std::make_pair(0, -1); CBlockIndex* pindex = (*mi).second; if (!pindex || !pindex->IsInMainChain()) - return 0; + return std::make_pair(0, -1); // Make sure the merkle branch connects to this block if (!fMerkleVerified) { if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot) - return 0; + return std::make_pair(0, -1); fMerkleVerified = true; } pindexRet = pindex; - return pindexBest->nHeight - pindex->nHeight + 1; + return std::make_pair(pindexBest->nHeight - pindex->nHeight + 1, pindex->nHeight); } -int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const +std::pair CMerkleTx::GetDepthAndHeightInMainChain(CBlockIndex* &pindexRet) const { AssertLockHeld(cs_main); - int nResult = GetDepthInMainChainINTERNAL(pindexRet); - if (nResult == 0 && !mempool.exists(GetHash())) - return -1; // Not in chain, not in mempool + pair nResult = GetDepthAndHeightInMainChainINTERNAL(pindexRet); + if (nResult.first == 0 && !mempool.exists(GetHash())) + return std::make_pair(-1, -1); // Not in chain, not in mempool return nResult; } -int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const +std::pair CMerkleTx::GetDepthAndHeightInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const { //if (hashBlock == 0 || nIndex == -1) if (hashBlock == 0) - return 0; + return std::make_pair(0, -1); AssertLockHeld(cs_main); @@ -3058,7 +3205,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const map::iterator mi = mapBlockThinIndex.find(hashBlock); if (mi == mapBlockThinIndex.end()) { - pindexRet = NULL; + pindexRet = nullptr; if (!fThinFullIndex) { @@ -3068,15 +3215,15 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const CDiskBlockThinIndex diskindex; if (txdb.ReadBlockThinIndex(hashBlock, diskindex) && diskindex.hashNext != 0) - return pindexBestHeader->nHeight - diskindex.nHeight + 1; + return std::make_pair(pindexBestHeader->nHeight - diskindex.nHeight + 1, diskindex.nHeight); }; - return 0; + return std::make_pair(0, -1); }; CBlockThinIndex* pindex = (*mi).second; if (!pindex || !pindex->IsInMainChain()) - return 0; + return std::make_pair(0, -1); /* // Make sure the merkle branch connects to this block @@ -3088,15 +3235,15 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const }; */ pindexRet = pindex; - return pindexBestHeader->nHeight - pindex->nHeight + 1; + return std::make_pair(pindexBestHeader->nHeight - pindex->nHeight + 1, pindex->nHeight); } -int CMerkleTx::GetDepthInMainChain(CBlockThinIndex* &pindexRet) const +std::pair CMerkleTx::GetDepthAndHeightInMainChain(CBlockThinIndex* &pindexRet) const { AssertLockHeld(cs_main); - int nResult = GetDepthInMainChainINTERNAL(pindexRet); - if (nResult == 0 && !mempool.exists(GetHash())) - return -1; // Not in chain, not in mempool + std::pair nResult = GetDepthAndHeightInMainChainINTERNAL(pindexRet); + if (nResult.first == 0 && !mempool.exists(GetHash())) + return std::make_pair(-1, -1); // Not in chain, not in mempool return nResult; } @@ -3106,7 +3253,16 @@ int CMerkleTx::GetBlocksToMaturity() const if (!(IsCoinBase() || IsCoinStake())) return 0; - return max(0, (nCoinbaseMaturity + 5) - GetDepthInMainChain()); + std::pair pDepthAndHeight = GetDepthAndHeightInMainChain(); + + // Block to maturity is only relevant for PoSv3 according to the consensus rule in CheckProofOfStake + if (pDepthAndHeight.second != -1 && !Params().IsProtocolV3(pDepthAndHeight.second)) + return 0; + + int nMaturity = IsCoinBase() ? nCoinbaseMaturity : + IsAnonCoinStake() ? Params().GetAnonStakeMinConfirmations() : + Params().GetStakeMinConfirmations(GetAdjustedTime()); + return max(0, nMaturity - pDepthAndHeight.first); } @@ -3297,7 +3453,7 @@ bool CTransaction::GetCoinAge(CTxDB& txdb, const CBlockIndex* pindexPrev, uint64 if (IsCoinBase()) return true; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) { // First try finding the previous transaction in database CTransaction txPrev; @@ -3310,7 +3466,7 @@ bool CTransaction::GetCoinAge(CTxDB& txdb, const CBlockIndex* pindexPrev, uint64 if (Params().IsProtocolV3(pindexPrev->nHeight)) { int nSpendDepth; - if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, nStakeMinConfirmations - 1, nSpendDepth)) + if (IsConfirmedInNPrevBlocks(txindex, pindexPrev, Params().GetStakeMinConfirmations(nTime) - 1, nSpendDepth)) { LogPrint("coinage", "coin age skip nSpendDepth=%d\n", nSpendDepth + 1); continue; // only count coins meeting min confirmations requirement @@ -3395,6 +3551,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u if (!ComputeNextStakeModifier(pindexNew->pprev, nStakeModifier, fGeneratedStakeModifier)) return error("AddToBlockIndex() : ComputeNextStakeModifier() failed"); pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier); + // note prevout.hash contains keyImage if vin[0] is anon input pindexNew->bnStakeModifierV2 = ComputeStakeModifierV2(pindexNew->pprev, IsProofOfWork() ? hash : vtx[1].vin[0].prevout.hash); // Add to mapBlockIndex @@ -3428,7 +3585,8 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos, const u hashPrevBestCoinBase = vtx[0].GetHash(); } - uiInterface.NotifyBlocksChanged(); + BlockChangedEvent blockChangedEvent = {nBestHeight, GetNumBlocksOfPeers(), IsInitialBlockDownload(), pindexBest->GetBlockTime()}; + uiInterface.NotifyBlocksChanged(blockChangedEvent); return true; } @@ -3474,11 +3632,12 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c // Check proof-of-stake block signature if (fCheckSig && !CheckBlockSignature()) - return DoS(100, error("CheckBlock() : bad proof-of-stake block signature")); + return IsProofOfAnonStake() ? DoS(100, error("CheckBlock() : bad proof-of-anon-stake block signature")) : + DoS(100, error("CheckBlock() : bad proof-of-stake block signature")); } // Check transactions - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) { if (!tx.CheckTransaction()) return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed")); @@ -3491,7 +3650,7 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c // Check for duplicate txids. This is caught by ConnectInputs(), // but catching it earlier avoids a potential DoS attack: set uniqueTx; - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) { uniqueTx.insert(tx.GetHash()); } @@ -3499,7 +3658,7 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c return DoS(100, error("CheckBlock() : duplicate transaction")); unsigned int nSigOps = 0; - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) { nSigOps += tx.GetLegacySigOpCount(); }; @@ -3562,7 +3721,7 @@ bool CBlock::AcceptBlock() return error("AcceptBlock() : block's timestamp is too early"); // Check that all transactions are finalized - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) if (!tx.IsFinal(nHeight, GetBlockTime())) return DoS(10, error("AcceptBlock() : contains a non-final transaction")); @@ -3599,6 +3758,48 @@ bool CBlock::AcceptBlock() if (fReindexing) return true; + // Prevent fake stake block spam attacks on forks + if (IsProofOfStake() && !chainActive.Contains(pindexPrev)) + { + // start at the block we're adding on to + CBlockIndex *last = pindexPrev; + + bool isAnonCoinStake = IsProofOfAnonStake(); + ec_point vchImage, vchImageIn; + if (isAnonCoinStake) + vtx[1].vin[0].ExtractKeyImage(vchImage); + + // while that block is not on the main chain + while (!chainActive.Contains(last)) + { + CBlock bl; + if (!bl.ReadFromDisk(last)) + return error("AcceptBlock() : ReadFromDisk for prev forked block failed"); + + // loop through every spent input from said block + for (CTransaction t : bl.vtx) + { + for (CTxIn in: t.vin) + { + if (in.IsAnonInput() != isAnonCoinStake) + continue; + + if (isAnonCoinStake) + { + in.ExtractKeyImage(vchImageIn); + if (vchImage == vchImageIn) + return DoS(100, error("AcceptBlock() : rejected because keyImage spent in prev forked block")); + } + else if (vtx[1].vin[0].prevout == in.prevout) + return DoS(100, error("AcceptBlock() : rejected because prevout spent in prev forked block")); + } + } + + // go to the parent block + last = last->pprev; + } + } + // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); @@ -3615,7 +3816,7 @@ bool CBlock::AcceptBlock() if (hashBestChain == hash) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if (nBestHeight > (pnode->nChainHeight != -1 ? pnode->nChainHeight - 2000 : nBlockEstimate)) pnode->PushInventory(CInv(MSG_BLOCK, hash)); } @@ -3637,7 +3838,7 @@ uint256 CBlockIndex::GetBlockTrust() const bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) { unsigned int nFound = 0; - for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) + for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != nullptr; i++) { if (pstart->nVersion >= minVersion) ++nFound; @@ -3657,6 +3858,23 @@ uint256 CBlockThinIndex::GetBlockTrust() const return ((CBigNum(1)<<256) / (bnTarget+1)).getuint256(); } + +/** + * CChain implementation + */ +void CChain::SetTip(CBlockIndex *pindex) { + if (pindex == nullptr) { + vChain.clear(); + return; + } + vChain.resize(pindex->nHeight + 1); + while (pindex && vChain[pindex->nHeight] != pindex) { + vChain[pindex->nHeight] = pindex; + pindex = pindex->pprev; + } +} + + bool ProcessBlock(CNode* pfrom, CBlock* pblock, uint256& hash) { AssertLockHeld(cs_main); @@ -3708,15 +3926,26 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock, uint256& hash) if (setStakeSeenOrphan.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash)) return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for orphan block %s", pblock->GetProofOfStake().first.ToString(), pblock->GetProofOfStake().second, hash.ToString()); } - PruneOrphanBlocks(); + const COrphanBlock* orphan = AddOrphanBlock(pblock); - // Ask this guy to fill in what we're missing - pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(hash)); - // ppcoin: getblocks may not obtain the ancestor block rejected - // earlier by duplicate-stake check so we ask for it again directly - if (!IsInitialBlockDownload()) - pfrom->AskFor(CInv(MSG_BLOCK, WantedByOrphan(orphan))); + const CBlockIndex* pcheckpoint = Checkpoints::AutoSelectSyncCheckpoint(); + map::iterator it = mapOrphanBlocks.find(GetOrphanRoot(hash)); + if (it != mapOrphanBlocks.end() && it->second->nTime < pcheckpoint->nTime) + { + PruneOrphanBlocks(); + pfrom->Misbehaving(1); + return error("ProcessBlock() : orphan root block with timestamp before last checkpoint"); + } + else { + // Ask this guy to fill in what we're missing + pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(hash)); + // ppcoin: getblocks may not obtain the ancestor block rejected + // earlier by duplicate-stake check so we ask for it again directly + if (!IsInitialBlockDownload()) + pfrom->AskFor(CInv(MSG_BLOCK, WantedByOrphan(orphan))); + PruneOrphanBlocks(); + } } return true; } @@ -3861,37 +4090,49 @@ bool CBlock::SignBlock(CWallet& wallet, int64_t nFees) static int64_t nLastCoinStakeSearchTime = GetAdjustedTime(); // startup timestamp - CKey key; - CTransaction txCoinStake; + int64_t nSearchTime = GetAdjustedTime(); // search to current time if (Params().IsProtocolV2(nBestHeight+1)) - txCoinStake.nTime &= ~STAKE_TIMESTAMP_MASK; - - int64_t nSearchTime = txCoinStake.nTime; // search to current time + nSearchTime &= ~STAKE_TIMESTAMP_MASK; // decrease granularity to 16 seconds if (nSearchTime > nLastCoinStakeSearchTime) { int64_t nSearchInterval = Params().IsProtocolV2(nBestHeight+1) ? 1 : nSearchTime - nLastCoinStakeSearchTime; - if (wallet.CreateCoinStake(nBits, nSearchInterval, nFees, txCoinStake, key)) + + CKey key; + CTransaction txCoinStake; + txCoinStake.nTime = nSearchTime; + + bool foundStake = false; + if (Params().IsForkV3(nSearchTime) && Params().IsProtocolV3(nBestHeight+1) && + wallet.CreateAnonCoinStake(nBits, nSearchInterval, nFees, txCoinStake, key)) + foundStake = true; + else { - if (txCoinStake.nTime >= pindexBest->GetPastTimeLimit()+1) - { + key.Clear(); + txCoinStake.SetNull(); + txCoinStake.nTime = nSearchTime; + if (wallet.CreateCoinStake(nBits, nSearchInterval, nFees, txCoinStake, key)) + foundStake = true; + } - // make sure coinstake would meet timestamp protocol - // as it would be the same as the block timestamp - vtx[0].nTime = nTime = txCoinStake.nTime; + if (foundStake && txCoinStake.nTime >= pindexBest->GetPastTimeLimit()+1) + { + // make sure coinstake would meet timestamp protocol + // as it would be the same as the block timestamp + vtx[0].nTime = nTime = txCoinStake.nTime; - // we have to make sure that we have no future timestamps in - // our transactions set - for (vector::iterator it = vtx.begin(); it != vtx.end();) - if (it->nTime > nTime) { it = vtx.erase(it); } else { ++it; } + // we have to make sure that we have no future timestamps in + // our transactions set + for (vector::iterator it = vtx.begin(); it != vtx.end();) + if (it->nTime > nTime) { it = vtx.erase(it); } else { ++it; } - vtx.insert(vtx.begin() + 1, txCoinStake); - hashMerkleRoot = BuildMerkleTree(); + vtx.insert(vtx.begin() + 1, txCoinStake); + hashMerkleRoot = BuildMerkleTree(); - // append a signature to our block - return key.Sign(GetHash(), vchBlockSig); - } + // append a signature to our block + return key.Sign(GetHash(), vchBlockSig); } + nLastCoinStakeSearchInterval = nSearchTime - nLastCoinStakeSearchTime; nLastCoinStakeSearchTime = nSearchTime; } @@ -3907,6 +4148,9 @@ bool CBlock::CheckBlockSignature() const if (vchBlockSig.empty()) return false; + if (IsProofOfAnonStake()) + return CheckAnonBlockSignature(); + vector vSolutions; txnouttype whichType; @@ -3942,6 +4186,18 @@ bool CBlock::CheckBlockSignature() const return false; } +bool CBlock::CheckAnonBlockSignature() const +{ + if (vtx.size() < 2 || !vtx[1].IsAnonCoinStake()) + return false; + + const CTxOut& txout = vtx[1].vout[1]; + const CScript &s = txout.scriptPubKey; + const CPubKey pkCoin = CPubKey(&s[2+1], EC_COMPRESSED_SIZE); + + return pkCoin.Verify(GetHash(), vchBlockSig); +} + bool CBlock::GetHashProof(uint256& hashProof) { // PoW is checked in CheckBlock() @@ -3970,7 +4226,7 @@ bool CBlock::GetHashProof(uint256& hashProof) bool CheckDiskSpace(uint64_t nAdditionalBytes) { - uint64_t nFreeBytesAvailable = boost::filesystem::space(GetDataDir()).available; + uint64_t nFreeBytesAvailable = fs::space(GetDataDir()).available; // Check for nMinDiskSpace bytes (currently 50MB) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) @@ -3978,7 +4234,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) string strMessage = _("Warning: Disk space is low!"); strMiscWarning = strMessage; LogPrintf("*** %s\n", strMessage.c_str()); - uiInterface.ThreadSafeMessageBox(strMessage, "ShadowCoin", CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); + uiInterface.ThreadSafeMessageBox(strMessage, "Alias", CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING | CClientUIInterface::MODAL); StartShutdown(); return false; } @@ -3992,19 +4248,19 @@ static unsigned int nCurrentBlockThinFile = 1; FILE* OpenBlockFile(bool fHeaderFile, unsigned int nFile, unsigned int nBlockPos, const char* pszMode) { if ((nFile < 1) || (nFile == (unsigned int) -1)) - return NULL; + return nullptr; string strBlockFn = strprintf(fHeaderFile ? "blk_hdr%04u.dat": "blk%04u.dat", nFile); FILE* file = fopen((GetDataDir() / strBlockFn).string().c_str(), pszMode); if (!file) - return NULL; + return nullptr; if (nBlockPos != 0 && !strchr(pszMode, 'a') && !strchr(pszMode, 'w')) { if (fseek(file, nBlockPos, SEEK_SET) != 0) { fclose(file); - return NULL; + return nullptr; }; }; return file; @@ -4019,9 +4275,9 @@ FILE* AppendBlockFile(bool fHeaderFile, unsigned int& nFileRet, const char* fmod 0, fmode); if (!file) - return NULL; + return nullptr; if (fseek(file, 0, SEEK_END) != 0) - return NULL; + return nullptr; // FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB if (ftell(file) < (long)(0x7F000000 - MAX_SIZE)) { @@ -4035,7 +4291,7 @@ FILE* AppendBlockFile(bool fHeaderFile, unsigned int& nFileRet, const char* fmod } -int LoadBlockIndex(bool fAllowNew) +int LoadBlockIndex(bool fAllowNew, std::function funcProgress) { LOCK(cs_main); @@ -4050,10 +4306,25 @@ int LoadBlockIndex(bool fAllowNew) if (nNodeMode == NT_FULL) { - if (!txdb.LoadBlockIndex()) - return 1; - - if (!pwalletMain->CacheAnonStats()) + int res = 1; + if (!txdb.LoadBlockIndex([&res] (const CBlockIndex* const pBlockIndex) -> bool { + // Check that the block matches the known checkpoint blocks + if (Checkpoints::CheckHardened(pBlockIndex->nHeight, pBlockIndex->GetBlockHash())) + return true; + else { + res = 3; + return error("LoadBlockIndex() : Block at height %d with hash %s does not match checkpoint.", + pBlockIndex->nHeight, pBlockIndex->GetBlockHash().GetHex()); + } + }, funcProgress)) + return res; + + if (!pwalletMain->CacheAnonStats(nBestHeight, [] (const unsigned mode, const uint32_t& nOutpus) -> void { + if (mode == 0) + uiInterface.InitMessage(strprintf(_("Read ATXOs... (%d)"), nOutpus)); + else + uiInterface.InitMessage(strprintf(_("Read spent ATXOs... (%d)"), nOutpus)); + })) LogPrintf("CacheAnonStats() failed.\n"); } else { @@ -4079,8 +4350,8 @@ int LoadBlockIndex(bool fAllowNew) }; // Start new block file - unsigned int nFile; - unsigned int nBlockPos; + unsigned int nFile = 0; + unsigned int nBlockPos = 0; if (nNodeMode == NT_FULL) { @@ -4179,7 +4450,7 @@ void PrintBlockTree() } } -bool LoadExternalBlockFile(int nFile, FILE* fileIn) +bool LoadExternalBlockFile(int nFile, FILE* fileIn, std::function funcProgress) { if (nNodeMode != NT_FULL) { @@ -4189,7 +4460,7 @@ bool LoadExternalBlockFile(int nFile, FILE* fileIn) int64_t nStart = GetTimeMillis(); - int nLoaded = 0; + uint32_t nLoaded = 0; { try { @@ -4237,7 +4508,7 @@ bool LoadExternalBlockFile(int nFile, FILE* fileIn) blkdat >> block; uint256 hashblock = block.GetHash(); LOCK(cs_main); - if (ProcessBlock(NULL, &block, hashblock)) + if (ProcessBlock(nullptr, &block, hashblock)) { uint256 hashProof; if (fReindexing @@ -4247,8 +4518,10 @@ bool LoadExternalBlockFile(int nFile, FILE* fileIn) nLoaded++; nPos += 4 + nSize; - if (nLoaded % 20000 == 0) + if (nLoaded % 10000 == 0) LogPrintf("Loaded %d blocks and counting.\n", nLoaded); + if (funcProgress) + funcProgress(nLoaded); }; }; }; @@ -4275,13 +4548,13 @@ struct CImportingNow } }; -void ThreadImport(std::vector vImportFiles) +void ThreadImport(std::vector vImportFiles) { - RenameThread("shadow-loadblk"); + RenameThread("alias-loadblk"); CImportingNow imp; // -loadblock= - BOOST_FOREACH(boost::filesystem::path &path, vImportFiles) { + for (fs::path& path : vImportFiles) { FILE *file = fopen(path.string().c_str(), "rb"); if (file) { LogPrintf("Importing blocks file %s...\n", path.string()); @@ -4292,11 +4565,11 @@ void ThreadImport(std::vector vImportFiles) } // hardcoded $DATADIR/bootstrap.dat - boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (boost::filesystem::exists(pathBootstrap)) { - FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); + fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (fs::exists(pathBootstrap)) { + FILE *file = fopen(fs::PathToString(pathBootstrap).c_str(), "rb"); if (file) { - boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(0, file); RenameOver(pathBootstrap, pathBootstrapOld); @@ -4339,7 +4612,7 @@ string GetWarnings(string strFor) // Alerts { LOCK(cs_mapAlerts); - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + for (auto& item : mapAlerts) { const CAlert& alert = item.second; if (alert.AppliesToMe() && alert.nPriority > nPriority) @@ -4471,21 +4744,11 @@ static void ProcessGetData(CNode* pfrom) CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); if (pcheckpoint && nHeight < pcheckpoint->nHeight) { - //if (!chainActive.Contains(mi->second)) - // -- check if best chain contains block - // necessary? faster way? (mark unlinked blocks) - CBlockIndex *pindex = pindexBest; - while (pindex && pindex != mi->second && pindex->pprev) - pindex = pindex->pprev; - - if ((!pindex->pprev && pindex != mi->second)) // reached start of chain. - { + if (!chainActive.Contains(mi->second)) LogPrintf("ProcessGetData(): ignoring request for old block that isn't in the main chain\n"); - } else - { + else send = true; - }; } else { send = true; @@ -4538,7 +4801,7 @@ static void ProcessGetData(CNode* pfrom) CMBlkThinElement mbElem; mbElem.merkleBlock = merkleBlock; - BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn) + for (auto& pair : merkleBlock.vMatchedTxn) { if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second))) { @@ -4568,7 +4831,7 @@ static void ProcessGetData(CNode* pfrom) // they must either disconnect and retry or request the full block. // Thus, the protocol spec specified allows for us to provide duplicate txn here, // however we MUST always provide at least what the remote peer needs - BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn) + for (auto& pair : merkleBlock.vMatchedTxn) { if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second))) { @@ -4682,7 +4945,7 @@ static int ProcessMerkleBlock(CNode* pfrom, CMerkleBlockIncoming& merkleBlock, s bool fAlloc = false; - CBlockThinIndex *pBlockThinIndex = NULL; + CBlockThinIndex *pBlockThinIndex = nullptr; std::map::iterator mi = mapBlockThinIndex.find(hashBlock); if (mi != mapBlockThinIndex.end()) @@ -4826,7 +5089,7 @@ static int ProcessMerkleBlock(CNode* pfrom, CMerkleBlockIncoming& merkleBlock, s if (fDebugChain) LogPrintf("Found txn match in mempool.\n"); - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) pwallet->AddToWalletIfInvolvingMe(txMp, merkleBlock.vMatch[i], (void*)&hashBlock, true); mempool.remove(txMp); @@ -4840,7 +5103,7 @@ static int ProcessMerkleBlock(CNode* pfrom, CMerkleBlockIncoming& merkleBlock, s { CTransaction &txMp = (*pvTxns)[i]; uint256 txnhash = txMp.GetHash(); - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) pwallet->AddToWalletIfInvolvingMe(txMp, txnhash, (void*)&hashBlock, true); /* @@ -4870,7 +5133,7 @@ void static ThreadCloseSocket(void* parg) // -- loop incase pcloseNode is gone by now LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if (pnode != pcloseNode) continue; @@ -4908,7 +5171,7 @@ static bool SetNodeType(CNode* pfrom, int nTypeInd) if (pfrom->nTypeInd != NT_FULL) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if (pnode->nTypeInd != NT_FULL) nMax--; @@ -4968,6 +5231,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CAddress addrFrom; uint64_t nNonce = 1; vRecv >> pfrom->nVersion >> pfrom->nServices >> nTime >> addrMe; + + // Future fork condition. Enforce minimum protcol version based on nTime. + if (Params().IsForkV4(nTime)) { + if (pfrom->nVersion < LEGACY_CUTOFF_MIN_PROTOCOL_VERSION) + { + // disconnect from peers older than this proto version + LogPrintf("Peer %s using pre-fork version %i; disconnecting\n", pfrom->addr.ToString(), pfrom->nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("node < %d", LEGACY_CUTOFF_MIN_PROTOCOL_VERSION)); + pfrom->fDisconnect = true; + return false; + } + } + if (pfrom->nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version @@ -5109,7 +5385,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Relay alerts { LOCK(cs_mapAlerts); - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) + for (auto& item : mapAlerts) item.second.RelayTo(pfrom); } @@ -5117,7 +5393,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LogPrint("net", "receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nChainHeight, addrMe.ToString(), addrFrom.ToString(), pfrom->addr.ToString()); + LOCK(cs_main); cPeerBlockCounts.input(pfrom->nChainHeight); + + BlockChangedEvent blockChangedEvent = {nBestHeight, GetNumBlocksOfPeers(), IsInitialBlockDownload(), nNodeMode == NT_FULL ? pindexBest->GetBlockTime() : pindexBestHeader->GetBlockTime()}; + uiInterface.NotifyBlocksChanged(blockChangedEvent); } @@ -5161,7 +5441,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vector vAddrOk; int64_t nNow = GetAdjustedTime(); int64_t nSince = nNow - 10 * 60; - BOOST_FOREACH(CAddress& addr, vAddr) + for (CAddress& addr : vAddr) { boost::this_thread::interruption_point(); @@ -5183,7 +5463,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, uint256 hashRand = hashSalt ^ (hashAddr<<32) ^ ((GetTime()+hashAddr)/(24*60*60)); hashRand = Hash(BEGIN(hashRand), END(hashRand)); multimap mapMix; - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if (pnode->nVersion < CADDR_TIME_VERSION) continue; @@ -5195,7 +5475,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } int nRelayNodes = fReachable ? 2 : 1; // limited relaying of addresses outside our network(s) for (multimap::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi) - ((*mi).second)->PushAddress(addr); + { + if (!addr.IsTorV3() || ((*mi).second)->nRecvVersion >= 60042) + ((*mi).second)->PushAddress(addr); + else + nRelayNodes++; + } } } // Do not store addresses outside our network @@ -5397,7 +5682,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, LOCK(cs_main); - CBlockIndex* pindex = NULL; + CBlockIndex* pindex = nullptr; if (locator.IsNull()) { // If locator is null, return the hashStop block @@ -5450,7 +5735,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (AcceptToMemoryPool(mempool, tx, txdb, &fMissingInputs)) { - SyncWithWallets(tx, NULL, true); + SyncWithWallets(tx, nullptr, true); RelayTransaction(tx, inv.hash); vWorkQueue.push_back(inv.hash); vEraseQueue.push_back(inv.hash); @@ -5472,7 +5757,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (AcceptToMemoryPool(mempool, orphanTx, txdb, &fMissingInputs2)) { LogPrint("mempool", " accepted orphan tx %s\n", orphanTxHash.ToString()); - SyncWithWallets(tx, NULL, true); + SyncWithWallets(tx, nullptr, true); RelayTransaction(orphanTx, orphanTxHash); vWorkQueue.push_back(orphanTxHash); vEraseQueue.push_back(orphanTxHash); @@ -5486,7 +5771,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } } - BOOST_FOREACH(uint256 hash, vEraseQueue) + for (const uint256& hash : vEraseQueue) EraseOrphanTx(hash); } else if (fMissingInputs) @@ -5518,7 +5803,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, //LogPrintf("Found match.\n"); uint256 blockhash = it->header.GetHash(); - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + for (CWallet* pwallet : setpwalletRegistered) pwallet->AddToWalletIfInvolvingMe(tx, txHash, (void*)&blockhash, true); it->nProcessed++; @@ -5541,11 +5826,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, bool fMissingInputs = false; if (AcceptToMemoryPool(mempool, tx, txdb, &fMissingInputs)) { - //SyncWithWallets(tx, NULL, true); + //SyncWithWallets(tx, nullptr, true); bool added = false; - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - added = added | pwallet->AddToWalletIfInvolvingMe(tx, txHash, NULL, true); + for (CWallet* pwallet : setpwalletRegistered) + added = added | pwallet->AddToWalletIfInvolvingMe(tx, txHash, nullptr, true); if (added) RelayTransaction(tx, inv.hash); @@ -5584,9 +5869,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, nTimeLastMblkRecv = GetTime(); { - LOCK(cs_main); for (uint32_t i = 0; i < nBlocks; ++i) { + LOCK(cs_main); CBlock &block = vBlocks[i]; uint256 hashBlock = block.GetHash(); @@ -5605,11 +5890,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (block.nDoS) pfrom->Misbehaving(block.nDoS); - - if (fSecMsgEnabled) - SecureMsgScanBlock(block); - }; - } // cs_main + } // cs_main + } } else if (strCommand == "mblkt" && !fImporting && !fReindexing) // Ignore blocks received while importing { @@ -5667,8 +5949,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, if (ProcessBlock(pfrom, &block, hashBlock)) mapAlreadyAskedFor.erase(inv); if (block.nDoS) pfrom->Misbehaving(block.nDoS); - if (fSecMsgEnabled) - SecureMsgScanBlock(block); } else if (strCommand == "merkleblock") { @@ -5683,7 +5963,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, CMerkleBlockIncoming merkleBlock; vRecv >> merkleBlock; - ProcessMerkleBlock(pfrom, merkleBlock, NULL); + ProcessMerkleBlock(pfrom, merkleBlock, nullptr); } else if (strCommand == "headers") @@ -5746,7 +6026,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nCutOff = GetTime() - (nNodeLifespan * 24 * 60 * 60); pfrom->vAddrToSend.clear(); vector vAddr = addrman.GetAddr(); - BOOST_FOREACH(const CAddress &addr, vAddr) + for (const CAddress& addr : vAddr) if (addr.nTime > nCutOff) pfrom->PushAddress(addr); } @@ -5760,7 +6040,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, mempool.queryHashes(vtxid); vector vInv; - BOOST_FOREACH(uint256& hash, vtxid) + for (uint256& hash : vtxid) { CInv inv(MSG_TX, hash); CTransaction tx; @@ -5883,7 +6163,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, pfrom->setKnown.insert(alertHash); { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) alert.RelayTo(pnode); } } @@ -5971,7 +6251,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, { LOCK(pfrom->cs_filter); delete pfrom->pfilter; - pfrom->pfilter = NULL; + pfrom->pfilter = nullptr; //pfrom->pfilter = new CBloomFilter(); pfrom->fRelayTxes = true; } else @@ -6016,9 +6296,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } else { - if (fSecMsgEnabled) - SecureMsgReceiveData(pfrom, strCommand, vRecv); - // Ignore unknown commands for extensibility } @@ -6208,7 +6485,7 @@ bool SendMessages(CNode* pto, std::vector &vNodesCopy, bool fSendTrickle static int64_t nLastRebroadcast; if (!IsInitialBlockDownload() && (GetTime() - nLastRebroadcast > 24 * 60 * 60)) { - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { // Periodically clear setAddrKnown to allow refresh broadcasts if (nLastRebroadcast) @@ -6232,7 +6509,7 @@ bool SendMessages(CNode* pto, std::vector &vNodesCopy, bool fSendTrickle { vector vAddr; vAddr.reserve(pto->vAddrToSend.size()); - BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend) + for (const CAddress& addr : pto->vAddrToSend) { // returns true if wasn't already contained in the set if (pto->setAddrKnown.insert(addr).second) @@ -6262,7 +6539,7 @@ bool SendMessages(CNode* pto, std::vector &vNodesCopy, bool fSendTrickle LOCK2(pwalletMain->cs_wallet, pto->cs_inventory); vInv.reserve(pto->vInventoryToSend.size()); vInvWait.reserve(pto->vInventoryToSend.size()); - BOOST_FOREACH(const CInv& inv, pto->vInventoryToSend) + for (const CInv& inv : pto->vInventoryToSend) { if (pto->setInventoryKnown.count(inv)) continue; @@ -6524,10 +6801,6 @@ bool SendMessages(CNode* pto, std::vector &vNodesCopy, bool fSendTrickle nTimeLastMblkRecv = nTimeNow; // reset timeout } - - if (fSecMsgEnabled) - SecureMsgSendData(pto, fSendTrickle); // should be in cs_main? - return true; } diff --git a/src/main.h b/src/main.h index 6690d7e6b5..7a19fb7e1b 100644 --- a/src/main.h +++ b/src/main.h @@ -1,9 +1,17 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_MAIN_H -#define BITCOIN_MAIN_H +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_MAIN_H +#define ALIAS_MAIN_H + +#ifdef _MSC_BUILD +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif #include "core.h" #include "bignum.h" @@ -14,7 +22,15 @@ #include "scrypt.h" #include "state.h" +#include +#include #include +#include +#include +#include +#include +#include +#include class CWallet; class CWalletTx; @@ -24,6 +40,7 @@ class CBlock; class CBlockThin; class CBlockIndex; class CBlockThinIndex; +class CChain; class CKeyItem; class CReserveKey; @@ -44,6 +61,7 @@ static const unsigned int MAX_GETHEADERS_SZ = 2000; static const unsigned int MAX_MULTI_BLOCK_SIZE = 5120000; // 5MiB, most likely to hit MAX_MULTI_BLOCK_ELEMNTS first static const unsigned int MAX_MULTI_BLOCK_ELEMENTS = 64; // processing larger blocks is cpu intensive static const unsigned int MAX_MULTI_BLOCK_THIN_ELEMENTS = 128; +static const unsigned int TARGET_BLOCK_TIME = 96; /** No amount larger than this (in satoshi) is valid */ static const int64_t MAX_MONEY = std::numeric_limits::max(); @@ -57,10 +75,21 @@ inline int64_t FutureDriftV2(int64_t nTime) { return nTime + 15; } inline int64_t FutureDrift(int64_t nTime, int nHeight) { return Params().IsProtocolV2(nHeight) ? FutureDriftV2(nTime) : FutureDriftV1(nTime); } -inline unsigned int GetTargetSpacing(int nHeight) { return Params().IsProtocolV2(nHeight) ? 64 : 60; } +inline unsigned int GetTargetSpacing(int nHeight, int64_t nBlockTime) { return Params().IsProtocolV2(nHeight) ? Params().IsForkV3(nBlockTime) ? TARGET_BLOCK_TIME : 64 : 60; } +inline std::pair GetRingSizeMinMax(int64_t nTime = 0) { + uint32_t nMinRingSize = 1, nMaxRingSize = MAX_RING_SIZE; + if (nTime == 0 || Params().IsForkV3(nTime)) + { + nMinRingSize = MIN_RING_SIZE; + if (nTime == 0 || !fTestNet) // TODO remove with next TESTNET restart + nMaxRingSize = MIN_RING_SIZE; + } + return std::make_pair(nMinRingSize, nMaxRingSize); +} extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; +extern CChain chainActive; extern std::map mapBlockIndex; extern std::map mapBlockThinIndex; extern std::set > setStakeSeen; @@ -91,14 +120,25 @@ extern std::set setpwalletRegistered; struct COrphanBlock { uint256 hashBlock; uint256 hashPrev; + unsigned int nTime; std::pair stake; std::vector vchBlock; }; extern std::map mapOrphanBlocks; +extern std::multimap mapOrphanBlocksByPrev; extern std::map mapOrphanBlockThins; +extern size_t nOrphanBlocksSize; +extern bool fStaleAnonCache; extern std::map mapAnonOutputStats; +struct CAnonBlockStat { + uint16_t nSpends, nOutputs, nStakingOutputs, nCompromisedOutputs; +}; +extern int nMaxAnonBlockCache; +extern std::map> mapAnonBlockStats; + + extern CTxMemPool mempool; @@ -119,20 +159,20 @@ class CTxIndex; void RegisterWallet(CWallet* pwalletIn); void UnregisterWallet(CWallet* pwalletIn); -void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false, bool fConnect = true); +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = nullptr, bool fUpdate = false, bool fConnect = true); bool ProcessBlock(CNode* pfrom, CBlock* pblock, uint256& hash); bool CheckDiskSpace(uint64_t nAdditionalBytes=0); FILE* OpenBlockFile(bool fHeaderFile, unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* AppendBlockFile(bool fHeaderFile, unsigned int& nFileRet, const char* fmode = "ab"); -int LoadBlockIndex(bool fAllowNew=true); +int LoadBlockIndex(bool fAllowNew=true, std::function funcProgress = nullptr); void PrintBlockTree(); CBlockIndex* FindBlockByHeight(int nHeight); CBlockThinIndex* FindBlockThinByHeight(int nHeight); bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, std::vector &vNodesCopy, bool fSendTrickle); -bool LoadExternalBlockFile(int nFile, FILE* fileIn); -void ThreadImport(std::vector vImportFiles); +bool LoadExternalBlockFile(int nFile, FILE* fileIn, std::function funcProgress = nullptr); +void ThreadImport(std::vector vImportFiles); bool CheckProofOfWork(uint256 hash, unsigned int nBits); unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake); @@ -142,7 +182,7 @@ int GetNumBlocksOfPeers(); bool IsInitialBlockDownload(); bool IsConfirmedInNPrevBlocks(const CTxIndex& txindex, const CBlockIndex* pindexFrom, int nMaxDepth, int& nActualDepth); std::string GetWarnings(std::string strFor); -bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool includemempool = false); bool GetTransactionBlockHash(const uint256 &hash, uint256 &hashBlock); bool GetKeyImage(CTxDB* ptxdb, ec_point& keyImage, CKeyImageSpent& keyImageSpent, bool& fInMempool); @@ -167,6 +207,7 @@ bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); /** Get statistics from node state */ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); +bool AddOrphanTx(const CTransaction& tx); /** Position on disk for a particular transaction. */ class CDiskTxPos @@ -286,7 +327,7 @@ class CTransaction nBlockTime = GetAdjustedTime(); if ((int64_t)nLockTime < ((int64_t)nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime)) return true; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) if (!txin.IsFinal()) return false; return true; @@ -333,6 +374,12 @@ class CTransaction return (vin.size() > 0 && (!vin[0].prevout.IsNull()) && vout.size() >= 2 && vout[0].IsEmpty()); } + bool IsAnonCoinStake() const + { + // ppcoin: the coin stake transaction is marked with the first output empty + return nVersion == ANON_TXN_VERSION && IsCoinStake(); + } + /** Check for standard transaction types @return True if all outputs (scriptPubKeys) use only standard transaction forms */ @@ -367,8 +414,7 @@ class CTransaction int64_t GetValueOut() const { int64_t nValueOut = 0; - BOOST_FOREACH(const CTxOut& txout, vout) - { + for (const CTxOut& txout : vout) { nValueOut += txout.nValue; if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); @@ -388,7 +434,7 @@ class CTransaction int64_t GetMinFee(unsigned int nBlockSize=1, enum GetMinFee_mode mode=GMF_BLOCK, unsigned int nBytes = 0) const; - bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) + bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=nullptr) { CAutoFile filein = CAutoFile(OpenBlockFile(false, pos.nFile, 0, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION); if (!filein) @@ -470,6 +516,7 @@ class CTransaction bool FetchInputs(CTxDB& txdb, const std::map& mapTestPool, bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid); + bool CheckAnonInputAB(CTxDB &txdb, const CTxIn &txin, int iVin, int nRingSize, const std::vector &vchImage, int64_t &nCoinValue) const; bool CheckAnonInputs(CTxDB& txdb, int64_t& nSumValue, bool& fInvalid, bool fCheckExists); /** Sanity check previous transactions, then, if all checks succeed, @@ -503,8 +550,11 @@ bool AcceptToMemoryPool(CTxMemPool &pool, CTransaction &tx, CTxDB& txdb, bool *p class CMerkleTx : public CTransaction { private: - int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const; - int GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const; + int GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const { return GetDepthAndHeightInMainChainINTERNAL(pindexRet).first; }; + int GetDepthInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const { return GetDepthAndHeightInMainChainINTERNAL(pindexRet).first; }; + + std::pair GetDepthAndHeightInMainChainINTERNAL(CBlockIndex* &pindexRet) const; + std::pair GetDepthAndHeightInMainChainINTERNAL(CBlockThinIndex* &pindexRet) const; public: uint256 hashBlock; std::vector vMerkleBranch; @@ -542,25 +592,36 @@ class CMerkleTx : public CTransaction ) - int SetMerkleBranch(const CBlock* pblock=NULL); + int SetMerkleBranch(const CBlock* pblock=nullptr); // Return depth of transaction in blockchain: // -1 : not in blockchain, and not in memory pool (conflicted transaction) // 0 : in memory pool, waiting to be included in a block // >=1 : this many blocks deep in the main chain - int GetDepthInMainChain(CBlockIndex* &pindexRet) const; - int GetDepthInMainChain(CBlockThinIndex* &pindexRet) const; - int GetDepthInMainChain() const + int GetDepthInMainChain(CBlockIndex* &pindexRet) const { return GetDepthAndHeightInMainChain(pindexRet).first; }; + int GetDepthInMainChain(CBlockThinIndex* &pindexRet) const { return GetDepthAndHeightInMainChain(pindexRet).first; }; + int GetDepthInMainChain() const { return GetDepthAndHeightInMainChain().first; }; + + // Return depth and height of transaction in blockchain as pair. + // first contains the depth: + // -1 : not in blockchain, and not in memory pool (conflicted transaction) + // 0 : in memory pool, waiting to be included in a block + // >=1 : this many blocks deep in the main chain + // seconds contains the height of the block or -1 if the block is not in the blockchain + std::pair GetDepthAndHeightInMainChain(CBlockIndex* &pindexRet) const; + std::pair GetDepthAndHeightInMainChain(CBlockThinIndex* &pindexRet) const; + std::pair GetDepthAndHeightInMainChain() const { if (nNodeMode == NT_FULL) { CBlockIndex *pindexRet; - return GetDepthInMainChain(pindexRet); + return GetDepthAndHeightInMainChain(pindexRet); }; CBlockThinIndex *pindexRet; - return GetDepthInMainChain(pindexRet); + return GetDepthAndHeightInMainChain(pindexRet); } + bool IsInMainChain() const { if (nNodeMode == NT_THIN) @@ -790,6 +851,11 @@ class CBlock : public CBlockHeader return (vtx.size() > 1 && vtx[1].IsCoinStake()); } + bool IsProofOfAnonStake() const + { + return (vtx.size() > 1 && vtx[1].IsAnonCoinStake()); + } + bool IsProofOfWork() const { return !IsProofOfStake(); @@ -804,7 +870,7 @@ class CBlock : public CBlockHeader int64_t GetMaxTransactionTime() const { int64_t maxTransactionTime = 0; - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) maxTransactionTime = std::max(maxTransactionTime, (int64_t)tx.nTime); return maxTransactionTime; } @@ -812,7 +878,7 @@ class CBlock : public CBlockHeader uint256 BuildMerkleTree() const { vMerkleTree.clear(); - BOOST_FOREACH(const CTransaction& tx, vtx) + for (const CTransaction& tx : vtx) vMerkleTree.push_back(tx.GetHash()); int j = 0; for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) @@ -848,7 +914,7 @@ class CBlock : public CBlockHeader { if (nIndex == -1) return 0; - BOOST_FOREACH(const uint256& otherside, vMerkleBranch) + for (const uint256& otherside : vMerkleBranch) { if (nIndex & 1) hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); @@ -951,6 +1017,7 @@ class CBlock : public CBlockHeader bool AcceptBlock(); bool SignBlock(CWallet& keystore, int64_t nFees); bool CheckBlockSignature() const; + bool CheckAnonBlockSignature() const; bool GetHashProof(uint256& hashProof); @@ -1131,47 +1198,53 @@ class CBlockIndex unsigned int nNonce; CBlockIndex() + : phashBlock(nullptr) + , pprev(nullptr) + , pnext(nullptr) + , nFile(0) + , nBlockPos(0) + , nChainTrust(0) + , nHeight(0) + , nMint(0) + , nMoneySupply(0) + , nAnonSupply(0) + , nFlags(0) + , nStakeModifier(0) + , bnStakeModifierV2(0) + , prevoutStake() + , nStakeTime(0) + , hashProof(0) + , nVersion(0) + , hashMerkleRoot(0) + , nTime(0) + , nBits(0) + , nNonce(0) { - phashBlock = NULL; - pprev = NULL; - pnext = NULL; - nFile = 0; - nBlockPos = 0; - nHeight = 0; - nChainTrust = 0; - nMint = 0; - nMoneySupply = 0; - nAnonSupply = 0; - nFlags = 0; - nStakeModifier = 0; - bnStakeModifierV2 = 0; - hashProof = 0; - prevoutStake.SetNull(); - nStakeTime = 0; - - nVersion = 0; - hashMerkleRoot = 0; - nTime = 0; - nBits = 0; - nNonce = 0; } CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block) + : phashBlock(nullptr) + , pprev(nullptr) + , pnext(nullptr) + , nFile(nFileIn) + , nBlockPos(nBlockPosIn) + , nChainTrust(0) + , nHeight(0) + , nMint(0) + , nMoneySupply(0) + , nAnonSupply(0) + , nFlags(0) + , nStakeModifier(0) + , bnStakeModifierV2(0) + , prevoutStake() + , nStakeTime(0) + , hashProof(0) + , nVersion(block.nVersion) + , hashMerkleRoot(block.hashMerkleRoot) + , nTime(block.nTime) + , nBits(block.nBits) + , nNonce(block.nNonce) { - phashBlock = NULL; - pprev = NULL; - pnext = NULL; - nFile = nFileIn; - nBlockPos = nBlockPosIn; - nHeight = 0; - nChainTrust = 0; - nMint = 0; - nMoneySupply = 0; - nAnonSupply = 0; - nFlags = 0; - nStakeModifier = 0; - bnStakeModifierV2 = 0; - hashProof = 0; if (block.IsProofOfStake()) { SetProofOfStake(); @@ -1181,14 +1254,7 @@ class CBlockIndex else { prevoutStake.SetNull(); - nStakeTime = 0; } - - nVersion = block.nVersion; - hashMerkleRoot = block.hashMerkleRoot; - nTime = block.nTime; - nBits = block.nBits; - nNonce = block.nNonce; } CBlock GetBlockHeader() const @@ -1354,50 +1420,42 @@ class CBlockThinIndex : public CBlockThin uint256 hashProof; CBlockThinIndex() + : phashBlock(nullptr) + , pprev(nullptr) + , pnext(nullptr) + , nFile(0) + , nBlockPos(0) + , nHeight(0) + , nChainTrust(0) + , nStakeModifier(0) + , hashProof(0) + , nVersion(0) + , hashMerkleRoot(0) + , nTime(0) + , nBits(0) + , nNonce(0) + , nFlags(0) { - phashBlock = NULL; - pprev = NULL; - pnext = NULL; - nFile = 0; - nBlockPos = 0; - nHeight = 0; - - nChainTrust = 0; - nStakeModifier = 0; - - hashProof = 0; - - - - nVersion = 0; - hashMerkleRoot = 0; - nTime = 0; - nBits = 0; - nNonce = 0; - nFlags = 0; - nStakeModifier = 0; } CBlockThinIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlockThin& block) + : phashBlock(nullptr) + , pprev(nullptr) + , pnext(nullptr) + , nFile(nFileIn) + , nBlockPos(nBlockPosIn) + , nHeight(0) + , nChainTrust(0) + , nStakeModifier(0) + , hashProof(0) + , nVersion(block.nVersion) + , hashMerkleRoot(block.hashMerkleRoot) + , nTime(block.nTime) + , nBits(block.nBits) + , nNonce(block.nNonce) + , nFlags(block.nFlags) { - phashBlock = NULL; - pprev = NULL; - pnext = NULL; - nFile = nFileIn; - nBlockPos = nBlockPosIn; - nHeight = 0; - - hashProof = 0; - - nVersion = block.nVersion; - hashMerkleRoot = block.hashMerkleRoot; - nTime = block.nTime; - nBits = block.nBits; - nNonce = block.nNonce; - - nFlags = block.nFlags; - } CBlockThin GetBlockThin() const @@ -1533,16 +1591,16 @@ class CDiskBlockIndex : public CBlockIndex uint256 hashNext; CDiskBlockIndex() + : hashPrev(0) + , hashNext(0) + , blockHash(0) { - hashPrev = 0; - hashNext = 0; - blockHash = 0; } explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) { - hashPrev = (pprev ? pprev->GetBlockHash() : 0); - hashNext = (pnext ? pnext->GetBlockHash() : 0); + hashPrev = (pprev ? pprev->GetBlockHash() : uint256(0)); + hashNext = (pnext ? pnext->GetBlockHash() : uint256(0)); } IMPLEMENT_SERIALIZE @@ -1626,15 +1684,15 @@ class CDiskBlockThinIndex : public CBlockThinIndex uint256 hashNext; CDiskBlockThinIndex() + : hashPrev(0) + , hashNext(0) { - hashPrev = 0; - hashNext = 0; } explicit CDiskBlockThinIndex(CBlockThinIndex* pindex) : CBlockThinIndex(*pindex) { - hashPrev = (pprev ? pprev->GetBlockHash() : 0); - hashNext = (pnext ? pnext->GetBlockHash() : 0); + hashPrev = (pprev ? pprev->GetBlockHash() : uint256(0)); + hashNext = (pnext ? pnext->GetBlockHash() : uint256(0)); } IMPLEMENT_SERIALIZE @@ -1793,7 +1851,7 @@ class CBlockLocator // Retrace how far back it was in the sender's branch int nDistance = 0; int nStep = 1; - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) @@ -1812,7 +1870,7 @@ class CBlockLocator CBlockIndex* GetBlockIndex() { // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) @@ -1828,7 +1886,7 @@ class CBlockLocator uint256 GetBlockHash() { // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) @@ -1921,7 +1979,7 @@ class CBlockThinLocator // Retrace how far back it was in the sender's branch int nDistance = 0; int nStep = 1; - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockThinIndex.find(hash); if (mi != mapBlockThinIndex.end()) @@ -1940,7 +1998,7 @@ class CBlockThinLocator CBlockThinIndex* GetBlockIndex() { // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockThinIndex.find(hash); if (mi != mapBlockThinIndex.end()) @@ -1956,7 +2014,7 @@ class CBlockThinLocator uint256 GetBlockHash() { // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) + for (const uint256& hash : vHave) { std::map::iterator mi = mapBlockThinIndex.find(hash); if (mi != mapBlockThinIndex.end()) @@ -1978,6 +2036,68 @@ class CBlockThinLocator } }; + +/** An in-memory indexed chain of blocks. */ +class CChain { +private: + std::vector vChain; + +public: + /** Returns the index entry for the genesis block of this chain, or nullptr if none. */ + CBlockIndex *Genesis() const { + return vChain.size() > 0 ? vChain[0] : nullptr; + } + + /** Returns the index entry for the tip of this chain, or nullptr if none. */ + CBlockIndex *Tip() const { + return vChain.size() > 0 ? vChain[vChain.size() - 1] : nullptr; + } + + /** Returns the index entry at a particular height in this chain, or nullptr if no such height exists. */ + CBlockIndex *operator[](int nHeight) const { + if (nHeight < 0 || nHeight >= (int)vChain.size()) + return nullptr; + return vChain[nHeight]; + } + + /** Compare two chains efficiently. */ + friend bool operator==(const CChain &a, const CChain &b) { + return a.vChain.size() == b.vChain.size() && + a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1]; + } + + /** Efficiently check whether a block is present in this chain. */ + bool Contains(const CBlockIndex *pindex) const { + return (*this)[pindex->nHeight] == pindex; + } + + /** Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip. */ + CBlockIndex *Next(const CBlockIndex *pindex) const { + if (Contains(pindex)) + return (*this)[pindex->nHeight + 1]; + else + return nullptr; + } + + /** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */ + int Height() const { + return vChain.size() - 1; + } + + /** Set/initialize a chain with a given tip. */ + void SetTip(CBlockIndex *pindex); + + /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */ + CBlockLocator GetLocator(const CBlockIndex *pindex = nullptr) const; + + /** Find the last common block between this chain and a block index entry. */ + const CBlockIndex *FindFork(const CBlockIndex *pindex) const; + + /** Find the earliest block with timestamp equal or greater than the given. */ + CBlockIndex* FindEarliestAtLeast(int64_t nTime) const; +}; + + /** Data structure that represents a partial merkle tree. * * It respresents a subset of the txid's of a known block, in a way that @@ -2133,4 +2253,4 @@ class CMBlkThinElement ) }; -#endif +#endif // ALIAS_MAIN_H diff --git a/src/makefile.bsd b/src/makefile.bsd deleted file mode 100644 index bf34580f1e..0000000000 --- a/src/makefile.bsd +++ /dev/null @@ -1,192 +0,0 @@ -# Copyright (c) 2009-2010 Satoshi Nakamoto -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -USE_UPNP:=0 - -LINK:=$(CXX) - -DEFS=-DBOOST_SPIRIT_THREADSAFE - -DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH)) -LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) - -LMODE = dynamic -LMODE2 = dynamic -ifdef STATIC - LMODE = static - ifeq (${STATIC}, all) - LMODE2 = static - endif -endif - -# for boost 1.37, add -mt to the boost libraries -LIBS += \ - -Wl,-B$(LMODE) \ - -l boost_system$(BOOST_LIB_SUFFIX) \ - -l boost_filesystem$(BOOST_LIB_SUFFIX) \ - -l boost_program_options$(BOOST_LIB_SUFFIX) \ - -l boost_thread$(BOOST_LIB_SUFFIX) \ - -l db_cxx$(BDB_LIB_SUFFIX) \ - -l ssl \ - -l crypto \ - -l execinfo - -ifndef USE_UPNP - override USE_UPNP = - -endif -ifneq (${USE_UPNP}, -) - LIBS += -l miniupnpc - DEFS += -DUSE_UPNP=$(USE_UPNP) -endif - -LIBS+= \ - -Wl,-B$(LMODE2) \ - -l z \ - -l dl \ - -l pthread - - -# Hardening -# Make some classes of vulnerabilities unexploitable in case one is discovered. -# - # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes - # -fstack-protector-all to be ignored unless -fno-stack-protector is used first. - # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722 - HARDENING=-fno-stack-protector - - # Stack Canaries - # Put numbers at the beginning of each stack frame and check that they are the same. - # If a stack buffer if overflowed, it writes over the canary number and then on return - # when that number is checked, it won't be the same and the program will exit with - # a "Stack smashing detected" error instead of being exploited. - HARDENING+=-fstack-protector-all -Wstack-protector - - # Make some important things such as the global offset table read only as soon as - # the dynamic linker is finished building it. This will prevent overwriting of addresses - # which would later be jumped to. - LDHARDENING+=-Wl,-z,relro -Wl,-z,now - - # Build position independent code to take advantage of Address Space Layout Randomization - # offered by some kernels. - # see doc/build-unix.txt for more information. - ifdef PIE - HARDENING+=-fPIE - LDHARDENING+=-pie - endif - - # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in - # the source such overflowing a statically defined buffer. - HARDENING+=-D_FORTIFY_SOURCE=2 -# - - -DEBUGFLAGS=-g - -# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only -# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work. -xCXXFLAGS=-O0 -msse2 -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \ - $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) - -# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only -# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work. -xLDFLAGS=$(LDHARDENING) $(LDFLAGS) - -OBJS= \ - obj/alert.o \ - obj/version.o \ - obj/checkpoints.o \ - obj/netbase.o \ - obj/addrman.o \ - obj/crypter.o \ - obj/key.o \ - obj/db.o \ - obj/init.o \ - obj/keystore.o \ - obj/main.o \ - obj/miner.o \ - obj/net.o \ - obj/protocol.o \ - obj/bitcoinrpc.o \ - obj/rpcdump.o \ - obj/rpcnet.o \ - obj/rpcmining.o \ - obj/rpcwallet.o \ - obj/rpcblockchain.o \ - obj/rpcrawtransaction.o \ - obj/script.o \ - obj/sync.o \ - obj/util.o \ - obj/wallet.o \ - obj/walletdb.o \ - obj/noui.o \ - obj/kernel.o \ - obj/pbkdf2.o \ - obj/scrypt.o \ - obj/scrypt-arm.o \ - obj/scrypt-x86.o \ - obj/scrypt-x86_64.o \ - obj/zerocoin/Accumulator.o \ - obj/zerocoin/AccumulatorProofOfKnowledge.o \ - obj/zerocoin/Coin.o \ - obj/zerocoin/CoinSpend.o \ - obj/zerocoin/Commitment.o \ - obj/zerocoin/ParamGeneration.o \ - obj/zerocoin/Params.o \ - obj/zerocoin/SerialNumberSignatureOfKnowledge.o \ - obj/zerocoin/SpendMetaData.o \ - obj/zerocoin/ZeroTest.o - -all: shadowcoind - -LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/txdb-leveldb.o -leveldb/libleveldb.a: - @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; -obj/txdb-leveldb.o: leveldb/libleveldb.a - -# auto-generated dependencies: --include obj/*.P - -obj/build.h: FORCE - /bin/sh ../share/genbuild.sh obj/build.h -version.cpp: obj/build.h -DEFS += -DHAVE_BUILD_INFO - -obj/scrypt-x86.o: scrypt-x86.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-x86_64.o: scrypt-x86_64.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-arm.o: scrypt-arm.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/%.o: %.cpp - $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -obj/zerocoin/%.o: zerocoin/%.cpp - $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -shadowcoind: $(OBJS:obj/%=obj/%) - $(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) - -clean: - -rm -f shadowcoind - -rm -f obj/*.o - -rm -f obj/zerocoin/*.o - -rm -f obj/*.P - -rm -f obj/zerocoin/*.P - -rm -f obj/build.h - -FORCE: diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw deleted file mode 100644 index c86a12ae11..0000000000 --- a/src/makefile.linux-mingw +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (c) 2009-2010 Satoshi Nakamoto -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#TARGET_PLATFORM:=i686 -#TARGET_PLATFORM:=x86_64 - -HOSTDEPSDIR:=/usr/$(HOST) -CC:=$(HOST)-gcc -CXX:=$(HOST)-g++ -RANLIB=$(HOST)-ranlib -STRIP=$(HOST)-strip - -USE_UPNP:=1 - -INCLUDEPATHS= \ - -I"$(CURDIR)" \ - -I"$(CURDIR)"/obj \ - -I"$(HOSTDEPSDIR)/include" \ - -I"$(HOSTDEPSDIR)" \ - -I"$(DEPSDIR)/include" \ - -I"$(DEPSDIR)" - -LIBPATHS= \ - -L"$(HOSTDEPSDIR)" \ - -L"$(HOSTDEPSDIR)/lib" \ - -L"$(DEPSDIR)/lib" \ - -L"$(DEPSDIR)" - -LIBS= \ - -l boost_system-mt-s \ - -l boost_filesystem-mt-s \ - -l boost_program_options-mt-s \ - -l boost_thread_win32-mt-s \ - -l boost_chrono-mt-s \ - -l db_cxx \ - -l ssl \ - -l crypto \ - -l z - -DEFS=-D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE -DEBUGFLAGS=-g -CFLAGS=-O3 -msse2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) -LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -static -static-libgcc -static-libstdc++ - -ifndef USE_UPNP - override USE_UPNP = - -endif -ifneq (${USE_UPNP}, -) - LIBPATHS += -L"$(DEPSDIR)/miniupnpc" - LIBS += -l miniupnpc -l iphlpapi - DEFS += -DMINIUPNP_STATICLIB -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) -endif - -LIBS += -l mingwthrd -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi - -# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are -HEADERS = $(wildcard *.h) - -OBJS= \ - obj/alert.o \ - obj/version.o \ - obj/checkpoints.o \ - obj/netbase.o \ - obj/addrman.o \ - obj/crypter.o \ - obj/key.o \ - obj/eckey.o \ - obj/extkey.o \ - obj/db.o \ - obj/init.o \ - obj/shadowcoind.o \ - obj/keystore.o \ - obj/miner.o \ - obj/main.o \ - obj/net.o \ - obj/protocol.o \ - obj/rpcprotocol.o \ - obj/rpcserver.o \ - obj/rpcclient.o \ - obj/rpcdump.o \ - obj/rpcnet.o \ - obj/rpcmining.o \ - obj/rpcwallet.o \ - obj/rpcblockchain.o \ - obj/rpcrawtransaction.o \ - obj/rpcsmessage.o \ - obj/rpcextkey.o \ - obj/rpcmnemonic.o \ - obj/script.o \ - obj/sync.o \ - obj/util.o \ - obj/hash.o \ - obj/wallet.o \ - obj/walletdb.o \ - obj/noui.o \ - obj/kernel.o \ - obj/pbkdf2.o \ - obj/scrypt.o \ - obj/scrypt-arm.o \ - obj/scrypt-x86.o \ - obj/scrypt-x86_64.o \ - obj/smessage.o \ - obj/stealth.o \ - obj/ringsig.o \ - obj/core.o \ - obj/txmempool.o \ - obj/chainparams.o \ - obj/state.o \ - obj/bloom.o - -all: shadowcoind.exe - -LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += -I"$(CURDIR)/leveldb/include" -DEFS += -I"$(CURDIR)/leveldb/helpers" -OBJS += obj/txdb-leveldb.o -leveldb/libleveldb.a: - @echo "Building LevelDB ..." && cd leveldb && CC=$(CC) CXX=$(CXX) TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" $(MAKE) libleveldb.a libmemenv.a && $(RANLIB) libleveldb.a && $(RANLIB) libmemenv.a && cd .. -obj/txdb-leveldb.o: leveldb/libleveldb.a - -obj/build.h: FORCE - /bin/sh ../share/genbuild.sh obj/build.h -version.cpp: obj/build.h -DEFS += -DHAVE_BUILD_INFO - -obj/%.o: %.cpp $(HEADERS) - $(CXX) -c $(CFLAGS) -o $@ $< - -obj/scrypt-x86.o: scrypt-x86.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-x86_64.o: scrypt-x86_64.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-arm.o: scrypt-arm.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -shadowcoind.exe: $(OBJS:obj/%=obj/%) - $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lshlwapi - $(STRIP) shadowcoind.exe - -clean: - -rm -f obj/*.o - -rm -f obj/zerocoin/*.o - -rm -f shadowcoind.exe - -rm -f obj/build.h - cd leveldb && TARGET_OS=OS_WINDOWS_CROSSCOMPILE $(MAKE) clean && cd .. - -FORCE: diff --git a/src/makefile.mingw b/src/makefile.mingw deleted file mode 100644 index 339d2a7dea..0000000000 --- a/src/makefile.mingw +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright (c) 2009-2010 Satoshi Nakamoto -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -USE_UPNP:=1 -USE_WALLET:=1 - -INCLUDEPATHS= \ - -I"C:\Develop\deps\boost_1_59_0" \ - -I"C:\Develop\deps\db-4.8.30.NC\build_unix" \ - -I"C:\Develop\deps\openssl-1.0.2d\include" \ - -I"$(abspath obj)" - -TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) - -LIBPATHS= \ - -L"C:\Develop\deps\boost_1_59_0\bin.v2\libs" \ - -L"C:\Develop\deps\db-4.8.30.NC\build_unix" \ - -L"C:\Develop\deps\openssl-1.0.2d\lib" \ - -LIBS= \ - -l boost_system-mgw49-mt-s-1_59 \ - -l boost_filesystem-mgw49-mt-s-1_59 \ - -l boost_program_options-mgw49-mt-s-1_59 \ - -l boost_thread-mgw49-mt-s-1_59 \ - -l boost_chrono-mgw49-mt-s-1_59 \ - -l db_cxx \ - -l ssl \ - -l crypto \ - -l z - -DEFS=-DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -DBOOST_SPIRIT_THREADSAFE -DEBUGFLAGS=-g -CFLAGS=-mthreads -O3 -msse2 -w -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) -LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -static -static-libgcc -static-libstdc++ - -TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) - -ifndef USE_UPNP - override USE_UPNP = - -endif -ifneq (${USE_UPNP}, -) - INCLUDEPATHS += -I"C:\Develop\deps\miniupnpc-1.9\include" - LIBPATHS += -L"C:\Develop\deps\miniupnpc-1.9\lib" - LIBS += -l miniupnpc -l iphlpapi - DEFS += -DMINIUPNP_STATICLIB -DSTATICLIB -DUSE_UPNP=$(USE_UPNP) -endif - -LIBS += -l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l mswsock -l shlwapi -# Hardening -# Make some classes of vulnerabilities unexploitable in case one is discovered. -# - # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes - # -fstack-protector-all to be ignored unless -fno-stack-protector is used first. - # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722 - HARDENING=-fno-stack-protector - - # Stack Canaries - # Put numbers at the beginning of each stack frame and check that they are the same. - # If a stack buffer if overflowed, it writes over the canary number and then on return - # when that number is checked, it won't be the same and the program will exit with - # a "Stack smashing detected" error instead of being exploited. - HARDENING+=-fstack-protector-all -Wstack-protector - - # Make some important things such as the global offset table read only as soon as - # the dynamic linker is finished building it. This will prevent overwriting of addresses - # which would later be jumped to. - LDHARDENING+=-Wl,-z,relro -Wl,-z,now - - # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in - # the source such overflowing a statically defined buffer. - HARDENING+=-D_FORTIFY_SOURCE=2 -# -DEBUGFLAGS=-g - -# TODO: make the mingw builds smarter about dependencies, like the linux/osx builds are -HEADERS = $(wildcard *.h) - -OBJS= \ - obj/alert.o \ - obj/version.o \ - obj/checkpoints.o \ - obj/netbase.o \ - obj/addrman.o \ - obj/crypter.o \ - obj/key.o \ - obj/eckey.o \ - obj/extkey.o \ - obj/db.o \ - obj/init.o \ - obj/shadowcoind.o \ - obj/keystore.o \ - obj/miner.o \ - obj/main.o \ - obj/net.o \ - obj/protocol.o \ - obj/rpcprotocol.o \ - obj/rpcserver.o \ - obj/rpcclient.o \ - obj/rpcdump.o \ - obj/rpcnet.o \ - obj/rpcmining.o \ - obj/rpcwallet.o \ - obj/rpcblockchain.o \ - obj/rpcrawtransaction.o \ - obj/rpcsmessage.o \ - obj/rpcextkey.o \ - obj/rpcmnemonic.o \ - obj/script.o \ - obj/sync.o \ - obj/util.o \ - obj/hash.o \ - obj/wallet.o \ - obj/walletdb.o \ - obj/noui.o \ - obj/kernel.o \ - obj/pbkdf2.o \ - obj/scrypt.o \ - obj/scrypt-arm.o \ - obj/scrypt-x86.o \ - obj/scrypt-x86_64.o \ - obj/smessage.o \ - obj/stealth.o \ - obj/ringsig.o \ - obj/core.o \ - obj/txmempool.o \ - obj/chainparams.o \ - obj/state.o \ - obj/bloom.o - -all: shadowcoind.exe - -test check: test_shadow FORCE - ./test_shadow - -LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/txdb-leveldb.o -leveldb/libleveldb.a: - @echo "Building LevelDB ..." && cd leveldb TARGET_OS=NATIVE_WINDOWS make libleveldb.a libmemenv.a cd .. -obj/txdb-leveldb.o: leveldb/libleveldb.a - -obj/build.h: FORCE - sh ../share/genbuild.sh obj/build.h - -version.cpp: obj/build.h -DEFS += -DHAVE_BUILD_INFO - -obj/%.o: %.cpp $(HEADERS) - $(CXX) -c $(CFLAGS) -o $@ $< - -shadowcoind.exe: $(OBJS:obj/%=obj/%) - $(CXX) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS) -lshlwapi - strip shadowcoind.exe - -obj/scrypt-x86.o: scrypt-x86.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-x86_64.o: scrypt-x86_64.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-arm.o: scrypt-arm.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) - -xTESTCXXFLAGS = -std=c++11 - -obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(xTESTCXXFLAGS) $(xCXXFLAGS) $(CFLAGS) $(LDFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -test_shadow.exe: $(TESTOBJS) $(filter-out obj/init.o obj/shadowcoind.o,$(OBJS:obj/%=obj/%)) - $(LINK) $(xCXXFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(LIBPATHS) $^ $(TESTLIBS) $(xLDFLAGS) $(LIBS) - -clean: - -rm -f obj/*.o - -rm -f shadowcoind.exe - -rm -f obj/build.h - cd leveldb && TARGET_OS=NATIVE_WINDOWS $(MAKE) clean && cd .. - -rm -f test_shadow.exe - -rm -f obj-test/*.o - -rm -f obj-test/*.P - -FORCE: diff --git a/src/makefile.osx b/src/makefile.osx deleted file mode 100644 index 9df411e932..0000000000 --- a/src/makefile.osx +++ /dev/null @@ -1,166 +0,0 @@ -# -*- mode: Makefile; -*- -# Copyright (c) 2011 Bitcoin Developers -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Mac OS X makefile for shadowcoin -# Originally by Laszlo Hanyecz (solar@heliacal.net) -USE_UPNP:=0 -CXX=llvm-g++ -DEPSDIR=/usr/local/Cellar - -INCLUDEPATHS= \ - -I"$(CURDIR)" \ - -I"$(CURDIR)"/obj \ - -I"$(DEPSDIR)/include" \ - -I"$(DEPSDIR)/include/db48" - -LIBPATHS= \ - -L"$(DEPSDIR)/lib" \ - -L"$(DEPSDIR)/lib/db48" - -USE_UPNP:=1 - -LIBS= -dead_strip - -LIBS += \ - -ldb_cxx-4.8 \ - -lboost_system-mt \ - -lboost_filesystem-mt \ - -lboost_program_options-mt \ - -lboost_thread-mt \ - -lssl \ - -lcrypto - - -DEFS=-DMAC_OSX -DMSG_NOSIGNAL=0 -DBOOST_SPIRIT_THREADSAFE - -ifdef RELEASE -# Compile for maximum compatibility and smallest size. -# This requires that dependencies are compiled -# the same way. -CFLAGS = -arch x86_64 -stdlib=libc++ -else -CFLAGS = -arch x86_64 -stdlib=libc++ -g -msse2 -endif - -# ppc doesn't work because we don't support big-endian -CFLAGS += -Wall -Wextra -Wformat -Wno-ignored-qualifiers -Wformat-security -Wno-unused-parameter \ - $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS) -OBJS= \ - obj/alert.o \ - obj/version.o \ - obj/checkpoints.o \ - obj/netbase.o \ - obj/addrman.o \ - obj/crypter.o \ - obj/key.o \ - obj/eckey.o \ - obj/extkey.o \ - obj/db.o \ - obj/init.o \ - obj/shadowcoind.o \ - obj/keystore.o \ - obj/miner.o \ - obj/main.o \ - obj/net.o \ - obj/protocol.o \ - obj/rpcprotocol.o \ - obj/rpcserver.o \ - obj/rpcclient.o \ - obj/rpcdump.o \ - obj/rpcnet.o \ - obj/rpcmining.o \ - obj/rpcwallet.o \ - obj/rpcblockchain.o \ - obj/rpcrawtransaction.o \ - obj/rpcsmessage.o \ - obj/rpcextkey.o \ - obj/rpcmnemonic.o \ - obj/script.o \ - obj/sync.o \ - obj/util.o \ - obj/hash.o \ - obj/wallet.o \ - obj/walletdb.o \ - obj/noui.o \ - obj/kernel.o \ - obj/pbkdf2.o \ - obj/scrypt.o \ - obj/scrypt-arm.o \ - obj/scrypt-x86.o \ - obj/scrypt-x86_64.o \ - obj/smessage.o \ - obj/stealth.o \ - obj/ringsig.o \ - obj/core.o \ - obj/txmempool.o \ - obj/chainparams.o \ - obj/state.o \ - obj/bloom.o - - - -all: shadowcoind - -test check: test_shadow FORCE - ./test_shadow -LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/txdb-leveldb.o -leveldb/libleveldb.a: - @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; -obj/txdb-leveldb.o: leveldb/libleveldb.a - -# auto-generated dependencies: --include obj/*.P - -obj/build.h: FORCE - /bin/sh ../share/genbuild.sh obj/build.h -version.cpp: obj/build.h -DEFS += -DHAVE_BUILD_INFO -obj/scrypt-x86.o: scrypt-x86.S - $(CXX) -c $(CFLAGS) -MMD -o $@ $< -obj/scrypt-x86_64.o: scrypt-x86_64.S - $(CXX) -c $(CFLAGS) -MMD -o $@ $< -obj/scrypt-arm.o: scrypt-arm.S - $(CXX) -c $(CFLAGS) -MMD -o $@ $< - -obj/%.o: %.cpp - $(CXX) -c $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -shadowcoind: $(OBJS:obj/%=obj/%) - $(LINK) $(CFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) - - -TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) - -xTESTCXXFLAGS = -std=c++11 - -obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(xTESTCXXFLAGS) $(CFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -test_shadow: $(TESTOBJS) $(filter-out obj/init.o obj/shadowcoind.o,$(OBJS:obj/%=obj/%)) - $(LINK) $(CFLAGS) -o $@ $(LIBPATHS) $^ $(TESTLIBS) $(xLDFLAGS) $(LIBS) - -clean: - -rm -f shadowcoind - -rm -f obj/*.o - -rm -f obj/*.P - -rm -f obj/build.h - -rm -f test_shadow - -rm -f obj-test/*.o - -rm -f obj-test/*.P - -cd leveldb && $(MAKE) clean || true - - -FORCE: \ No newline at end of file diff --git a/src/makefile.unix b/src/makefile.unix deleted file mode 100644 index 4364c46380..0000000000 --- a/src/makefile.unix +++ /dev/null @@ -1,229 +0,0 @@ -# Copyright (c) 2009-2010 Satoshi Nakamoto -# Distributed under the MIT/X11 software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -USE_UPNP:=0 - -LINK:=$(CXX) -ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') - -DEFS=-DBOOST_SPIRIT_THREADSAFE - -DEFS += $(addprefix -I,$(CURDIR) $(CURDIR)/obj $(BOOST_INCLUDE_PATH) $(BDB_INCLUDE_PATH) $(OPENSSL_INCLUDE_PATH)) -LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH)) - - -TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data) - -LMODE = dynamic -LMODE2 = dynamic -ifdef STATIC - LMODE = static - ifeq (${STATIC}, all) - LMODE2 = static - endif -else - TESTDEFS += -DBOOST_TEST_DYN_LINK -endif - - -# for boost 1.37, add -mt to the boost libraries -LIBS += \ - -Wl,-B$(LMODE) \ - -l boost_system$(BOOST_LIB_SUFFIX) \ - -l boost_filesystem$(BOOST_LIB_SUFFIX) \ - -l boost_program_options$(BOOST_LIB_SUFFIX) \ - -l boost_thread$(BOOST_LIB_SUFFIX) \ - -l db_cxx$(BDB_LIB_SUFFIX) \ - -l ssl \ - -l crypto - -ifndef USE_UPNP - override USE_UPNP = - -endif -ifneq (${USE_UPNP}, -) - LIBS += -l miniupnpc - DEFS += -DUSE_UPNP=$(USE_UPNP) -endif - -LIBS+= \ - -Wl,-B$(LMODE2) \ - -l z \ - -l dl \ - -l pthread - -TESTLIBS += \ - -Wl,-B$(LMODE) \ - -l boost_unit_test_framework$(BOOST_LIB_SUFFIX) - -# Hardening -# Make some classes of vulnerabilities unexploitable in case one is discovered. -# - # This is a workaround for Ubuntu bug #691722, the default -fstack-protector causes - # -fstack-protector-all to be ignored unless -fno-stack-protector is used first. - # see: https://bugs.launchpad.net/ubuntu/+source/gcc-4.5/+bug/691722 - HARDENING=-fno-stack-protector - - # Stack Canaries - # Put numbers at the beginning of each stack frame and check that they are the same. - # If a stack buffer if overflowed, it writes over the canary number and then on return - # when that number is checked, it won't be the same and the program will exit with - # a "Stack smashing detected" error instead of being exploited. - HARDENING+=-fstack-protector-all -Wstack-protector - - # Make some important things such as the global offset table read only as soon as - # the dynamic linker is finished building it. This will prevent overwriting of addresses - # which would later be jumped to. - LDHARDENING+=-Wl,-z,relro -Wl,-z,now - - # Build position independent code to take advantage of Address Space Layout Randomization - # offered by some kernels. - # see doc/build-unix.txt for more information. - ifdef PIE - HARDENING+=-fPIE - LDHARDENING+=-pie - endif - - # -D_FORTIFY_SOURCE=2 does some checking for potentially exploitable code patterns in - # the source such overflowing a statically defined buffer. - HARDENING+=-D_FORTIFY_SOURCE=2 -# - - -DEBUGFLAGS=-g - - -ifeq (${ARCH}, i686) - EXT_OPTIONS=-msse2 -endif - - -# CXXFLAGS can be specified on the make command line, so we use xCXXFLAGS that only -# adds some defaults in front. Unfortunately, CXXFLAGS=... $(CXXFLAGS) does not work. -xCXXFLAGS=-O2 $(EXT_OPTIONS) -pthread -Wall -Wextra -Wno-ignored-qualifiers -Wformat -Wformat-security -Wno-unused-parameter \ - $(DEBUGFLAGS) $(DEFS) $(HARDENING) $(CXXFLAGS) - -# LDFLAGS can be specified on the make command line, so we use xLDFLAGS that only -# adds some defaults in front. Unfortunately, LDFLAGS=... $(LDFLAGS) does not work. -xLDFLAGS=$(LDHARDENING) $(LDFLAGS) - -OBJS= \ - obj/alert.o \ - obj/version.o \ - obj/checkpoints.o \ - obj/netbase.o \ - obj/addrman.o \ - obj/crypter.o \ - obj/key.o \ - obj/eckey.o \ - obj/extkey.o \ - obj/db.o \ - obj/init.o \ - obj/shadowcoind.o \ - obj/keystore.o \ - obj/miner.o \ - obj/main.o \ - obj/net.o \ - obj/protocol.o \ - obj/rpcprotocol.o \ - obj/rpcserver.o \ - obj/rpcclient.o \ - obj/rpcdump.o \ - obj/rpcnet.o \ - obj/rpcmining.o \ - obj/rpcwallet.o \ - obj/rpcblockchain.o \ - obj/rpcrawtransaction.o \ - obj/rpcsmessage.o \ - obj/rpcextkey.o \ - obj/rpcmnemonic.o \ - obj/script.o \ - obj/sync.o \ - obj/util.o \ - obj/hash.o \ - obj/wallet.o \ - obj/walletdb.o \ - obj/noui.o \ - obj/kernel.o \ - obj/pbkdf2.o \ - obj/scrypt.o \ - obj/scrypt-arm.o \ - obj/scrypt-x86.o \ - obj/scrypt-x86_64.o \ - obj/smessage.o \ - obj/stealth.o \ - obj/ringsig.o \ - obj/core.o \ - obj/txmempool.o \ - obj/chainparams.o \ - obj/state.o \ - obj/bloom.o - - -all: shadowcoind - -test check: test_shadow FORCE - ./test_shadow - -LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/txdb-leveldb.o -leveldb/libleveldb.a: - @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; -obj/txdb-leveldb.o: leveldb/libleveldb.a - - -# auto-generated dependencies: --include obj/*.P - -obj/build.h: FORCE - /bin/sh ../share/genbuild.sh obj/build.h -version.cpp: obj/build.h -DEFS += -DHAVE_BUILD_INFO - -obj/scrypt-x86.o: scrypt-x86.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-x86_64.o: scrypt-x86_64.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/scrypt-arm.o: scrypt-arm.S - $(CXX) -c $(xCXXFLAGS) -MMD -o $@ $< - -obj/%.o: %.cpp - $(CXX) -c $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -shadowcoind: $(OBJS:obj/%=obj/%) - $(LINK) $(xCXXFLAGS) -o $@ $^ $(xLDFLAGS) $(LIBS) - - -TESTOBJS := $(patsubst test/%.cpp,obj-test/%.o,$(wildcard test/*.cpp)) - -xTESTCXXFLAGS = -std=c++11 - -obj-test/%.o: test/%.cpp - $(CXX) -c $(TESTDEFS) $(xTESTCXXFLAGS) $(xCXXFLAGS) -MMD -MF $(@:%.o=%.d) -o $@ $< - @cp $(@:%.o=%.d) $(@:%.o=%.P); \ - sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ - -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ - rm -f $(@:%.o=%.d) - -test_shadow: $(TESTOBJS) $(filter-out obj/init.o obj/shadowcoind.o,$(OBJS:obj/%=obj/%)) - $(LINK) $(xCXXFLAGS) -o $@ $(LIBPATHS) $^ $(TESTLIBS) $(xLDFLAGS) $(LIBS) - -clean: - -rm -f shadowcoind - -rm -f obj/*.o - -rm -f obj/*.P - -rm -f obj/build.h - -rm -f test_shadow - -rm -f obj-test/*.o - -rm -f obj-test/*.P - -cd leveldb && $(MAKE) clean || true - -FORCE: diff --git a/src/miner.cpp b/src/miner.cpp index b47f37e601..5a43e0b90a 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,14 +1,18 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Copyright (c) 2013 The NovaCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "txdb.h" #include "miner.h" #include "kernel.h" #include "core.h" - +#include "coincontrol.h" +#include using namespace std; @@ -64,25 +68,26 @@ class COrphan int64_t nFee; COrphan(CTransaction* ptxIn) + : ptx(ptxIn) + , dPriority(0) + , dFeePerKb(0) + , nFee(0) { - ptx = ptxIn; - dPriority = dFeePerKb = 0; - nFee = 0; } COrphan(double dPriority_, double dFeePerKb_, int64_t nFee_, CTransaction* ptxIn) + : ptx(ptxIn) + , dPriority(dPriority_) + , dFeePerKb(dFeePerKb_) + , nFee(nFee_) { - dPriority = dPriority_; - dFeePerKb = dFeePerKb_; - nFee = nFee_; - ptx = ptxIn; } void print() const { LogPrintf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n", ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb); - BOOST_FOREACH(uint256 hash, setDependsOn) + for (const uint256& hash : setDependsOn) LogPrintf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str()); } }; @@ -118,10 +123,12 @@ class TxPriorityCompare // CreateNewBlock: create new block (without proof-of-work/proof-of-stake) CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) { + int64_t nStart = GetTimeMicros(); + // Create new block - auto_ptr pblock(new CBlock()); + unique_ptr pblock(new CBlock()); if (!pblock.get()) - return NULL; + return nullptr; CBlockIndex* pindexPrev = pindexBest; @@ -170,18 +177,17 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) // This vector will be sorted into a priority queue: vector vecPriority; vecPriority.reserve(mempool.mapTx.size()); - for (map::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) + for (auto& pair : mempool.mapTx) { - CTransaction& tx = (*mi).second; + CTransaction& tx = pair.second; if (tx.IsCoinBase() || tx.IsCoinStake() || !tx.IsFinal()) continue; - COrphan* porphan = NULL; + COrphan* porphan = nullptr; double dPriority = 0; int64_t nTotalIn = 0; bool fMissingInputs = false; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { + for (const CTxIn& txin : tx.vin) { if (tx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) // anon inputs are verified later in CheckAnonInputs() continue; @@ -230,14 +236,13 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) { int64_t nSumAnon; bool fInvalid; + if (!tx.CheckAnonInputs(txdb, nSumAnon, fInvalid, false)) { if (fInvalid) LogPrintf("CreateNewBlock() : CheckAnonInputs found invalid tx %s\n", tx.GetHash().ToString().substr(0,10).c_str()); - fMissingInputs = true; continue; }; - nTotalIn += nSumAnon; }; @@ -260,7 +265,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) porphan->dFeePerKb = dFeePerKb; } else { - vecPriority.push_back(TxPriority(dPriority, dFeePerKb, nFee, &(*mi).second)); + vecPriority.push_back(TxPriority(dPriority, dFeePerKb, nFee, &pair.second)); }; }; @@ -300,7 +305,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) continue; // Transaction fee - int64_t nMinFee = tx.GetMinFee(nBlockSize, GMF_BLOCK); // will get GMF_ANON if tx.nVersion == ANON_TXN_VERSION + int64_t nMinFee = tx.GetMinFee(nBlockSize, GMF_BLOCK); // Skip free transactions if we're past the minimum block size: if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) @@ -383,7 +388,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) uint256 hash = tx.GetHash(); if (mapDependers.count(hash)) { - BOOST_FOREACH(COrphan* porphan, mapDependers[hash]) + for (COrphan* porphan : mapDependers[hash]) { if (!porphan->setDependsOn.empty()) { @@ -418,6 +423,9 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) pblock->nNonce = 0; } + if (fDebugPoS) + LogPrintf("CreateNewBlock() : created block at height: %d, txs: %d, size: %d bytes in %d µs.\n", nBestHeight, pblock->vtx.size(), nLastBlockSize, GetTimeMicros() - nStart); + return pblock.release(); } @@ -520,7 +528,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) } // Process this block the same as if we had received it from another node - if (!ProcessBlock(NULL, pblock, hashBlock)) + if (!ProcessBlock(nullptr, pblock, hashBlock)) return error("CheckWork() : ProcessBlock, block not accepted"); } @@ -543,9 +551,12 @@ bool CheckStake(CBlock* pblock, CWallet& wallet) return error("CheckStake() : proof-of-stake checking failed"); //// debug print - LogPrintf("CheckStake() : new proof-of-stake block found \n hash: %s \nproofhash: %s \ntarget: %s\n", hashBlock.GetHex().c_str(), proofHash.GetHex().c_str(), hashTarget.GetHex().c_str()); + LogPrintf("CheckStake() : new %s block found \n hash: %s \nproofhash: %s \ntarget: %s\n", + pblock->IsProofOfAnonStake() ? "proof-of-anon-stake" : "proof-of-stake", hashBlock.GetHex().c_str(), proofHash.GetHex().c_str(), hashTarget.GetHex().c_str()); pblock->print(); - LogPrintf("out %s\n", FormatMoney(pblock->vtx[1].GetValueOut()).c_str()); + + int64_t vout = pblock->vtx[1].GetValueOut(); + LogPrintf("out %s\n", FormatMoney(vout).c_str()); // Found a solution { @@ -560,8 +571,12 @@ bool CheckStake(CBlock* pblock, CWallet& wallet) } // Process this block the same as if we had received it from another node - if (!ProcessBlock(NULL, pblock, hashBlock)) + if (ProcessBlock(nullptr, pblock, hashBlock)) { + // Successful stake + } + else { return error("CheckStake() : ProcessBlock, block not accepted"); + } } return true; @@ -578,7 +593,7 @@ void ThreadStakeMiner(CWallet *pwallet) { boost::this_thread::interruption_point(); - while (pwallet->IsLocked()) + while (pwallet->IsLocked() || !fIsStakingEnabled) { fIsStaking = false; MilliSleep(2000); @@ -630,7 +645,7 @@ void ThreadStakeMiner(CWallet *pwallet) // Create new block // int64_t nFees; - auto_ptr pblock(CreateNewBlock(pwallet, true, &nFees)); + unique_ptr pblock(CreateNewBlock(pwallet, true, &nFees)); if (!pblock.get()) return; diff --git a/src/miner.h b/src/miner.h index 21e6baaf7d..29c23cb415 100644 --- a/src/miner.h +++ b/src/miner.h @@ -1,8 +1,12 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Copyright (c) 2013 The NovaCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef NOVACOIN_MINER_H #define NOVACOIN_MINER_H @@ -13,7 +17,7 @@ void ThreadStakeMiner(CWallet *pwallet); /* Generate a new block, without valid proof-of-work */ -CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false, int64_t* pFees = 0); +CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false, int64_t* pFees = nullptr); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); diff --git a/src/mruset.h b/src/mruset.h index 3b8c30a887..c55ffd02ae 100644 --- a/src/mruset.h +++ b/src/mruset.h @@ -1,6 +1,10 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_MRUSET_H #define BITCOIN_MRUSET_H diff --git a/src/net.cpp b/src/net.cpp index a4fe3eba43..9bcd1dcd57 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,17 +1,38 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "db.h" #include "net.h" #include "init.h" #include "strlcpy.h" #include "addrman.h" -#include "ui_interface.h" +#include "interface.h" +#include "net_alias.h" +#include "net_node_alias.h" +#include "util/fs.h" + +#include +#include #ifdef WIN32 #include +#include +#elif __APPLE__ +// Tor separate process via boost::process +#include +boost::process::group gTor; +#elif __linux__ +#include +#include // signals +#include // fork() +#include // waitpid() +pid_t tor_process_pid = 0; +bool tor_killed_from_here = false; #endif #ifdef USE_UPNP @@ -26,10 +47,20 @@ using namespace std; using namespace boost; +// Using modern std::filesystem via util/fs.h + +#if !defined(WIN32) && !defined(__APPLE__) && !defined(__linux__) +// Tor embedded +extern "C" { + int tor_main(int argc, char *argv[]); +} +#endif static const int MAX_OUTBOUND_CONNECTIONS = 16; +// Increment this variable when doing change to torrc-defaults on Linux +static const int TORRC_DEFAULTS_REV = 1; -bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); +bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = nullptr, const char *strDest = nullptr, bool fOneShot = false); // @@ -42,8 +73,8 @@ CCriticalSection cs_mapLocalHost; map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; -static CNode* pnodeLocalHost = NULL; -static CNode* pnodeSync = NULL; +static CNode* pnodeLocalHost = nullptr; +static CNode* pnodeSync = nullptr; CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices); uint64_t nLocalHostNonce = 0; static std::vector vhListenSocket; @@ -66,7 +97,7 @@ CCriticalSection cs_setservAddNodeAddresses; vector vAddedNodes; CCriticalSection cs_vAddedNodes; -static CSemaphore *semOutbound = NULL; +static CSemaphore *semOutbound = nullptr; NodeId nLastNodeId = 0; CCriticalSection cs_nLastNodeId; @@ -138,17 +169,21 @@ bool GetLocal(CService& addr, const CNetAddr *paddrPeer) int nBestScore = -1; int nBestReachability = -1; + int nBestTorScore = -1; { LOCK(cs_mapLocalHost); for (map::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) { int nScore = (*it).second.nScore; int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); - if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore)) + // Use helper function for Tor V3 check (alias-wallet already has IsTorV3 method) + int nTorScore = (*it).first.IsTorV3() ? 1 : 0; + if (nReachability > nBestReachability || (nReachability == nBestReachability && (nTorScore > nBestTorScore || (nTorScore == nBestTorScore && nScore > nBestScore)))) { addr = CService((*it).first, (*it).second.nPort); nBestReachability = nReachability; nBestScore = nScore; + nBestTorScore = nTorScore; } } } @@ -242,7 +277,7 @@ bool IsPeerAddrLocalGood(CNode *pnode) void static AdvertizeLocal() { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if (pnode->fSuccessfullyConnected) { @@ -371,31 +406,31 @@ CNode* FindNode(const CNetAddr& ip) { { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if ((CNetAddr)pnode->addr == ip) return (pnode); } - return NULL; + return nullptr; } CNode* FindNode(const std::string& addrName) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if (pnode->addrName == addrName) return (pnode); - return NULL; + return nullptr; } CNode* FindNode(const CService& addr) { { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if ((CService)pnode->addr == addr) return (pnode); } - return NULL; + return nullptr; } CNode* ConnectNode(CAddress addrConnect, const char *pszDest) @@ -406,10 +441,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) // don't want to lock cs_vNodes as ConnectSocket may be slow LOCK(cs_connectNode); - if (pszDest == NULL) { + if (pszDest == nullptr) { if (IsLocal(addrConnect)) - return NULL; + return nullptr; // Look for an existing connection CNode* pnode = FindNode((CService)addrConnect); @@ -463,7 +498,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) addrman.Attempt(addrConnect); } - return NULL; + return nullptr; } void CNode::CloseSocketDisconnect() @@ -483,7 +518,7 @@ void CNode::CloseSocketDisconnect() // if this was the sync node, we'll need a new one if (this == pnodeSync) - pnodeSync = NULL; + pnodeSync = nullptr; } void CNode::Cleanup() @@ -554,21 +589,21 @@ bool CNode::IsBanned(CNetAddr ip) bool CNode::Misbehaving(int howmuch) { - if (addr.IsLocal()) - { - LogPrintf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName, howmuch); - return false; - } - nMisbehavior += howmuch; if (nMisbehavior >= GetArg("-banscore", 100)) { - int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban - LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString(), nMisbehavior-howmuch, nMisbehavior); + if (addr.IsLocal()) { - LOCK(cs_setBanned); - if (setBanned[addr] < banTime) - setBanned[addr] = banTime; + LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING (Warning: local addr not banned)\n", addr.ToString(), nMisbehavior-howmuch, nMisbehavior); + } + else { + int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban + LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString(), nMisbehavior-howmuch, nMisbehavior); + { + LOCK(cs_setBanned); + if (setBanned[addr] < banTime) + setBanned[addr] = banTime; + } } CloseSocketDisconnect(); return true; @@ -580,18 +615,18 @@ bool CNode::Misbehaving(int howmuch) bool CNode::SoftBan() { // -- same as Misbehaving, but a shorter ban time - if (addr.IsLocal()) - { - LogPrintf("Warning: Tried to soft ban local node %s !\n", addrName.c_str()); - return false; - }; - - int64_t banTime = GetTime()+GetArg("-softbantime", 60*60*1); // Default 1-hour ban - LogPrintf("SoftBan: %s DISCONNECTING\n", addr.ToString().c_str()); { - LOCK(cs_setBanned); - if (setBanned[addr] < banTime) - setBanned[addr] = banTime; + if (addr.IsLocal()) + { + LogPrintf("SoftBan: %s DISCONNECTING (Warning: local addr not banned)\n", addr.ToString().c_str()); + } + else { + int64_t banTime = GetTime()+GetArg("-softbantime", 60*60*1); // Default 1-hour ban + LogPrintf("SoftBan: %s DISCONNECTING\n", addr.ToString().c_str()); + LOCK(cs_setBanned); + if (setBanned[addr] < banTime) + setBanned[addr] = banTime; + } } CloseSocketDisconnect(); @@ -637,6 +672,8 @@ void CNode::copyStats(CNodeStats &stats) // Leave string empty if addrLocal invalid (not filled in yet) stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : ""; + + stats.m_network = addr.GetNetwork(); } #undef X @@ -786,7 +823,7 @@ void ThreadSocketHandler() LOCK(cs_vNodes); // Disconnect unused nodes vector vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { if (pnode->fDisconnect || (pnode->GetRefCount() <= 0 && pnode->vRecvMsg.empty() && pnode->nSendSize == 0 && pnode->ssSend.empty())) @@ -811,7 +848,7 @@ void ThreadSocketHandler() { // Delete disconnected nodes list vNodesDisconnectedCopy = vNodesDisconnected; - BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy) + for (CNode* pnode : vNodesDisconnectedCopy) { // wait until threads are done using it if (pnode->GetRefCount() <= 0) @@ -860,14 +897,14 @@ void ThreadSocketHandler() SOCKET hSocketMax = 0; bool have_fds = false; - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { + for (SOCKET hListenSocket : vhListenSocket) { FD_SET(hListenSocket, &fdsetRecv); hSocketMax = max(hSocketMax, hListenSocket); have_fds = true; } { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if (pnode->hSocket == INVALID_SOCKET) continue; @@ -908,10 +945,9 @@ void ThreadSocketHandler() // // Accept new connections - // - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) - if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) - { + for (SOCKET hListenSocket : vhListenSocket) { + if (hListenSocket == INVALID_SOCKET || !FD_ISSET(hListenSocket, &fdsetRecv)) + continue; struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); @@ -924,7 +960,7 @@ void ThreadSocketHandler() { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if (pnode->fInbound) nInbound++; } @@ -964,10 +1000,10 @@ void ThreadSocketHandler() { LOCK(cs_vNodes); vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) pnode->AddRef(); } - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { boost::this_thread::interruption_point(); @@ -1062,7 +1098,7 @@ void ThreadSocketHandler() } { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) pnode->Release(); } @@ -1071,131 +1107,65 @@ void ThreadSocketHandler() } +/* Tor implementation ---------------------------------*/ +// hidden service seeds +static const char *strMainNetOnionSeed[][1] = { + // project-maintained nodes + {"gji6yid3u2gozq5hvoufkfyybcvj3ftajvrlhmjjrtzv42o7oeosllqd.onion"}, + {"nounwopyxdcwe72v5xey5jgjf6ypsmyitzolambc7c4vgvheyquekmyd.onion"}, + {"vz2a5ivpeodhydehc4n433n3wrn4exck5i6audy5hbe3pnyi5nudbqid.onion"}, + {"thje6hx5tpj65ujrnizkp6vkg276lcuba5faephxyp65xrwviz452rid.onion"}, + {"34mek66nmcgc4hb4u55zq3pjay5fz3qqmmopqqw6vaqlfxbqtuudkhad.onion"}, + // other stable nodes that are monitored by the project + {NULL} +}; +static const char *strTestNetOnionSeed[][1] = { + // project-maintained nodes + {"f3kcqb22tae4twfvd6lrsanwp4ikfocltsuo4onsjdapcsgatoyw7oid.onion"}, + {"k2chqlj5s5q6xejbkznjqptidqmdbdtnm4jozbe5d5o7mmugikuwzsyd.onion"}, + {"srrfkizif7t7t46s4n37remlzjslryzo5vwibm2l2ewcfsbfgesie7yd.onion"}, + {"f3htcdks3hspr4b52ham4btbxvvtvdqamxpdojexbf42mgkqei5kdcid.onion"}, + {"cuvepsg3uezrchf3cezopd6thrp4osoagi6ngmayakme5qik3f2toiqd.onion"}, + {NULL} +}; - - -#ifdef USE_UPNP -void ThreadMapPort() +void ThreadOnionSeed() { - std::string port = strprintf("%u", GetListenPort()); - const char * multicastif = 0; - const char * minissdpdpath = 0; - struct UPNPDev * devlist = 0; - char lanaddr[64]; - -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); -#elif MINIUPNPC_API_VERSION < 14 - /* miniupnpc 1.6 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); -#else - /* miniupnpc 1.9.20150730 */ - int error = 0; - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); -#endif - struct UPNPUrls urls; - struct IGDdatas data; - int r; + // Make this thread recognisable as the tor thread + RenameThread("onionseed"); - r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); - if (r == 1) - { - if (fDiscover) { - char externalIPAddress[40]; - r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) - LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); - else - { - if(externalIPAddress[0]) - { - LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); - AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); - } - else - LogPrintf("UPnP: GetExternalIPAddress failed.\n"); - } - } - - string strDesc = "ShadowCoin " + FormatFullVersion(); - - try { - while (true) { -#ifndef UPNPDISCOVER_SUCCESS - /* miniupnpc 1.5 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); -#else - /* miniupnpc 1.6 */ - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, - port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); -#endif - - if(r!=UPNPCOMMAND_SUCCESS) - LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - port, port, lanaddr, r, strupnperror(r)); - else - LogPrintf("UPnP Port Mapping successful.\n");; + static const char *(*strOnionSeed)[1] = fTestNet ? strTestNetOnionSeed : strMainNetOnionSeed; - MilliSleep(20*60*1000); // Refresh every 20 minutes - } - } - catch (boost::thread_interrupted) - { - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); - LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r); - freeUPNPDevlist(devlist); devlist = 0; - FreeUPNPUrls(&urls); - throw; - } - } else { - LogPrintf("No valid UPnP IGDs found\n"); - freeUPNPDevlist(devlist); devlist = 0; - if (r != 0) - FreeUPNPUrls(&urls); - } -} + int found = 0; -void MapPort(bool fUseUPnP) -{ - static boost::thread* upnp_thread = NULL; + LogPrintf("Loading addresses from .onion seeds\n"); - if (fUseUPnP) - { - if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - delete upnp_thread; + for (unsigned int seed_idx = 0; strOnionSeed[seed_idx][0] != nullptr; seed_idx++) { + CNetAddr parsed; + if ( + !parsed.SetSpecial( + strOnionSeed[seed_idx][0] + ) + ) { + throw runtime_error("ThreadOnionSeed() : invalid .onion seed"); } - upnp_thread = new boost::thread(boost::bind(&TraceThread, "upnp", &ThreadMapPort)); + int nOneDay = 24*3600; + // Use migration helper for chainparams access + CAddress addr = CAddress(CService(parsed, ChainParamsMigration::GetDefaultPort())); + addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + found++; + addrman.Add(addr, parsed); } - else if (upnp_thread) { - upnp_thread->interrupt(); - upnp_thread->join(); - delete upnp_thread; - upnp_thread = NULL; - } -} -#else -void MapPort(bool) -{ - // Intentionally left blank. + LogPrintf("%d addresses found from .onion seeds\n", found); } -#endif - - - - -void ThreadDNSAddressSeed() +/* void ThreadDNSAddressSeed() { // goal: only query DNS seeds if address need is acute if ((addrman.size() > 0) && @@ -1214,7 +1184,7 @@ void ThreadDNSAddressSeed() LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); - BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) { + for (const CDNSSeedData& seed : vSeeds) { if (HaveNameProxy()) { AddOneShot(seed.host); } else { @@ -1222,7 +1192,7 @@ void ThreadDNSAddressSeed() vector vAdd; if (LookupHost(seed.host.c_str(), vIPs)) { - BOOST_FOREACH(CNetAddr& ip, vIPs) + for (CNetAddr& ip : vIPs) { int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort())); @@ -1236,7 +1206,7 @@ void ThreadDNSAddressSeed() } LogPrintf("%d addresses found from DNS seeds\n", found); -} +} */ void DumpAddresses() { @@ -1275,10 +1245,10 @@ void ThreadOpenConnections() for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); - BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"]) + for (const std::string& strAddr : mapMultiArgs["-connect"]) { CAddress addr; - OpenNetworkConnection(addr, NULL, strAddr.c_str()); + OpenNetworkConnection(addr, nullptr, strAddr.c_str()); for (int i = 0; i < 10 && i < nLoop; i++) { MilliSleep(500); @@ -1320,7 +1290,7 @@ void ThreadOpenConnections() set > setConnected; { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (!pnode->fInbound) { setConnected.insert(pnode->addr.GetGroup()); nOutbound++; @@ -1380,10 +1350,10 @@ void ThreadOpenAddedConnections() list lAddresses(0); { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + for (std::string& strAddNode : vAddedNodes) lAddresses.push_back(strAddNode); } - BOOST_FOREACH(string& strAddNode, lAddresses) { + for (std::string& strAddNode : lAddresses) { CAddress addr; CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(addr, &grant, strAddNode.c_str()); @@ -1398,12 +1368,12 @@ void ThreadOpenAddedConnections() list lAddresses(0); { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + for (std::string& strAddNode : vAddedNodes) lAddresses.push_back(strAddNode); } list > lservAddressesToAdd(0); - BOOST_FOREACH(string& strAddNode, lAddresses) + for (std::string& strAddNode : lAddresses) { vector vservNode(0); if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) @@ -1411,7 +1381,7 @@ void ThreadOpenAddedConnections() lservAddressesToAdd.push_back(vservNode); { LOCK(cs_setservAddNodeAddresses); - BOOST_FOREACH(CService& serv, vservNode) + for (CService& serv : vservNode) setservAddNodeAddresses.insert(serv); } } @@ -1420,9 +1390,9 @@ void ThreadOpenAddedConnections() // (keeping in mind that addnode entries can have many IPs if fNameLookup) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) for (list >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++) - BOOST_FOREACH(CService& addrNode, *(it)) + for (CService& addrNode : *it) if (pnode->addr == addrNode) { it = lservAddressesToAdd.erase(it); @@ -1430,7 +1400,7 @@ void ThreadOpenAddedConnections() break; } } - BOOST_FOREACH(vector& vserv, lservAddressesToAdd) + for (std::vector& vserv : lservAddressesToAdd) { CSemaphoreGrant grant(*semOutbound); OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant); @@ -1473,13 +1443,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu } -// for now, use a very simple selection metric: the node from which we received -// most recently -static int64_t NodeSyncScore(const CNode *pnode) { - return pnode->nLastRecv; -} - - void ThreadMessageHandler() { SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); @@ -1490,18 +1453,18 @@ void ThreadMessageHandler() { LOCK(cs_vNodes); vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) pnode->AddRef(); } // cs_vNodes // Poll the connected nodes for messages - CNode* pnodeTrickle = NULL; + CNode* pnodeTrickle = nullptr; if (!vNodesCopy.empty()) pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())]; bool fSleep = true; - //BOOST_FOREACH(CNode* pnode, vNodesCopy) + //for (CNode* pnode : vNodesCopy) size_t r = GetRandInt(vNodesCopy.size()-1); // randomise the order for (size_t i = 0; i < vNodesCopy.size(); ++i) @@ -1536,7 +1499,7 @@ void ThreadMessageHandler() { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) pnode->Release(); } // cs_vNodes @@ -1631,7 +1594,7 @@ bool BindListenPort(const CService &addrBind, string& strError) { int nErr = WSAGetLastError(); if (nErr == WSAEADDRINUSE) - strError = strprintf(_("Unable to bind to %s on this computer. ShadowCoin is probably already running."), addrBind.ToString()); + strError = strprintf(_("Unable to bind to %s on this computer. Alias is probably already running."), addrBind.ToString()); else strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString(), nErr, strerror(nErr)); LogPrintf("%s\n", strError); @@ -1656,81 +1619,317 @@ bool BindListenPort(const CService &addrBind, string& strError) return true; } -void static Discover(boost::thread_group& threadGroup) +static char *convert_str(const std::string &s) { + char *pc = new char[s.size()+1]; + std::strcpy(pc, s.c_str()); + return pc; +} + +static std::string quoteArg(const bool& quote, const std::string& arg) { - if (!fDiscover) - return; + if (quote) + return "\"" + arg + "\""; + else + return arg; +} -#ifdef WIN32 - // Get local host IP - char pszHostName[1000] = ""; - if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) +/** + * Run tor as separate process for Windows, macOS and Linux + * - Windows with windows specific CreateProcess() + * - macOS with boost::process:child + * - Linux with fork() and execvp() + * All other platforms run Tor embedded. + * + * @brief run_tor + */ +static void run_tor() { + fs::path tor_dir = GetDataDir() / "tor"; + fs::create_directory(tor_dir); + fs::path log_file = tor_dir / "tor.log"; + + std::vector argv; + bool bQuoteArg = false; +#if defined(WIN32) + bQuoteArg = true; +#endif +#ifndef __APPLE__ + // Windows CreateProcess(), exec() and main() when embedding tor need 'tor' as first argument + // Tor separate process via boost::process does not need 'tor' as first argument + argv.push_back("tor"); +#endif + argv.push_back("--SocksPort"); + if (TestNet()) { + argv.push_back(quoteArg(bQuoteArg,"9090 OnionTrafficOnly")); + } else { + argv.push_back(quoteArg(bQuoteArg,"9089 OnionTrafficOnly")); + } + argv.push_back("--ignore-missing-torrc"); + argv.push_back("-f"); + // Move the location of the torrc to the .spectrecoin folder instead of .spectrecoin/tor + // Allows to have all config files in one place + argv.push_back(quoteArg(bQuoteArg, (GetDataDir() / "torrc").string())); + argv.push_back("--DataDirectory"); + argv.push_back(quoteArg(bQuoteArg, tor_dir.string())); + argv.push_back("--GeoIPFile"); + argv.push_back(quoteArg(bQuoteArg, (tor_dir / "geoip").string())); + argv.push_back("--GeoIPv6File"); + argv.push_back(quoteArg(bQuoteArg, (tor_dir / "geoipv6").string())); + argv.push_back("--HiddenServiceDir"); + argv.push_back(quoteArg(bQuoteArg, (tor_dir / "onion").string())); + argv.push_back("--HiddenServiceVersion"); + if (GetBoolArg("-onionv2")) { + argv.push_back("2"); + } + else { + argv.push_back("3"); + } + argv.push_back("--HiddenServicePort"); + if (TestNet()) { + argv.push_back("37111"); + } + else { + argv.push_back("37347"); + } + +#if defined(WIN32) || defined(__APPLE__) + // Tor separate process + fs::path pathApplicationDir = dll::program_location().parent_path(); + fs::path pathTorDir = pathApplicationDir / "Tor"; + + argv.push_back("--defaults-torrc"); + fs::path torrc_defaults_file = pathTorDir / "torrc-defaults"; + argv.push_back(quoteArg(bQuoteArg, torrc_defaults_file.string())); +#elif __linux__ + + fs::path torrc_defaults_file = tor_dir / "torrc-defaults"; + bool must_override = false; + if (fs::exists(torrc_defaults_file) && fs::is_regular_file(torrc_defaults_file)) { - vector vaddr; - if (LookupHost(pszHostName, vaddr)) + FILE* file = fopen(torrc_defaults_file.string().c_str(), "r"); + if (file) { - BOOST_FOREACH (const CNetAddr &addr, vaddr) - { - AddLocal(addr, LOCAL_IF); - } + int check_rev = 0; + fscanf(file, "# torrc-defaults for Alias rev. %d\n", &check_rev); + if (check_rev != TORRC_DEFAULTS_REV) + must_override = true; + fclose(file); } } -#else - // Get local host ip - struct ifaddrs* myaddrs; - if (getifaddrs(&myaddrs) == 0) + if (must_override || !fs::exists(torrc_defaults_file) || !fs::is_regular_file(torrc_defaults_file)) { - for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) + FILE* file = fopen(torrc_defaults_file.string().c_str(), "w"); + if (file) { - if (ifa->ifa_addr == NULL) continue; - if ((ifa->ifa_flags & IFF_UP) == 0) continue; - if (strcmp(ifa->ifa_name, "lo") == 0) continue; - if (strcmp(ifa->ifa_name, "lo0") == 0) continue; - if (ifa->ifa_addr->sa_family == AF_INET) - { - struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); - CNetAddr addr(s4->sin_addr); - if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString()); - } - else if (ifa->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); - CNetAddr addr(s6->sin6_addr); - if (AddLocal(addr, LOCAL_IF)) - LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString()); - } + fprintf(file, "# torrc-defaults for Alias rev. %d\n", TORRC_DEFAULTS_REV); + fprintf(file, "#\n"); + fprintf(file, "# DO NOT EDIT THIS FILE\n"); + fprintf(file, "#\n"); + fprintf(file, "# This file is distributed with Alias within the tor folder and SHOULD NOT be modified\n"); + fprintf(file, "# (it may be overwritten during the next Alias update).\n"); + fprintf(file, "# To customize your Tor configuration, shut down Alias and edit the torrc file.\n"); + fprintf(file, "#\n"); + fprintf(file, "# If non-zero, try to write to disk less frequently than we would otherwise.\n"); + fprintf(file, "AvoidDiskWrites 1\n"); + fprintf(file, "#\n"); + fprintf(file, "# If non-zero, try to use built-in (static) crypto hardware acceleration when available.\n"); + fprintf(file, "HardwareAccel 1\n"); +#if defined(ANDROID) || defined(__ANDROID__) + fprintf(file, "# If it is set to 0, Tor will not send any padding cells. This option should be offered to mobile users for use where bandwidth may be expensive.\n"); + fprintf(file, "ConnectionPadding 0\n"); + fprintf(file, "#\n"); + fprintf(file, "# If set to 1, Tor will not not hold OR connections open for very long. This option should be offered to mobile users for use where bandwidth may be expensive.\n"); + fprintf(file, "ReducedConnectionPadding 1\n"); +#endif + fclose(file); } - freeifaddrs(myaddrs); } + argv.push_back("--defaults-torrc"); + argv.push_back(quoteArg(bQuoteArg, torrc_defaults_file.string())); #endif +#ifdef WIN32 + // Tor separate process via CreateProcess + argv.push_back("--Log"); + argv.push_back("\"notice file " + log_file.string() + "\""); + + HANDLE hJob; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + STARTUPINFOA si = { 0 }; + + // Create a job object. + hJob = CreateJobObject(nullptr, nullptr); + + // Causes all processes associated with the job to terminate when the last handle to the job is closed. + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)); + + // Hide the console window + si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + // Build concatenated commandline string for CreateProcess + std::string strCommandLine; + for (auto const& s : argv) { strCommandLine += s + " "; } + + // Create the process suspended + LogPrintf("Start tor 'Tor/tor.exe' as separate process (CreateProcess) with: %s\n", strCommandLine); + + if (!CreateProcessA("Tor/tor.exe", const_cast(strCommandLine.c_str()), nullptr, nullptr, FALSE, + CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB /*Important*/, nullptr, nullptr, &si, &pi)) { + LogPrintf("Terminating - Error: CreateProcess for tor failed with error %d\n", GetLastError()); + exit(1); // TODO improved termination + } + // Add the process to our job object. + AssignProcessToJobObject(hJob, pi.hProcess); // Does not work if without CREATE_BREAKAWAY_FROM_JOB + + // Start our suspended process. + ResumeThread(pi.hThread); + + /* + * At this point, if we are closed, windows will automatically clean up + * by closing any handles we have open. When the handle to the job object + * is closed, any processes belonging to the job will be terminated. + * Note: Grandchild processes automatically become part of the job and + * will also be terminated. This behaviour can be avoided by using the + * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK limit flag. + */ + + // Block this thread until the process exits (to have same behavior as tor_main call for static tor integration) + WaitForSingleObject(pi.hProcess, INFINITE); +#elif __APPLE__ + // Tor separate process via boost::process + argv.push_back("--Log"); + argv.push_back("notice file " + log_file.string()); + + std::string strCommandLine; + for (auto const& s : argv) { strCommandLine += s + " "; } + LogPrintf("Start tor as separate process (process::child) with: %s\n", strCommandLine); + + process::child pChildTor(process::start_dir = pathTorDir, "./tor.real", argv, gTor); + pChildTor.detach(); + // Block this thread until the process exits (to have same behavior as tor_main call for static tor integration) + std::error_code ec; + gTor.wait(ec); + if (ec && !ShutdownRequested()) + boost::process::detail::throw_error(ec, "Tor process: waitpid(2) failed in wait"); +#elif __linux__ + // Tor separate process via fork,execvp + argv.push_back("--Log"); + argv.push_back("notice file " + log_file.string()); + + std::string strCommandLine; + for (auto const& s : argv) { strCommandLine += s + " "; } + LogPrintf("Start tor as separate process (fork,execvp) with: %s\n", strCommandLine); + + std::string torResult; + pid_t ppid_before_fork = getpid(); + tor_process_pid = fork(); + if (tor_process_pid == -1) { + torResult = "Terminating - Error: fork() for tor failed: "; + torResult += strerror(errno); + torResult += "\n"; + } + else if (tor_process_pid == 0) { + // Continue child execution... + // Make sure tor gets terminated when parent process dies + int r = prctl(PR_SET_PDEATHSIG, SIGKILL); + if (r == -1) { + perror("Could not install PDEATHSIG."); + _exit(1); + } + if (getppid() != ppid_before_fork) { + LogPrintf("Original parent exited just before the prctl() call\n"); + _exit(1); + } + + std::vector argv_c; + std::transform(argv.begin(), argv.end(), std::back_inserter(argv_c), convert_str); + argv_c.push_back(nullptr); + + if (execvp("tor", &argv_c[0]) < 0) { + perror("execvp(\"tor\", ...) failed"); + _exit(127); + } + } else { + // Continue parent execution... + // Block this thread until the process exits (to have same behavior as tor_main call for static tor integration) + int status; + if (waitpid(tor_process_pid, &status, 0) > 0) { + if (WIFEXITED(status) && !WEXITSTATUS(status)) { + torResult = "Tor shutdown successfull\n"; + } else if (tor_killed_from_here) { + torResult = "Tor shutdown during wallet stop\n"; + } else if (WIFEXITED(status) && WEXITSTATUS(status)) { + if (WEXITSTATUS(status) == 127) { + torResult = "Terminating - Error: Could not start tor. Is tor installed and available in PATH?\n"; + } else { + torResult = "Terminating - Error: Tor did exit with status " + std::to_string(WEXITSTATUS(status)) + + "\n"; + } + } else { + torResult = "Terminating - Error: Tor was terminated\n"; + } + } else { + torResult = "Terminating - Error: waitpid() for tor failed\n"; + } + } + +#else + // Tor embedded + argv.push_back("--Log"); + argv.push_back("notice file " + log_file.string()); + + std::string strCommandLine; + for (auto const& s : argv) { strCommandLine += s + " "; } + LogPrintf("Start tor embedded (tor_main) with: %s\n", strCommandLine); + + std::vector argv_c; + std::transform(argv.begin(), argv.end(), std::back_inserter(argv_c), convert_str); + tor_main(argv_c.size(), &argv_c[0]); +#endif } +void StartTor(void *nothing) +{ + // Make this thread recognisable as the tor thread + RenameThread("onion"); + + try + { + run_tor(); + } + catch (std::exception& e) { + PrintException(&e, "StartTor()"); + } + + // If tor could not be started or exits for any reason, shutdown the application + StartShutdown(); + + LogPrintf("Onion thread exited.\n"); +} void StartNode(boost::thread_group& threadGroup) { - if (semOutbound == NULL) { + if (semOutbound == nullptr) { // initialize semaphore int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); semOutbound = new CSemaphore(nMaxOutbound); } - if (pnodeLocalHost == NULL) + if (pnodeLocalHost == nullptr) pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices)); - Discover(threadGroup); - // // Start threads // - if (!GetBoolArg("-dnsseed", true)) - LogPrintf("DNS seeding disabled\n"); + // start the onion seeder + if (!GetBoolArg("-onionseed", true)) + LogPrintf(".onion seeding disabled\n"); else - threadGroup.create_thread(boost::bind(&TraceThread, "dnsseed", &ThreadDNSAddressSeed)); - - MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); + threadGroup.create_thread(boost::bind(&TraceThread, "onionseed", &ThreadOnionSeed)); // Send and receive from sockets, accept connections threadGroup.create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); @@ -1751,12 +1950,27 @@ void StartNode(boost::thread_group& threadGroup) bool StopNode() { LogPrintf("StopNode()\n"); - MapPort(false); mempool.AddTransactionsUpdated(1); if (semOutbound) for (int i=0; ipost(); DumpAddresses(); + +#ifdef __APPLE__ + // Tor separate process via boost::process + if (gTor && gTor.valid()) { + LogPrintf("Terminate tor process group\n"); + gTor.terminate(); + } +#elif __linux__ + if (tor_process_pid > 0) { + // Prevent confusing error output as SIGTERM is not working from here + tor_killed_from_here = true; + + kill(tor_process_pid, SIGKILL); + } +#endif + return true; } @@ -1769,13 +1983,13 @@ class CNetCleanup ~CNetCleanup() { // Close sockets - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if (pnode->hSocket != INVALID_SOCKET) closesocket(pnode->hSocket); - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) - if (hListenSocket != INVALID_SOCKET) - if (closesocket(hListenSocket) == SOCKET_ERROR) - LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); + for (SOCKET hListenSocket : vhListenSocket) { + if (hListenSocket != INVALID_SOCKET && closesocket(hListenSocket) == SOCKET_ERROR) + LogPrintf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); + } #ifdef WIN32 // Shutdown Windows Sockets @@ -1811,7 +2025,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt } LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { if(!pnode->fRelayTxes) continue; diff --git a/src/net.h b/src/net.h index 5f496e0989..f1a8b9d14a 100644 --- a/src/net.h +++ b/src/net.h @@ -1,14 +1,19 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_NET_H #define BITCOIN_NET_H #include +#ifndef Q_MOC_RUN #include -#include #include +#endif #include #ifndef WIN32 @@ -24,6 +29,10 @@ #include "hash.h" +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0x0 // not necessary on systems where it is not defined +#endif + class CRequestTracker; class CNode; class CBlockIndex; @@ -56,10 +65,11 @@ void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); -CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL); +CNode* ConnectNode(CAddress addrConnect, const char *strDest = nullptr); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); +void StartTor(void *); void StartNode(boost::thread_group& threadGroup); bool StopNode(); void SocketSendData(CNode *pnode); @@ -103,11 +113,11 @@ bool AddLocal(const CService& addr, int nScore = LOCAL_NONE); bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); bool SeenLocal(const CService& addr); bool IsLocal(const CService& addr); -bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); +bool GetLocal(CService &addr, const CNetAddr *paddrPeer = nullptr); bool IsReachable(const CNetAddr &addr); bool IsReachable(enum Network net); void SetReachable(enum Network net, bool fFlag = true); -CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); +CAddress GetLocalAddress(const CNetAddr *paddrPeer = nullptr); class CRequestTracker { @@ -123,7 +133,7 @@ class CRequestTracker bool IsNull() { - return fn == NULL; + return fn == nullptr; } }; @@ -131,12 +141,14 @@ class CRequestTracker /** Thread types */ enum threadId { + THREAD_TORNET, THREAD_SOCKETHANDLER, THREAD_OPENCONNECTIONS, THREAD_MESSAGEHANDLER, THREAD_RPCLISTENER, THREAD_UPNP, - THREAD_DNSSEED, + THREAD_ONIONSEED, +// THREAD_DNSSEED, THREAD_ADDEDCONNECTIONS, THREAD_DUMPADDRESS, THREAD_RPCHANDLER, @@ -145,7 +157,7 @@ enum threadId THREAD_MAX }; -extern bool fDiscover; +// extern bool fDiscover; extern bool fUseUPnP; extern uint64_t nLocalHostNonce; @@ -202,6 +214,7 @@ class CNodeStats double dPingTime; double dPingWait; std::string addrLocal; + Network m_network; }; @@ -247,30 +260,6 @@ class CNetMessage - -class SecMsgNode -{ -public: - SecMsgNode() - { - lastSeen = 0; - lastMatched = 0; - ignoreUntil = 0; - nWakeCounter = 0; - fEnabled = false; - }; - - ~SecMsgNode() {}; - - CCriticalSection cs_smsg_net; - int64_t lastSeen; - int64_t lastMatched; - int64_t ignoreUntil; - uint32_t nWakeCounter; - bool fEnabled; - -}; - /** Information about a peer */ class CNode { @@ -293,7 +282,7 @@ class CNode int64_t nLastSend; int64_t nLastRecv; - + int64_t nLastSendEmpty; int64_t nTimeConnected; int64_t nTimeOffset; @@ -306,6 +295,7 @@ class CNode bool fOneShot; bool fClient; bool fInbound; + bool fVerified; // tor implementation bool fNetworkNode; bool fSuccessfullyConnected; bool fDisconnect; @@ -345,8 +335,6 @@ class CNode CCriticalSection cs_inventory; std::multimap mapAskFor; - SecMsgNode smsgData; - // Ping time measurement: // The pong reply we're expecting, or 0 if no pong expected. uint64_t nPingNonceSent; @@ -356,8 +344,8 @@ class CNode int64_t nPingUsecTime; // Whether a ping is requested. bool fPingQueued; - - + + CCriticalSection cs_filter; CBloomFilter* pfilter; @@ -381,6 +369,7 @@ class CNode fOneShot = false; fClient = false; // set by version message fInbound = fInboundIn; + fVerified = false; // tor implementation fNetworkNode = false; fSuccessfullyConnected = false; fDisconnect = false; @@ -396,12 +385,12 @@ class CNode fGetAddr = false; nMisbehavior = 0; setInventoryKnown.max_size(SendBufferSize() / 1000); - pfilter = NULL; + pfilter = nullptr; nPingNonceSent = 0; nPingUsecStart = 0; nPingUsecTime = 0; fPingQueued = false; - + { LOCK(cs_nLastNodeId); id = nLastNodeId++; @@ -444,7 +433,7 @@ class CNode unsigned int GetTotalRecvSize() { unsigned int total = 0; - BOOST_FOREACH(const CNetMessage &msg, vRecvMsg) + for (const CNetMessage& msg : vRecvMsg) total += msg.vRecv.size() + 24; return total; } @@ -456,7 +445,7 @@ class CNode void SetRecvVersion(int nVersionIn) { nRecvVersion = nVersionIn; - BOOST_FOREACH(CNetMessage &msg, vRecvMsg) + for (CNetMessage& msg : vRecvMsg) msg.SetVersion(nVersionIn); } @@ -483,7 +472,7 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (addr.IsValid() && !setAddrKnown.count(addr)) + if (addr.IsValid() && !setAddrKnown.count(addr) && (!addr.IsTorV3() || nRecvVersion >= 60042)) vAddrToSend.push_back(addr); } @@ -509,7 +498,7 @@ class CNode { // We're using mapAskFor as a priority queue, // the key is the earliest time the request can be sent - + int64_t& nRequestTime = mapAlreadyAskedFor[inv]; LogPrint("net", "askfor %s %d (%s)\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000)); @@ -556,8 +545,10 @@ class CNode return; } - if (ssSend.size() == 0) + if (ssSend.size() == 0) { + LEAVE_CRITICAL_SECTION(cs_vSend); return; + } // Set the size unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; @@ -792,7 +783,7 @@ class CNode void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); - + void PushGetBlocks(uint256& hashBegin, uint256 hashEnd); void PushGetBlocks(CBlockThinIndex* pindexBegin, uint256 hashEnd); void PushGetHeaders(CBlockThinIndex* pindexBegin, uint256 hashEnd); diff --git a/src/net_alias.cpp b/src/net_alias.cpp new file mode 100644 index 0000000000..20f9b028f2 --- /dev/null +++ b/src/net_alias.cpp @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include + +// Alias-specific: Embedded Tor support +// Note: This requires linking with Tor libraries +extern void tor_main(void* arg); + +bool IsTorV3Address(const CNetAddr& addr) +{ + // Alias-specific: Check if address is Tor V3 (.onion v3) + // Tor V3 addresses are 56 characters long (base32 encoded) + if (!addr.IsTor()) + return false; + + // Check if it's a V3 address (56 chars) vs V2 (16 chars) + std::string addrStr = addr.ToString(); + return addrStr.length() == 56; // V3 addresses are 56 chars +} + +void StartTor(void* parg) +{ + // Alias-specific: Start embedded Tor service + // This runs Tor in a separate thread + LogPrintf("Starting embedded Tor service...\n"); + + // Create thread for Tor network + if (!NewThread(ThreadTorNet, parg)) + { + LogPrintf("ERROR: NewThread(ThreadTorNet) failed\n"); + } + + // Create thread for onion seed + if (!NewThread(ThreadOnionSeed, parg)) + { + LogPrintf("ERROR: NewThread(ThreadOnionSeed) failed\n"); + } +} + +void ThreadTorNet(void* parg) +{ + // Alias-specific: Tor network thread + // This runs the embedded Tor service + LogPrintf("ThreadTorNet started\n"); + + // Run embedded Tor + // Note: This requires the Tor library to be linked + try { + tor_main(parg); + } catch (const std::exception& e) { + LogPrintf("ThreadTorNet exception: %s\n", e.what()); + } + + LogPrintf("ThreadTorNet exiting\n"); +} + +void ThreadOnionSeed(void* parg) +{ + // Alias-specific: Onion seed thread + // This seeds .onion addresses for the network + LogPrintf("ThreadOnionSeed started\n"); + + // TODO: Implement onion seed logic + // This should periodically seed .onion addresses + + LogPrintf("ThreadOnionSeed exiting\n"); +} + +namespace AliasNet { + +bool IsTorVerified(const CNode* pnode) +{ + // Alias-specific: Check if node is Tor-verified + // Note: This requires fVerified to be added to CNode structure + // For now, this is a placeholder that will be integrated + (void)pnode; + + // TODO: Access fVerified flag from CNode + // In modern structure, this might be: + // return pnode->fVerified; + + return false; +} + +void SetTorVerified(CNode* pnode, bool fVerified) +{ + // Alias-specific: Set Tor verification status + // Note: This requires fVerified to be added to CNode structure + (void)pnode; + (void)fVerified; + + // TODO: Set fVerified flag on CNode + // In modern structure, this might be: + // pnode->fVerified = fVerified; +} + +} // namespace AliasNet + diff --git a/src/net_alias.h b/src/net_alias.h new file mode 100644 index 0000000000..c447e02376 --- /dev/null +++ b/src/net_alias.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NET_ALIAS_H +#define BITCOIN_NET_ALIAS_H + +#include +#include + +/** + * Alias-specific networking extensions + * Preserves Tor integration and fVerified flag + */ + +/** + * Check if address is a Tor V3 address + * Alias-specific: Tor V3 address validation + */ +bool IsTorV3Address(const CNetAddr& addr); + +/** + * Start embedded Tor service + * Alias-specific: Embedded Tor integration + * This runs Tor in a separate thread (THREAD_TORNET) + */ +void StartTor(void* parg); + +/** + * Thread function for Tor network + * Alias-specific: Tor network thread + */ +void ThreadTorNet(void* parg); + +/** + * Thread function for onion seed + * Alias-specific: Onion address seeding thread + */ +void ThreadOnionSeed(void* parg); + +/** + * Add fVerified flag support to modern CNode + * Alias-specific: Tor verification flag + * This should be added as a member to CNode or Peer structure + */ +namespace AliasNet { + // Helper to check if a node is Tor-verified + // This will be integrated into the modern CNode structure + bool IsTorVerified(const CNode* pnode); + + // Set Tor verification status + // This will be integrated into the modern CNode structure + void SetTorVerified(CNode* pnode, bool fVerified); +} + +#endif // BITCOIN_NET_ALIAS_H + diff --git a/src/net_migration_guide.md b/src/net_migration_guide.md new file mode 100644 index 0000000000..1202c6c5f6 --- /dev/null +++ b/src/net_migration_guide.md @@ -0,0 +1,93 @@ +# Networking Migration Guide + +## Adding fVerified Flag to Modern CNode + +### Step 1: Modify particl-core/src/net.h + +Add the fVerified flag to the CNode class: + +```cpp +class CNode { + // ... existing members ... + + // Alias-specific: Tor verification flag + std::atomic_bool fVerified{false}; // tor implementation + + // ... rest of class ... +}; +``` + +### Step 2: Initialize in Constructor + +In `CNode::CNode()` constructor in `particl-core/src/net.cpp`: + +```cpp +CNode::CNode(...) + : // ... existing initializers ... + fVerified{false} // Initialize Tor verification flag +{ + // ... rest of constructor ... +} +``` + +### Step 3: Use in Connection Logic + +When establishing Tor connections, set fVerified: + +```cpp +// In connection establishment code +if (addr.IsTor() && /* Tor verification successful */) { + pnode->fVerified.store(true); +} +``` + +### Step 4: Use Helper Functions + +Use the helper functions from `net_node_alias.h`: + +```cpp +#include + +// Check if verified +if (AliasNode::IsTorVerified(pnode)) { + // Handle verified Tor connection +} + +// Set verification status +AliasNode::SetTorVerified(pnode, true); +``` + +## Preserving Tor Integration + +### StartTor Function + +The `StartTor()` function from `net_alias.cpp` should be called during node initialization: + +```cpp +// In init.cpp or similar +if (gArgs.GetBoolArg("-tor", true)) { + StartTor(nullptr); +} +``` + +### ThreadOnionSeed + +The onion seed thread should be started alongside other network threads: + +```cpp +// In StartNode or similar +threadGroup.create_thread(boost::bind(&TraceThread, "onionseed", &ThreadOnionSeed)); +``` + +## Migration Checklist + +- [ ] Add fVerified flag to CNode class +- [ ] Initialize fVerified in constructor +- [ ] Set fVerified when Tor connection is verified +- [ ] Use helper functions for fVerified access +- [ ] Integrate StartTor() into node initialization +- [ ] Start ThreadOnionSeed thread +- [ ] Update all Tor-related connection logic +- [ ] Test Tor connections work correctly +- [ ] Verify fVerified flag is set/checked properly + diff --git a/src/net_node_alias.cpp b/src/net_node_alias.cpp new file mode 100644 index 0000000000..223f97633e --- /dev/null +++ b/src/net_node_alias.cpp @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include +#include +#include +#include +#include + +namespace AliasNode { + +bool IsTorVerified(const CNode* pnode) +{ + if (!pnode) + return false; + + // Access fVerified flag from CNode (already exists in alias-wallet) + return pnode->fVerified; +} + +void SetTorVerified(CNode* pnode, bool fVerified) +{ + if (!pnode) + return; + + // Set fVerified flag on CNode (already exists in alias-wallet) + pnode->fVerified = fVerified; + + if (fVerified && pnode->addr.IsTor()) { + LogPrintf("Marking Tor connection as verified: %s\n", + pnode->addr.ToString().c_str()); + } +} + +bool IsTorConnection(const CNode* pnode) +{ + if (!pnode) + return false; + + // Check if node is connected via Tor + bool isTor = pnode->addr.IsTor(); + bool isVerified = IsTorVerified(pnode); + + return isTor && isVerified; +} + +} // namespace AliasNode + diff --git a/src/net_node_alias.h b/src/net_node_alias.h new file mode 100644 index 0000000000..fbfabb7b09 --- /dev/null +++ b/src/net_node_alias.h @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NET_NODE_ALIAS_H +#define BITCOIN_NET_NODE_ALIAS_H + +#include + +/** + * Alias-specific extensions to modern CNode structure + * Adds fVerified flag for Tor verification + * + * This header provides the interface for adding fVerified to CNode + * The actual implementation will be integrated into the modern net.h + */ + +class CNode; + +namespace AliasNode { + +/** + * Get Tor verification status + * Alias-specific: Returns fVerified flag value + * + * Usage: bool fVerified = AliasNode::IsTorVerified(pnode); + */ +bool IsTorVerified(const CNode* pnode); + +/** + * Set Tor verification status + * Alias-specific: Sets fVerified flag + * + * Usage: AliasNode::SetTorVerified(pnode, true); + */ +void SetTorVerified(CNode* pnode, bool fVerified); + +/** + * Check if node is connected via Tor + * Alias-specific: Checks if address is Tor and verified + */ +bool IsTorConnection(const CNode* pnode); + +} // namespace AliasNode + +/** + * Instructions for adding fVerified to modern CNode: + * + * In particl-core/src/net.h, add to CNode class: + * + * // Alias-specific: Tor verification flag + * std::atomic_bool fVerified{false}; // tor implementation + * + * Then implement the helper functions in net_node_alias.cpp + */ + +#endif // BITCOIN_NET_NODE_ALIAS_H + diff --git a/src/netbase.cpp b/src/netbase.cpp index 4bf7e16161..17872113bb 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "netbase.h" @@ -10,6 +13,11 @@ #include "uint256.h" #include "util.h" +#if defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + #ifdef HAVE_GETADDRINFO_A #include #endif @@ -41,7 +49,7 @@ bool fNameLookup = false; static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; // Need ample time for negotiation for very slow proxies such as Tor (milliseconds) -static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; +static const int SOCKS5_RECV_TIMEOUT = 60 * 1000; enum Network ParseNetwork(std::string net) { boost::to_lower(net); @@ -127,13 +135,13 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; #endif - struct addrinfo *aiRes = NULL; + struct addrinfo *aiRes = nullptr; #ifdef HAVE_GETADDRINFO_A struct gaicb gcb, *query = &gcb; memset(query, 0, sizeof(struct gaicb)); gcb.ar_name = pszName; gcb.ar_request = &aiHint; - int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL); + int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, nullptr); if (nErr) return false; @@ -151,24 +159,24 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign aiRes = query->ar_result; } while (nErr == EAI_INPROGRESS); #else - int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes); + int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes); #endif if (nErr) return false; struct addrinfo *aiTrav = aiRes; - while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) + while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) { if (aiTrav->ai_family == AF_INET) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); - vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); + vIP.push_back(CNetAddr(static_cast(aiTrav->ai_addr)->sin_addr)); } if (aiTrav->ai_family == AF_INET6) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); - vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); + vIP.push_back(CNetAddr(static_cast(aiTrav->ai_addr)->sin6_addr)); } aiTrav = aiTrav->ai_next; @@ -268,7 +276,7 @@ bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSock fd_set fdset; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); - int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval); + int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval); if (nRet == SOCKET_ERROR) { return false; } @@ -303,7 +311,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); - return error("Error reading proxy response"); + return false; } if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00) { @@ -326,7 +334,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) { CloseSocket(hSocket); - return error("Error reading proxy response"); + return error("Error timeout"); } if (pchRet2[0] != 0x05) { @@ -397,7 +405,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe return false; } - SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); + SOCKET hSocket = socket(static_cast(&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); if (hSocket == INVALID_SOCKET) return false; @@ -421,7 +429,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe fd_set fdset; FD_ZERO(&fdset); FD_SET(hSocket, &fdset); - int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); + int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout); if (nRet == 0) { LogPrint("net", "connection to %s timeout\n", addrConnect.ToString()); @@ -436,7 +444,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe } socklen_t nRetSize = sizeof(nRet); #ifdef WIN32 - if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR) + if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, static_cast(static_cast(&nRet)), &nRetSize) == SOCKET_ERROR) #else if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR) #endif @@ -510,7 +518,7 @@ bool HaveNameProxy() { bool IsProxy(const CNetAddr &addr) { LOCK(cs_proxyInfos); for (int i = 0; i < NET_MAX; i++) { - if (addr == (CNetAddr)proxyInfo[i]) + if (addr == static_cast(proxyInfo[i])) return true; } return false; @@ -583,11 +591,13 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest void CNetAddr::Init() { memset(ip, 0, sizeof(ip)); + memset(ip_tor, 0, sizeof(ip_tor)); } void CNetAddr::SetIP(const CNetAddr& ipIn) { memcpy(ip, ipIn.ip, sizeof(ip)); + memcpy(ip_tor, ipIn.ip_tor, sizeof(ip_tor)); } void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) @@ -597,9 +607,11 @@ void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) case NET_IPV4: memcpy(ip, pchIPv4, 12); memcpy(ip+12, ip_in, 4); + memset(ip_tor, 0, sizeof(ip_tor)); break; case NET_IPV6: memcpy(ip, ip_in, 16); + memset(ip_tor, 0, sizeof(ip_tor)); break; default: assert(!"invalid network"); @@ -614,10 +626,25 @@ bool CNetAddr::SetSpecial(const std::string &strName) if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); if (vchAddr.size() != 16-sizeof(pchOnionCat)) - return false; + { + if (vchAddr.size() == 41-sizeof(pchOnionCat)) + { + memcpy(ip_tor, pchOnionCat, sizeof(pchOnionCat)); + for (unsigned int i=0; i<41-sizeof(pchOnionCat); i++) + ip_tor[i + sizeof(pchOnionCat)] = vchAddr[i]; + } + else + return false; + } + else + memset(ip_tor, 0, sizeof(ip_tor)); + memcpy(ip, pchOnionCat, sizeof(pchOnionCat)); for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++) + { ip[i + sizeof(pchOnionCat)] = vchAddr[i]; + } + return true; } if (strName.size()>11 && strName.substr(strName.size() - 11, 11) == ".oc.b32.i2p") { @@ -639,12 +666,12 @@ CNetAddr::CNetAddr() CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) { - SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr); + SetRaw(NET_IPV4, static_cast(static_cast(&ipv4Addr))); } CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) { - SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr); + SetRaw(NET_IPV6, static_cast(static_cast(&ipv6Addr))); } CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) @@ -668,6 +695,11 @@ unsigned int CNetAddr::GetByte(int n) const return ip[15-n]; } +unsigned int CNetAddr::GetByteTorV3(int n) const +{ + return ip_tor[40-n]; +} + bool CNetAddr::IsIPv4() const { return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0); @@ -756,6 +788,11 @@ bool CNetAddr::IsTor() const return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); } +bool CNetAddr::IsTorV3() const +{ + return IsTor() && (memcmp(ip_tor, pchOnionCat, sizeof(pchOnionCat)) == 0); +} + bool CNetAddr::IsI2P() const { return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); @@ -841,16 +878,18 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { + if (IsTorV3()) + return EncodeBase32(&ip_tor[6], 35) + ".onion"; if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; if (IsI2P()) return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p"; - CService serv(*this, 0); + CService serv(*this, 0); // Port 0 is intentional for IP-only representation struct sockaddr_storage sockaddr; socklen_t socklen = sizeof(sockaddr); if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) { char name[1025] = ""; - if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) + if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), nullptr, 0, NI_NUMERICHOST)) return std::string(name); } if (IsIPv4()) @@ -870,17 +909,24 @@ std::string CNetAddr::ToString() const bool operator==(const CNetAddr& a, const CNetAddr& b) { - return (memcmp(a.ip, b.ip, 16) == 0); + if (a.IsTorV3() == b.IsTorV3()) + return b.IsTorV3() ? (memcmp(a.ip_tor, b.ip_tor, 41) == 0) : (memcmp(a.ip, b.ip, 16) == 0); + return false; } bool operator!=(const CNetAddr& a, const CNetAddr& b) { - return (memcmp(a.ip, b.ip, 16) != 0); + if (a.IsTorV3() == b.IsTorV3()) + return b.IsTorV3() ? (memcmp(a.ip_tor, b.ip_tor, 41) != 0) : (memcmp(a.ip, b.ip, 16) != 0); + return true; } bool operator<(const CNetAddr& a, const CNetAddr& b) { - return (memcmp(a.ip, b.ip, 16) < 0); + if (a.IsTorV3() == b.IsTorV3()) + return b.IsTorV3() ? (memcmp(a.ip_tor, b.ip_tor, 41) < 0) : (memcmp(a.ip, b.ip, 16) < 0); + int result = memcmp(a.ip, b.ip, 16); + return (result == 0) ? b.IsTorV3() : (result < 0); } bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const @@ -962,19 +1008,31 @@ std::vector CNetAddr::GetGroup() const vchRet.push_back(nClass); while (nBits >= 8) { - vchRet.push_back(GetByte(15 - nStartByte)); + if (IsTorV3()) + vchRet.push_back(GetByteTorV3(40 - nStartByte)); + else + vchRet.push_back(GetByte(15 - nStartByte)); nStartByte++; nBits -= 8; } if (nBits > 0) - vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1)); + { + if (IsTorV3()) + vchRet.push_back(GetByteTorV3(40 - nStartByte) | ((1 << nBits) - 1)); + else + vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1)); + } return vchRet; } uint64_t CNetAddr::GetHash() const { - uint256 hash = Hash(&ip[0], &ip[16]); + uint256 hash; + if (IsTorV3()) + hash = Hash(&ip_tor[0], &ip_tor[41]); + else + hash = Hash(&ip[0], &ip[16]); uint64_t nRet; memcpy(&nRet, &hash, sizeof(nRet)); return nRet; @@ -986,7 +1044,7 @@ static const int NET_UNKNOWN = NET_MAX + 0; static const int NET_TEREDO = NET_MAX + 1; int static GetExtNetwork(const CNetAddr *addr) { - if (addr == NULL) + if (addr == nullptr) return NET_UNKNOWN; if (addr->IsRFC4380()) return NET_TEREDO; @@ -1094,10 +1152,10 @@ bool CService::SetSockAddr(const struct sockaddr *paddr) { switch (paddr->sa_family) { case AF_INET: - *this = CService(*(const struct sockaddr_in*)paddr); + *this = CService(*static_cast(paddr)); return true; case AF_INET6: - *this = CService(*(const struct sockaddr_in6*)paddr); + *this = CService(*static_cast(paddr)); return true; default: return false; @@ -1162,7 +1220,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const if (*addrlen < (socklen_t)sizeof(struct sockaddr_in)) return false; *addrlen = sizeof(struct sockaddr_in); - struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr; + struct sockaddr_in *paddrin = static_cast(paddr); memset(paddrin, 0, *addrlen); if (!GetInAddr(&paddrin->sin_addr)) return false; @@ -1174,7 +1232,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6)) return false; *addrlen = sizeof(struct sockaddr_in6); - struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr; + struct sockaddr_in6 *paddrin6 = static_cast(paddr); memset(paddrin6, 0, *addrlen); if (!GetIn6Addr(&paddrin6->sin6_addr)) return false; @@ -1188,10 +1246,20 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const std::vector CService::GetKey() const { std::vector vKey; - vKey.resize(18); - memcpy(&vKey[0], ip, 16); - vKey[16] = port / 0x100; - vKey[17] = port & 0x0FF; + if (IsTorV3()) + { + vKey.resize(43); + memcpy(&vKey[0], ip_tor, 41); + vKey[41] = port / 0x100; + vKey[42] = port & 0x0FF; + } + else + { + vKey.resize(18); + memcpy(&vKey[0], ip, 16); + vKey[16] = port / 0x100; + vKey[17] = port & 0x0FF; + } return vKey; } @@ -1328,7 +1396,7 @@ std::string NetworkErrorString(int err) buf[0] = 0; if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, sizeof(buf), NULL)) + buf, sizeof(buf), nullptr)) { return strprintf("%s (%d)", buf, err); } diff --git a/src/netbase.h b/src/netbase.h index fa13f1ac42..61ceaa6be1 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -1,6 +1,10 @@ -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_NETBASE_H #define BITCOIN_NETBASE_H @@ -15,7 +19,7 @@ extern int nConnectTimeout; extern bool fNameLookup; /** -timeout default */ -static const int DEFAULT_CONNECT_TIMEOUT = 5000; +static const int DEFAULT_CONNECT_TIMEOUT = 10000; #ifdef WIN32 // In MSVC, this is defined as a macro, undefine it to prevent a compile and link error @@ -29,15 +33,22 @@ enum Network NET_IPV6, NET_TOR, NET_I2P, - + NET_MAX, }; +enum AddressFormat +{ + ADDR_LEGACY = 0, + ADDR_TORV3, +}; + /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */ class CNetAddr { protected: unsigned char ip[16]; // in network byte order + unsigned char ip_tor[41]; //for compatibility with onion v3 addresses public: CNetAddr(); @@ -52,7 +63,6 @@ class CNetAddr * @note Only NET_IPV4 and NET_IPV6 are allowed for network. */ void SetRaw(Network network, const uint8_t *data); - bool SetSpecial(const std::string &strName); // for Tor addresses bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor/i2p) @@ -70,6 +80,7 @@ class CNetAddr bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96) bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) bool IsTor() const; + bool IsTorV3() const; bool IsI2P() const; bool IsLocal() const; bool IsRoutable() const; @@ -79,10 +90,11 @@ class CNetAddr std::string ToString() const; std::string ToStringIP() const; unsigned int GetByte(int n) const; + unsigned int GetByteTorV3(int n) const; uint64_t GetHash() const; bool GetInAddr(struct in_addr* pipv4Addr) const; std::vector GetGroup() const; - int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const; + int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; CNetAddr(const struct in6_addr& pipv6Addr); bool GetIn6Addr(struct in6_addr* pipv6Addr) const; @@ -93,7 +105,44 @@ class CNetAddr IMPLEMENT_SERIALIZE ( - READWRITE(FLATDATA(ip)); + CNetAddr* pthis = const_cast(this); + if (nType == SER_NETWORK && nVersion >= INIT_PROTO_VERSION && nVersion < 60042) + { + if (fRead) + pthis->Init(); + READWRITE(FLATDATA(ip)); + } + else + { + int fTorV3; + if (fRead) + { + pthis->Init(); + READWRITE(fTorV3); + if (fTorV3 == ADDR_TORV3) + { + READWRITE(FLATDATA(ip_tor)); + std::memcpy(static_cast(ip), ip_tor, sizeof(ip)); + } + else + READWRITE(FLATDATA(ip)); + } + else + { + if (pthis->IsTorV3()) + { + fTorV3 = ADDR_TORV3; + READWRITE(fTorV3); + READWRITE(FLATDATA(ip_tor)); + } + else + { + fTorV3 = ADDR_LEGACY; + READWRITE(fTorV3); + READWRITE(FLATDATA(ip)); + } + } + } ) }; @@ -154,7 +203,8 @@ class CService : public CNetAddr IMPLEMENT_SERIALIZE ( CService* pthis = const_cast(this); - READWRITE(FLATDATA(ip)); + CNetAddr* pip = static_cast(pthis); + READWRITE(*pip); unsigned short portN = htons(port); READWRITE(portN); if (fRead) @@ -176,8 +226,8 @@ bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nM bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true); bool Lookup(const char *pszName, std::vector& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0); bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); -bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); -bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); +bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = nullptr); +bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = nullptr); /** Return readable error string for a network error code */ std::string NetworkErrorString(int err); /** Close socket and set hSocket to INVALID_SOCKET */ diff --git a/src/node/context.cpp b/src/node/context.cpp new file mode 100644 index 0000000000..9af731022f --- /dev/null +++ b/src/node/context.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2019-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace node { +NodeContext::NodeContext() = default; +NodeContext::~NodeContext() = default; +} // namespace node + diff --git a/src/node/context.h b/src/node/context.h new file mode 100644 index 0000000000..94b3f48a6d --- /dev/null +++ b/src/node/context.h @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2019-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NODE_CONTEXT_H +#define BITCOIN_NODE_CONTEXT_H + +#include +#include +#include +#include +#include + +class ArgsManager; +class AddrMan; +class BanMan; +class BaseIndex; +class CBlockPolicyEstimator; +class CConnman; +class ValidationSignals; +class CScheduler; +class CTxMemPool; +class ChainstateManager; +class ECC_Context; +class NetGroupManager; +class PeerManager; +namespace interfaces { +class Chain; +class ChainClient; +class Mining; +class Init; +class WalletLoader; +} // namespace interfaces +namespace kernel { +struct Context; +} +namespace util { +class SignalInterrupt; +} + +namespace node { +class KernelNotifications; +class Warnings; + +//! NodeContext struct containing references to chain state and connection state. +//! This is used by init, rpc, and test code to pass object references around +//! without needing to declare the same variables and parameters repeatedly, or +//! to use globals. +struct NodeContext { + //! libbitcoin_kernel context + std::unique_ptr kernel; + std::unique_ptr ecc_context; + //! Init interface for initializing current process and connecting to other processes. + interfaces::Init* init{nullptr}; + //! Interrupt object used to track whether node shutdown was requested. + util::SignalInterrupt* shutdown{nullptr}; + std::unique_ptr addrman; + std::unique_ptr connman; + std::unique_ptr mempool; + std::unique_ptr netgroupman; + std::unique_ptr fee_estimator; + std::unique_ptr peerman; + std::unique_ptr chainman; + std::unique_ptr banman; + ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct + std::vector indexes; // raw pointers because memory is not managed by this struct + std::unique_ptr chain; + //! List of all chain clients (wallet processes or other client) connected to node. + std::vector> chain_clients; + //! Reference to chain client that should used to load or create wallets opened by the gui. + std::unique_ptr mining; + interfaces::WalletLoader* wallet_loader{nullptr}; + std::unique_ptr scheduler; + std::function rpc_interruption_point = [] {}; + //! Issues blocking calls about sync status, errors and warnings + std::unique_ptr notifications; + //! Issues calls about blocks and transactions + std::unique_ptr validation_signals; + std::atomic exit_status{EXIT_SUCCESS}; + //! Manages all the node warnings + std::unique_ptr warnings; + + //! Declare default constructor and destructor that are not inline + NodeContext(); + ~NodeContext(); +}; +} // namespace node + +#endif // BITCOIN_NODE_CONTEXT_H + diff --git a/src/noui.cpp b/src/noui.cpp index 262ca4fa49..47b331af86 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -1,8 +1,12 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "ui_interface.h" +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#include "interface.h" #include "init.h" #include "rpcserver.h" diff --git a/src/obj-test/.gitignore b/src/obj-test/.gitignore index d6b7ef32c8..004a3017bb 100644 --- a/src/obj-test/.gitignore +++ b/src/obj-test/.gitignore @@ -1,2 +1,8 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + * !.gitignore diff --git a/src/obj/.gitignore b/src/obj/.gitignore index d6b7ef32c8..004a3017bb 100644 --- a/src/obj/.gitignore +++ b/src/obj/.gitignore @@ -1,2 +1,8 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + * !.gitignore diff --git a/src/osx.pri b/src/osx.pri new file mode 100644 index 0000000000..446a5980d1 --- /dev/null +++ b/src/osx.pri @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +# 1. Before using autotools & make, make sure to set the macOS target platform in the shell: +# export MACOSX_DEPLOYMENT_TARGET=10.12 + +# 2. Install all libraries with homebrew: +# brew install autoconf automake libtool pkg-config openssl@1.1 libevent boost gcc wget + +# (2a optional) Fix for xCode to stop complaining about not finding the string.h file +# https://stackoverflow.com/questions/48839127/qmake-derived-clang-in-osx-10-13-cannot-find-string-h +# INCLUDEPATH += /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include + +ICON = $$PWD/qt/res/icons/alias-app.icns + +QMAKE_INFO_PLIST = $$PWD/osx/Info.plist + + # to build tor with autotools, call in subfolder tor: + # ./autogen.sh && ./configure --with-ssl-dir=/usr/local/Cellar/openssl@1.1/1.1.1 --disable-asciidoc --disable-lzma +# LIBS += -L$$PWD/../tor/src/or -ltor \ +# -L$$PWD/../tor/src/common -lor \ +# -L$$PWD/../tor/src/common -lor-ctime \ +# -L$$PWD/../tor/src/common -lor-crypto \ +# -L$$PWD/../tor/src/common -lor-event \ +# -L$$PWD/../tor/src/trunnel -lor-trunnel \ +# -L$$PWD/../tor/src/common -lcurve25519_donna \ +# -L$$PWD/../tor/src/ext/ed25519/donna -led25519_donna \ +# -L$$PWD/../tor/src/ext/ed25519/ref10 -led25519_ref10 \ +# -L$$PWD/../tor/src/ext/keccak-tiny -lkeccak-tiny \ + +# INCLUDEPATH += $$PWD/../tor/src/or $$PWD/../tor/src/common $$PWD/../tor/src/trunnel $$PWD/../tor/src/ext/ed25519/donna $$PWD/../tor/src/ext/ed25519/ref10 $$PWD/../tor/src/ext/keccak-tiny +# DEPENDPATH += $$PWD/../tor/src/or $$PWD/../tor/src/common $$PWD/../tor/src/trunnel $$PWD/../tor/src/ext/ed25519/donna $$PWD/../tor/src/ext/ed25519/ref10 $$PWD/../tor/src/ext/keccak-tiny + +# PRE_TARGETDEPS += $$PWD/../tor/src/or/libtor.a \ +# $$PWD/../tor/src/common/libor.a \ +# $$PWD/../tor/src/common/libor-ctime.a \ +# $$PWD/../tor/src/common/libor-crypto.a \ +# $$PWD/../tor/src/common/libor-event.a \ +# $$PWD/../tor/src/trunnel/libor-trunnel.a \ +# $$PWD/../tor/src/common/libcurve25519_donna.a \ +# $$PWD/../tor/src/ext/ed25519/donna/libed25519_donna.a \ +# $$PWD/../tor/src/ext/ed25519/ref10/libed25519_ref10.a \ +# $$PWD/../tor/src/ext/keccak-tiny/libkeccak-tiny.a \ + + # brew install zlib + _ZLIB_PATH = /usr/local/opt/zlib + INCLUDEPATH += "$${_ZLIB_PATH}/include/" + LIBS += -L$${_ZLIB_PATH}/lib + #Shblis-MacBook-Pro:src Shbli$ find /usr/local/Cellar/libevent/2.1.8/lib/ -name *a + LIBS += -lz + + # to build BerkeleyDB with autotools, call in subfolder db4.8: + # ./configure --enable-cxx --disable-shared --disable-replication --with-pic && make + _BERKELEY_PATH = $$PWD/../db4.8/build_unix + LIBS += $${_BERKELEY_PATH}/libdb_cxx.a \ # link static + $${_BERKELEY_PATH}/libdb.a + + DEPENDPATH += $${_BERKELEY_PATH} + INCLUDEPATH += $${_BERKELEY_PATH} + + # to build leveldb call in subfolder leveldb: + # ./build_detect_platform build_config.mk ./ && make + LIBS += -L$$PWD/../leveldb/out-static -lleveldb \ + -L$$PWD/../leveldb/out-static -lmemenv + + INCLUDEPATH += $$PWD/../leveldb/out-static + DEPENDPATH += $$PWD/../leveldb/out-static + INCLUDEPATH += $$PWD/../leveldb/include + DEPENDPATH += $$PWD/../leveldb/include + INCLUDEPATH += $$PWD/../leveldb/helpers + DEPENDPATH += $$PWD/../leveldb/helpers + + PRE_TARGETDEPS += $$PWD/../leveldb/out-static/libleveldb.a \ + $$PWD/../leveldb/out-static/libmemenv.a + + +HEADERS += $$PWD/qt/macdockiconhandler.h \ + $$PWD/qt/macnotificationhandler.h \ + +OBJECTIVE_SOURCES += $$PWD/qt/macdockiconhandler.mm \ + $$PWD/qt/macnotificationhandler.mm \ + +DEFINES += FORTIFY_SOURCE=1 + +QMAKE_LFLAGS += -fstack-protector +QMAKE_CXXFLAGS += -pthread -fPIC -fstack-protector -O2 -D_FORTIFY_SOURCE=1 -Wall -Wextra -Wno-ignored-qualifiers -Woverloaded-virtual -Wformat -Wformat-security -Wno-unused-parameter + +DEFINES += MAC_OSX +DEFINES += HAVE_BUILD_INFO +# Mac: compile for maximum compatibility (10.0 Yosemite, 32-bit) +QMAKE_CXXFLAGS += -std=c++17 -mmacosx-version-min=10.10 -isysroot + + # https://www.reddit.com/r/cpp/comments/334s4r/how_to_enable_c14_in_qt_creator_on_a_mac/ + # TODO might be obsolete with C++17: Turns out, there's a glitch in the Mac version where the standard library isn't correctly included when using the C++14 config flag. Adding this additional line to the .pro file fixes the problem: + QMAKE_CXXFLAGS += -stdlib=libc++ + + #add in core foundation framework + QMAKE_LFLAGS += -F /System/Library/Frameworks/CoreFoundation.framework/ + LIBS += -framework CoreFoundation + + QMAKE_LFLAGS += -F /System/Library/Frameworks/AppKit.framework/ + LIBS += -framework AppKit + + QMAKE_LFLAGS += -F /System/Library/Frameworks/ApplicationServices.framework/ + LIBS += -framework ApplicationServices + + + #brew install boost + # $BOOST_PATH is set via environment +# _BOOST_PATH = /usr/local/Cellar/boost/1.68.0_1 +# BOOST_PATH = /usr/local/Cellar/boost/1.68.0_1 + INCLUDEPATH += "${BOOST_PATH}/include/" + LIBS += -L${BOOST_PATH}/lib + LIBS += -lboost_system-mt -lboost_chrono-mt -lboost_filesystem-mt -lboost_program_options-mt -lboost_thread-mt -lboost_unit_test_framework-mt -lboost_timer-mt # using dynamic lib (not sure if you need that "-mt" at the end or not) + DEFINES += BOOST_ASIO_ENABLE_OLD_SERVICES BOOST_SPIRIT_THREADSAFE BOOST_THREAD_USE_LIB BOOST_THREAD_POSIX BOOST_HAS_THREADS + #LIBS += ${BOOST_PATH}/lib/libboost_chrono-mt.a # using static lib + + #brew install openssl@1.1 + # $OPENSSL_PATH is set via environment +# _OPENSSL_PATH = /usr/local/Cellar/openssl@1.1/1.1.1 +# OPENSSL_PATH = /usr/local/Cellar/openssl@1.1/1.1.0h + # See http://doc.qt.io/archives/qt-4.8/qmake-advanced-usage.html#variables + INCLUDEPATH += "${OPENSSL_PATH}/include/" + LIBS += -L${OPENSSL_PATH}/lib + LIBS += -lssl -lcrypto # using dynamic lib (not sure if you need that "-mt" at the end or not) + + #libevent-2.1.6.dylib + #brew install libevent +# _LIBEVENT_PATH = /usr/local/Cellar/libevent/2.1.8 + _LIBEVENT_PATH = /usr/local/Cellar/libevent/2.1.11_1 + INCLUDEPATH += "$${_LIBEVENT_PATH}/include/" + LIBS += -L$${_LIBEVENT_PATH}/lib + #Shblis-MacBook-Pro:src Shbli$ find /usr/local/Cellar/libevent/2.1.8/lib/ -name *a + LIBS += -levent_extra -levent -levent_core -levent_openssl -levent_pthreads diff --git a/src/osx/MacOSXBundleInfo.plist.in b/src/osx/MacOSXBundleInfo.plist.in new file mode 100644 index 0000000000..ae63f54b96 --- /dev/null +++ b/src/osx/MacOSXBundleInfo.plist.in @@ -0,0 +1,42 @@ + + + + + + + + + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundleExecutable + Alias + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleDisplayName + Alias + CFBundleIconFile + alias-app.icns + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + LSMinimumSystemVersion + 10.14 + NSPrincipalClass + NSApplication + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + NSSupportsAutomaticGraphicsSwitching + + NOTE + This file was initially generated by Qt/QMake automatically updated during CMake build + + diff --git a/src/osx/app-slide-arrow.png b/src/osx/app-slide-arrow.png new file mode 100644 index 0000000000..cf2f08bc4c Binary files /dev/null and b/src/osx/app-slide-arrow.png differ diff --git a/src/osx/torrc-defaults b/src/osx/torrc-defaults new file mode 100644 index 0000000000..633358ce05 --- /dev/null +++ b/src/osx/torrc-defaults @@ -0,0 +1,27 @@ +# torrc-defaults for Spectrecoin +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# DO NOT EDIT THIS FILE +# +# This file is distributed with Spectrecoin within the tor folder and SHOULD NOT be modified +# (it may be overwritten during the next Spectrecoin update). +# To customize your Tor configuration, shut down Spectrecoin and edit the torrc file. +# +# If non-zero, try to write to disk less frequently than we would otherwise. +AvoidDiskWrites 1 + +# If non-zero, try to use built-in (static) crypto hardware acceleration when available. +HardwareAccel 1 + +## obfs4proxy configuration +ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec PluggableTransports/obfs4proxy + +## meek configuration +#ClientTransportPlugin meek exec PluggableTransports/meek-client-torbrowser -- PluggableTransports/meek-client + +## snowflake configuration +ClientTransportPlugin snowflake exec PluggableTransports/snowflake-client -url https://snowflake-broker.azureedge.net/ -front ajax.aspnetcdn.com -ice stun:stun.l.google.com:19302 \ No newline at end of file diff --git a/src/osx/torrc-defaults_obfs4 b/src/osx/torrc-defaults_obfs4 new file mode 100644 index 0000000000..cc9a269429 --- /dev/null +++ b/src/osx/torrc-defaults_obfs4 @@ -0,0 +1,57 @@ +# torrc-defaults for Spectrecoin +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# DO NOT EDIT THIS FILE +# +# This file is distributed with Spectrecoin within the tor folder and SHOULD NOT be modified +# (it may be overwritten during the next Spectrecoin update). +# To customize your Tor configuration, shut down Spectrecoin and edit the torrc file. +# +# If non-zero, try to write to disk less frequently than we would otherwise. +AvoidDiskWrites 1 + +# If non-zero, try to use built-in (static) crypto hardware acceleration when available. +HardwareAccel 1 + +## obfs4proxy configuration +ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec PluggableTransports/obfs4proxy + +## meek configuration +#ClientTransportPlugin meek exec PluggableTransports/meek-client-torbrowser -- PluggableTransports/meek-client + +## snowflake configuration +ClientTransportPlugin snowflake exec PluggableTransports/snowflake-client -url https://snowflake-broker.azureedge.net/ -front ajax.aspnetcdn.com -ice stun:stun.l.google.com:19302 + +## preconfigured OBFS4 bridges +Bridge obfs4 154.35.22.9:12166 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 154.35.22.9:443 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1 +Bridge obfs4 154.35.22.13:443 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 +Bridge obfs4 192.99.11.54:443 7B126FAB960E5AC6A629C729434FF84FB5074EC2 cert=VW5f8+IBUWpPFxF+rsiVy2wXkyTQG7vEd+rHeN2jV5LIDNu8wMNEOqZXPwHdwMVEBdqXEw iat-mode=0 +Bridge obfs4 154.35.22.12:80 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 85.17.30.79:443 FC259A04A328A07FED1413E9FC6526530D9FD87A cert=RutxZlu8BtyP+y0NX7bAVD41+J/qXNhHUrKjFkRSdiBAhIHIQLhKQ2HxESAKZprn/lR3KA iat-mode=0 +Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 216.252.162.21:46089 0DB8799466902192B6C7576D58D4F7F714EC87C1 cert=XPUwcQPxEXExHfJYX58gZXN7mYpos7VNAHbkgERNFg+FCVNzuYo1Wp+uMscl3aR9hO2DRQ iat-mode=0 +Bridge obfs4 109.105.109.147:13764 BBB28DF0F201E706BE564EFE690FE9577DD8386D cert=KfMQN/tNMFdda61hMgpiMI7pbwU1T+wxjTulYnfw+4sgvG0zSH7N7fwT10BI8MUdAD7iJA iat-mode=2 +Bridge obfs4 154.35.22.10:80 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.11:443 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 83.212.101.3:50002 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0 +Bridge obfs4 109.105.109.165:10527 8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E cert=Bvg/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+/TfB7mqTFEfXILCjEwzVA iat-mode=1 +Bridge obfs4 154.35.22.11:80 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.12:4304 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 154.35.22.11:16488 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.9:80 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 +Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 +Bridge obfs4 154.35.22.10:443 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.13:16815 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 [2001:470:b381:bfff:216:3eff:fe23:d6c3]:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWODcgqIdPJ+rRupg4GGvVGfh25FWaIXZkit206OSngsp7GAIiGIXOJJROMxEqFKJg iat-mode=1 +Bridge obfs4 154.35.22.10:15937 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 +UseBridges 1 \ No newline at end of file diff --git a/src/pbkdf2.cpp b/src/pbkdf2.cpp index 6d3f3dcc5a..bcc836894f 100644 --- a/src/pbkdf2.cpp +++ b/src/pbkdf2.cpp @@ -1,17 +1,13 @@ -// Copyright (c) 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// +// SPDX-License-Identifier: MIT #include #include "pbkdf2.h" -static inline uint32_t -be32dec(const void *pp) -{ - const uint8_t *p = (uint8_t const *)pp; - - return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + - ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); -} - static inline void be32enc(void *pp, uint32_t x) { @@ -23,8 +19,6 @@ be32enc(void *pp, uint32_t x) p[0] = (x >> 24) & 0xff; } - - /* Initialize an HMAC-SHA256 operation with the given key. */ void HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) diff --git a/src/pbkdf2.h b/src/pbkdf2.h index 4c55fd919c..1be29e16eb 100644 --- a/src/pbkdf2.h +++ b/src/pbkdf2.h @@ -1,4 +1,9 @@ -// Copyright (c) 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// +// SPDX-License-Identifier: MIT #ifndef PBKDF2_H #define PBKDF2_H diff --git a/src/pos/kernel.cpp b/src/pos/kernel.cpp new file mode 100644 index 0000000000..6713983b42 --- /dev/null +++ b/src/pos/kernel.cpp @@ -0,0 +1,417 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 PPCoin Developers +// Copyright (c) 2017-2024 The Particl Core developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include

Total Balance (out of sync)


0 . 00 SDC

Balances


Public0.00
Private0.00
Reserved0.00
Stake0.00
Unconfirmed0.00
Immature0.00

Recent Transactions


Type
Amount
Date
DateTypeAddressNarrationAmount
Coin ValueOwned (Mature)System (Mature)SpendsLeast Depth
HashHeightTimestampTransactions
Transaction HashValue Out

Optional transaction fee per kB that helps make sure your transactions are processed quickly.

Most transactions are 1kB. Fee 0.01 recommended.

Reserved amount does not participate in staking and is therefore spendable at any time.

I2P (coming soon)
TOR (coming soon)

Lets create a New Wallet and Account to get you started!



Add an optional Password to secure the Recovery Phrase (shown on next page)
Next Step

Write your Wallet Recovery Phrase


You need the Wallet Recovery Phrase to restore this wallet. Write it down and keep them somewhere safe.
You will be asked to confirm the Wallet Recovery Phrase in the next screen to ensure you have written it down correctly
Back
Next Step

Please confirm your Wallet Recovery Phrase


Back
Next Step

Congratulations! You have successfully created a New Wallet and Account




You can now use your Account to send and receive funds :)
Remember to keep your Wallet Recovery Phrase and Password (if set) safe in case you ever need to recover your wallet



+Alias

Total Balance (out of sync)


0 . 00

BalancePublic
Private
Available
0.000.00
Reserved
0.000.00
Stake
0.000.00
Unconfirmed
0.000.00
Immature
0.000.00

Recent Transactions


TypeAmountDate
Automatically selected
Balance: 0.00 ALIAS 0.00 ALIAS
Balance: 0.00 ALIAS 0.00 ALIAS
(no label)
DateValueTypeAddressNote
ValueOwned (*)Unspent (*)Mixins (*)System (**)Least Depth
HashHeightTimestampTransactions
Transaction HashValue Out

Transaction fee per kB. A higher fee makes sure your transactions are processed quickly in times of high transaction volume.

Most transactions are 1kB. The minimal fee is 0.0001

Enables or disables the staking process. If your wallet is encrypted, you will need to unlock it for staking.

Every sixth block on the blockchain is a development contribution block (DCB). Staking rewards of DCBs are contributed to the development fund no matter the donation percentage setting. Please feel free to additionally donate from your remaining stake rewards by defining a donation chance. Thank you.

%

Reserved amount does not participate in staking and is therefore spendable at any time.

I2P (coming soon)
TOR (Active)
diff --git a/src/qt/res/qml/main.qml b/src/qt/res/qml/main.qml new file mode 100755 index 0000000000..27c5b5254b --- /dev/null +++ b/src/qt/res/qml/main.qml @@ -0,0 +1,17 @@ +import QtQuick 2.9 +import QtWebView 1.1 + +Item { + id: webViewRootItem + visible: true + WebView { + visible: true + id: webView + objectName: "webView" + anchors.fill: parent + onLoadingChanged: { + if (loadRequest.errorString) + { console.error(loadRequest.errorString); } + } + } +} diff --git a/src/qt/res/src/alias-app-white.svg b/src/qt/res/src/alias-app-white.svg new file mode 100644 index 0000000000..f9aa1585f2 --- /dev/null +++ b/src/qt/res/src/alias-app-white.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/src/qt/res/src/bitcoin.svg b/src/qt/res/src/bitcoin.svg index 96f10178a2..acd7b73e15 100644 --- a/src/qt/res/src/bitcoin.svg +++ b/src/qt/res/src/bitcoin.svg @@ -73,7 +73,7 @@ gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" - inkscape:pageshadow="2" + inkscape:pagespectre="2" inkscape:window-width="1204" inkscape:window-height="972" id="namedview4" @@ -88,7 +88,7 @@ setupUi(this); //GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this); -#ifndef Q_OS_MAC +#ifndef Q_OS_MACOS ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export")); ui->showCLOptionsButton->setIcon(QIcon(":/icons/options")); #endif ui->clearButton->setIcon(QIcon(":/icons/remove")); - + // Install event filter for up and down arrow ui->lineEdit->installEventFilter(this); ui->messagesWidget->installEventFilter(this); @@ -220,7 +209,12 @@ RPCConsole::RPCConsole(QWidget *parent) : connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); // set library version labels +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION)); +#else + ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION)); +#endif + ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); startExecutor(); @@ -297,9 +291,15 @@ void RPCConsole::setClientModel(ClientModel *model) ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows); ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection); + ui->peerWidget->setColumnWidth(PeerTableModel::NetNodeId, NETNODEID_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Age, AGE_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH); - ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Direction, DIRECTION_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Network, NETWORK_COLUMN_WIDTH); ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Sent, SENT_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Received, RECEIVED_COLUMN_WIDTH); + ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH); // connect the peerWidget selection model to our peerSelected() handler connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), @@ -312,7 +312,7 @@ void RPCConsole::setClientModel(ClientModel *model) ui->buildDate->setText(model->formatBuildDate()); ui->startupTime->setText(model->formatClientStartupTime()); - ui->networkName->setText(QString::fromStdString(Params().NetworkIDString())); + ui->networkName->setText(QString::fromStdString(ChainParamsMigration::GetNetworkIDString())); } } @@ -334,10 +334,10 @@ void RPCConsole::clear() historyPtr = 0; ui->lineEdit->clear(); ui->lineEdit->setFocus(); - - - QColor colour(226, 29, 57); - + + + QColor colour(242, 131, 33); + // Add smoothly scaled icon images. // (when using width/height on an img, Qt uses nearest instead of linear interpolation) for(int i=0; ICON_MAPPING[i].url; ++i) @@ -358,7 +358,7 @@ void RPCConsole::clear() "b { color: #006060; } " ); - message(CMD_REPLY, (tr("Welcome to the Shadow Core RPC console.") + "
" + + message(CMD_REPLY, (tr("Welcome to the Alias Core RPC console.") + "
" + tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" + tr("Type help for an overview of available commands.")), true); } @@ -402,11 +402,7 @@ void RPCConsole::setNumConnections(int count) void RPCConsole::setNumBlocks(int count, int countOfPeers) { ui->numberOfBlocks->setText(QString::number(count)); - QDateTime lastBlockDate; - if (nNodeMode == NT_FULL) - lastBlockDate = clientModel->getLastBlockDate(); - else - lastBlockDate = clientModel->getLastBlockThinDate(); + QDateTime lastBlockDate = clientModel->getLastBlockDate(); ui->lastBlockTime->setText(lastBlockDate.toString()); } @@ -530,7 +526,7 @@ void RPCConsole::peerLayoutChanged() if (!clientModel) return; - const CNodeCombinedStats *stats = NULL; + const CNodeCombinedStats *stats = nullptr; bool fUnselect = false; bool fReselect = false; diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 9e3afe7123..2d8be7976d 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -1,6 +1,9 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_QT_RPCCONSOLE_H #define BITCOIN_QT_RPCCONSOLE_H @@ -22,6 +25,19 @@ QT_BEGIN_NAMESPACE class QItemSelection; QT_END_NAMESPACE +/* Object for executing console RPC commands in a separate thread. +*/ +class RPCExecutor : public QObject +{ + Q_OBJECT + +public slots: + void request(const QString &command); + +signals: + void reply(int category, const QString &command); +}; + /** Local RPC console. */ class RPCConsole: public QDialog { @@ -90,9 +106,15 @@ public slots: enum ColumnWidths { + NETNODEID_COLUMN_WIDTH = 50, + AGE_COLUMN_WIDTH = 50, ADDRESS_COLUMN_WIDTH = 200, - SUBVERSION_COLUMN_WIDTH = 100, - PING_COLUMN_WIDTH = 80 + DIRECTION_COLUMN_WIDTH = 70, + NETWORK_COLUMN_WIDTH = 60, + PING_COLUMN_WIDTH = 60, + SENT_COLUMN_WIDTH = 70, + RECEIVED_COLUMN_WIDTH = 70, + SUBVERSION_COLUMN_WIDTH = 100 }; Ui::RPCConsole *ui; diff --git a/src/qt/scicon.cpp b/src/qt/scicon.cpp index a0ffcd82a9..e4851deebb 100644 --- a/src/qt/scicon.cpp +++ b/src/qt/scicon.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "scicon.h" diff --git a/src/qt/scicon.h b/src/qt/scicon.h index 1388069ddb..3e6154f661 100644 --- a/src/qt/scicon.h +++ b/src/qt/scicon.h @@ -1,6 +1,9 @@ -// Copyright (c) 2014 The Bitcoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_QT_SCICON_H #define BITCOIN_QT_SCICON_H diff --git a/src/qt/setupwalletwizard.cpp b/src/qt/setupwalletwizard.cpp new file mode 100644 index 0000000000..26cb03d3fe --- /dev/null +++ b/src/qt/setupwalletwizard.cpp @@ -0,0 +1,719 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +#include "setupwalletwizard.h" +#include "extkey.h" +#include "util.h" +#include "guiutil.h" +#include "guiconstants.h" +#include "base58.h" +#include "wallet.h" + +#include +#include + + +SetupWalletWizard::SetupWalletWizard(QWidget *parent) + : QWizard(parent) +{ + setPage(Page_Intro, new IntroPage); + setPage(Page_ImportWalletDat, new ImportWalletDatPage); + setPage(Page_NewMnemonic_Settings, new NewMnemonicSettingsPage); + setPage(Page_NewMnemonic_Result, new NewMnemonicResultPage); + setPage(Page_NewMnemonic_Verification, new NewMnemonicVerificationPage); + setPage(Page_RecoverFromMnemonic, new RecoverFromMnemonicPage); + setPage(Page_EncryptWallet, new EncryptWalletPage); + + setStartId(Page_Intro); + +//#ifndef Q_OS_MACOS + setWizardStyle(ModernStyle); +//#endif + setOption(HaveHelpButton, true); + + setPixmap(QWizard::LogoPixmap, GUIUtil::createPixmap(QString(":/assets/svg/alias-app.svg"), 48, 48)); + + connect(this, &QWizard::helpRequested, this, &SetupWalletWizard::showHelp); + + setWindowTitle(tr("Alias Wallet Setup")); + setWindowIcon(QIcon(":icons/alias-app")); +} + +void SetupWalletWizard::showHelp() +{ + static QString lastHelpMessage; + + QString message; + + switch (currentId()) { + case Page_Intro: + message = tr("The file 'wallet.dat', which holds your private keys, could not be found during startup. It must be created now.

" + "The private key consists of alphanumerical characters that give a user access and control over their funds to their corresponding cryptocurrency address. In other words, the private key creates unique digital signatures for every transaction that enable a user to spend their funds, by proving that the user does in fact have ownership of those funds."); + break; + case Page_ImportWalletDat: + message = tr("If you have a backup of a wallet.dat, you can import this file."); + break; + case Page_NewMnemonic_Settings: + message = tr("Mnemonic Seed Words allow you to create and later recover your private keys. " + "The seed consists of 24 words and the optional password functions as a 25th word that you can keep secret to protect your seed."); + break; + case Page_NewMnemonic_Result: + message = tr("It is recommended to make multiple copies of the seed words, stored in different locations.

" + "Attention: Seed Words cannot later be (re)created from your exsting private keys.
" + "If you you loose your Seed Words and don't have a backup of the wallet.dat file, you loose your coins!"); + break; + case Page_NewMnemonic_Verification: + message = tr("Please enter the mnemonic words and password given on the previous screen."); + break; + case Page_RecoverFromMnemonic: + message = tr("Please enter your mnemonic words and (optional) password."); + break; + default: + message = tr("This help is likely not to be of any help."); + } + + QMessageBox::information(this, tr("Alias Wallet Setup Help"), message); + + lastHelpMessage = message; +} + +IntroPage::IntroPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Set Up Your Wallet")); + + setPixmap(QWizard::WatermarkPixmap, GUIUtil::createPixmap(96, 400, QColor(55, 43, 62), QString(":/assets/svg/Alias-Stacked-Reverse.svg"), QRect(3, 155, 90, 90))); + + topLabel = new QLabel(tr("The application has detected that you don't have a wallet.dat file, which holds your private keys. Please choose how you want to create or restore your private keys.")); + topLabel->setWordWrap(true); + + newMnemonicRadioButton = new QRadioButton(tr("&Create new mnemonic recovery seed words")); + recoverFromMnemonicRadioButton = new QRadioButton(tr("&Recover from your existing mnemonic seed words")); + importWalletRadioButton = new QRadioButton(tr("&Import wallet.dat file")); + newMnemonicRadioButton->setChecked(true); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(topLabel); + layout->addSpacing(20); + layout->addWidget(newMnemonicRadioButton); + layout->addWidget(recoverFromMnemonicRadioButton); + layout->addWidget(importWalletRadioButton); + setLayout(layout); +} + +int IntroPage::nextId() const +{ + if (importWalletRadioButton->isChecked()) { + return SetupWalletWizard::Page_ImportWalletDat; + } else if (recoverFromMnemonicRadioButton->isChecked()) { + return SetupWalletWizard::Page_RecoverFromMnemonic; + } else { + return SetupWalletWizard::Page_NewMnemonic_Settings; + } +} + +ImportWalletDatPage::ImportWalletDatPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Import wallet.dat")); + setSubTitle(tr("Please import a wallet.dat file with your private keys.")); + + openFileNameLabel = new QLabel; + openFileNameLabel->setWordWrap(true); + openFileNameLabel->setFrameStyle(QFrame::Panel); + + openFileNameButton = new QPushButton(tr("&Select wallet.dat")); + QVBoxLayout *buttonLayout = new QVBoxLayout; + buttonLayout->setAlignment(Qt::AlignRight | Qt::AlignTop); + buttonLayout->addWidget(openFileNameButton); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(openFileNameLabel); + layout->addLayout(buttonLayout); + setLayout(layout); + + connect(openFileNameButton, &QAbstractButton::clicked, + this, &ImportWalletDatPage::setOpenFileName); +} + +void ImportWalletDatPage::setOpenFileName() +{ + const QFileDialog::Options options = QFileDialog::Options(); + QString selectedFilter; + fileName = QFileDialog::getOpenFileName(this, + tr("QFileDialog::getOpenFileName()"), + openFileNameLabel->text(), + tr("Wallet Files (*.dat)"), + &selectedFilter, + options); + + openFileNameLabel->setText(fileName); + + completeChanged(); +} + +int ImportWalletDatPage::nextId() const +{ + return -1; +} + +bool ImportWalletDatPage::isComplete() const +{ + return fileName.size() > 0; +} + +bool ImportWalletDatPage::validatePage() +{ + try { + fs::copy_file(fs::path(fileName.toStdWString()), GetDataDir() / "wallet.dat"); + return true; + } + catch (const std::filesystem::filesystem_error& e) { + QMessageBox::critical(this, tr("Error"), tr("Failed to copy wallet.dat: %1").arg(e.what())); + } + return false; +} + +NewMnemonicSettingsPage::NewMnemonicSettingsPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Create private keys with Mnemonic Recovery Seed Words")); + setSubTitle(tr("Step 1/3: Please define language to use and optional password to protect your seed.")); + + noteLabel = new QLabel(tr("Creating mnemonic seed words is a three step procedure:" + "
  1. Define language and optional password for your seed.
  2. " + "
  3. Write down created seed words.
  4. " + "
  5. Verify seed words and seed password.
")); + noteLabel->setWordWrap(true); + + languageLabel = new QLabel(tr("&Language:")); + languageComboBox = new QComboBox; + languageLabel->setBuddy(languageComboBox); + + languageComboBox->addItem("English", 1); + languageComboBox->addItem("French", 2); + languageComboBox->addItem("Japanese", 3); + languageComboBox->addItem("Spanish", 4); + languageComboBox->addItem("Chinese (Simplified)", 5); + languageComboBox->addItem("Chinese (Traditional)", 6); + + passwordLabel = new QLabel(tr("&Seed Password:")); + passwordEdit = new QLineEdit; + passwordEdit->setEchoMode(QLineEdit::Password); + passwordLabel->setBuddy(passwordEdit); + registerField("newmnemonic.password", passwordEdit); + connect(passwordEdit, &QLineEdit::textChanged, this, &NewMnemonicSettingsPage::completeChanged); + + passwordVerifyLabel = new QLabel(tr("&Verify Password:")); + passwordVerifyEdit = new QLineEdit; + passwordVerifyEdit->setEchoMode(QLineEdit::Password); + passwordVerifyLabel->setBuddy(passwordVerifyEdit); + registerField("newmnemonic.passwordverify", passwordVerifyEdit); + connect(passwordVerifyEdit, &QLineEdit::textChanged, this, &NewMnemonicSettingsPage::completeChanged); + + registerField("newmnemonic.language", languageComboBox, "currentData", "currentIndexChanged"); + + QVBoxLayout *layout = new QVBoxLayout; + + QGridLayout *formLayout = new QGridLayout; + formLayout->addWidget(languageLabel, 0, 0); + formLayout->addWidget(languageComboBox, 0, 1); + formLayout->addWidget(passwordLabel, 1, 0); + formLayout->addWidget(passwordEdit, 1, 1); + formLayout->addWidget(passwordVerifyLabel, 2, 0); + formLayout->addWidget(passwordVerifyEdit, 2, 1); + layout->addLayout(formLayout); + + noteLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + layout->addWidget(noteLabel, Qt::AlignBottom); + + setLayout(layout); +} + +int NewMnemonicSettingsPage::nextId() const +{ + return SetupWalletWizard::Page_NewMnemonic_Result; +} + +void NewMnemonicSettingsPage::cleanupPage() +{ + QWizardPage::cleanupPage(); + sKey.clear(); + mnemonicList.clear(); +} + +bool NewMnemonicSettingsPage::isComplete() const +{ + QString sPassword = field("newmnemonic.password").toString(); + QString sVerificationPassword = field("newmnemonic.passwordverify").toString(); + return sPassword == sVerificationPassword; +} + +bool NewMnemonicSettingsPage::validatePage() +{ + QString sPassword = field("newmnemonic.password").toString(); + int nLanguage = field("newmnemonic.language").toInt(); + + QVariantMap result; + + int nBytesEntropy = 32; + std::string sError; + std::vector vEntropy; + std::vector vSeed; + std::string sMnemonic; + CExtKey ekMaster; + + sKey.clear(); + mnemonicList.clear(); + + RandAddSeedPerfmon(); + for (uint32_t i = 0; i < MAX_DERIVE_TRIES; ++i) + { + sError.clear(); + GetRandBytes(vEntropy, nBytesEntropy); + + if (0 != MnemonicEncode(nLanguage, vEntropy, sMnemonic, sError)) + break; + + if (0 != MnemonicToSeed(sMnemonic, sPassword.normalized(QString::NormalizationForm_KD).toStdString(), vSeed)) + { + sError = "MnemonicToSeed failed."; + break; + } + + ekMaster.SetMaster(&vSeed[0], vSeed.size()); + if (!ekMaster.IsValid()) + { + sError = "Generated seed is not a valid key."; + continue; + } + + CExtKey58 eKey58; + eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY_BTC); + sKey = eKey58.ToString(); + + break; + }; + + if (sKey.empty()) + { + QMessageBox::critical(this, tr("Error"), tr("Failed to create Mnemonic Seed Words. %1").arg(sError.c_str())); + return false; + } + + if (nLanguage == WLL_JAPANESE) + mnemonicList = QString::fromStdString(sMnemonic).split("\u3000"); + else + mnemonicList = QString::fromStdString(sMnemonic).split(" "); + + if (mnemonicList.size() != 24) + throw std::runtime_error(strprintf("%s : Error splitting mnemonic words. 24 words expected!", __func__).c_str()); + + return true; +} + +NewMnemonicResultPage::NewMnemonicResultPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Create private keys with Mnemonic Recovery Seed Words")); + setSubTitle(tr("Step 2/3: Write down your mnemonic recovery seed words.")); + + mnemonicLabel = new QLabel(tr("Mnemonic Recovery Seed Words:")); + noticeLabel = new QLabel(tr("You need the Mnemonic Recovery Seed Words to restore this wallet. Write them down and keep them somewhere safe.
You will be asked to confirm the Recovery Seed Words in the next screen to ensure you have written it down correctly.")); + noticeLabel->setWordWrap(true); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(mnemonicLabel, 0, 0, 1, 4); + + vMnemonicResultLabel.reserve(24); + for (int i = 0; i < 24; i++) + { + vMnemonicResultLabel.push_back(new QLabel); + layout->addWidget(vMnemonicResultLabel[i], i / 4 + 1, i % 4); + } + + layout->addWidget(noticeLabel, 8, 0, 4, 4, Qt::AlignBottom); + setLayout(layout); +} + +int NewMnemonicResultPage::nextId() const +{ + return SetupWalletWizard::Page_NewMnemonic_Verification; +} + +void NewMnemonicResultPage::initializePage() +{ + NewMnemonicSettingsPage* mnemonicPage = (NewMnemonicSettingsPage*)wizard()->page(SetupWalletWizard::Page_NewMnemonic_Settings); + for (int i = 0; i < 24; i++) + vMnemonicResultLabel[i]->setText(QString("%1. %2").arg(i + 1, 2).arg(mnemonicPage->mnemonicList[i])); +} + +void NewMnemonicVerificationPage::initializePage() +{ + passwordEdit->setStyleSheet(""); + passwordEdit->setReadOnly(false); + for (int i = 0; i < 24; i++) + { + vMnemonicEdit[i]->setStyleSheet(""); + vMnemonicEdit[i]->setReadOnly(false); + } +} + +bool NewMnemonicVerificationPage::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::FocusOut) + { + if (obj == passwordEdit) + { + + QString sPassword = field("newmnemonic.password").toString(); + if (sPassword != passwordEdit->text()) + passwordEdit->setStyleSheet("QLineEdit { background: rgba(255, 0, 0, 30); }"); + else { + passwordEdit->setStyleSheet("QLineEdit { background: rgba(0, 255, 0, 30); }"); + passwordEdit->setReadOnly(true); + } + } + else { + for (int i = 0; i < 24; i++) + { + QLineEdit* pLineEdit = vMnemonicEdit[i]; + if (pLineEdit != obj) + continue; + + NewMnemonicSettingsPage* mnemonicPage = (NewMnemonicSettingsPage*)wizard()->page(SetupWalletWizard::Page_NewMnemonic_Settings); + if (pLineEdit->text().size() == 0) + pLineEdit->setStyleSheet(""); + else if (mnemonicPage->mnemonicList[i] != pLineEdit->text().normalized(QString::NormalizationForm_KD)) + pLineEdit->setStyleSheet("QLineEdit { background: rgba(255, 0, 0, 30); }"); + else { + pLineEdit->setStyleSheet("QLineEdit { background: rgba(0, 255, 0, 30); }"); + pLineEdit->setReadOnly(true); + } + break; + } + } + } + + // standard event processing + return QObject::eventFilter(obj, event); +} + +NewMnemonicVerificationPage::NewMnemonicVerificationPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Create private keys with Mnemonic Recovery Seed Words")); + setSubTitle(tr("Step 3/3: Verify you have the correct words and (optional) password noted.")); + + passwordLabel = new QLabel(tr("&Seed Password:")); + passwordEdit = new QLineEdit; + passwordEdit->setEchoMode(QLineEdit::Password); + passwordEdit->installEventFilter(this); + passwordLabel->setBuddy(passwordEdit); + registerField("verification.password", passwordEdit); + connect(passwordEdit, &QLineEdit::textChanged, this, &NewMnemonicVerificationPage::completeChanged); + + mnemonicLabel = new QLabel(tr("
Enter Mnemonic Seed Words:")); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(passwordLabel, 0, 0); + layout->addWidget(passwordEdit, 0, 1, 1, 3); + layout->addWidget(mnemonicLabel, 1, 0, 1, 4); + + vMnemonicEdit.reserve(24); + for (int i = 0; i < 24; i++) + { + QLineEdit *qLineEdit = new QLineEdit; + qLineEdit->installEventFilter(this); + vMnemonicEdit.push_back(qLineEdit); + registerField(QString("verification.mnemonic.%1*").arg(i), vMnemonicEdit[i]); + + QFormLayout *formLayout = new QFormLayout; + formLayout->addRow(QString("%1.").arg(i + 1, 2), vMnemonicEdit[i]); + layout->addLayout(formLayout, i / 4 + 2, i % 4); + } + + setLayout(layout); +} + +int NewMnemonicVerificationPage::nextId() const +{ + return SetupWalletWizard::Page_EncryptWallet; +} + +bool NewMnemonicVerificationPage::isComplete() const +{ + QString sPassword = field("newmnemonic.password").toString(); + QString sVerificationPassword = field("verification.password").toString(); + if (sPassword != sVerificationPassword) + return false; + + NewMnemonicSettingsPage* mnemonicPage = (NewMnemonicSettingsPage*)wizard()->page(SetupWalletWizard::Page_NewMnemonic_Settings); + for (int i = 0; i < 24; i++) + { + QString sVerificationMnemonic = field(QString("verification.mnemonic.%1").arg(i)).toString().normalized(QString::NormalizationForm_KD); + if (mnemonicPage->mnemonicList[i].compare(sVerificationMnemonic, Qt::CaseInsensitive) != 0) + return false; + } + return true; +} + +RecoverFromMnemonicPage::RecoverFromMnemonicPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Recover private keys from Mnemonic Seed Words")); + setSubTitle(tr("Please enter (optional) password and your mnemonic seed words to recover private keys.")); + + passwordLabel = new QLabel(tr("&Seed Password:")); + passwordEdit = new QLineEdit; + passwordEdit->setEchoMode(QLineEdit::Password); + passwordEdit->installEventFilter(this); + passwordLabel->setBuddy(passwordEdit); + registerField("recover.password", passwordEdit); + connect(passwordEdit, &QLineEdit::textChanged, this, &RecoverFromMnemonicPage::completeChanged); + + passwordVerifyLabel = new QLabel(tr("&Verify Password:")); + passwordVerifyEdit = new QLineEdit; + passwordVerifyEdit->setEchoMode(QLineEdit::Password); + passwordVerifyEdit->installEventFilter(this); + passwordVerifyLabel->setBuddy(passwordVerifyEdit); + registerField("recover.passwordverify", passwordVerifyEdit); + connect(passwordVerifyEdit, &QLineEdit::textChanged, this, &RecoverFromMnemonicPage::completeChanged); + + mnemonicLabel = new QLabel(tr("
Enter Mnemonic Seed Words:")); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(passwordLabel, 0, 0); + layout->addWidget(passwordEdit, 0, 1, 1, 3); + layout->addWidget(passwordVerifyLabel, 1, 0); + layout->addWidget(passwordVerifyEdit, 1, 1, 1, 3); + layout->addWidget(mnemonicLabel, 2, 0, 1, 4); + + vMnemonicEdit.reserve(24); + for (int i = 0; i < 24; i++) + { + vMnemonicEdit.push_back(new QLineEdit); + registerField(QString("recover.mnemonic.%1*").arg(i), vMnemonicEdit[i]); + + QFormLayout *formLayout = new QFormLayout; + formLayout->addRow(QString("%1.").arg(i + 1, 2), vMnemonicEdit[i]); + layout->addLayout(formLayout, i / 4 + 3, i % 4); + } + + setLayout(layout); +} + +int RecoverFromMnemonicPage::nextId() const +{ + return SetupWalletWizard::Page_EncryptWallet; +} + +bool RecoverFromMnemonicPage::isComplete() const +{ + QString sPassword = field("recover.password").toString(); + QString sVerificationPassword = field("recover.passwordverify").toString(); + + if (sPassword != sVerificationPassword) + return false; + + for (int i = 0; i < 24; i++) + { + if (field(QString("recover.mnemonic.%1").arg(i)).toString().isEmpty()) + return false; + } + return true; +} + +bool RecoverFromMnemonicPage::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::FocusOut) + { + if (obj == passwordVerifyEdit || obj == passwordEdit) + { + QString sPassword = field("recover.password").toString(); + QString sPasswordVerify = field("recover.passwordverify").toString(); + + if (sPasswordVerify.length() > 0) + { + if (sPassword != sPasswordVerify) + passwordVerifyEdit->setStyleSheet("QLineEdit { background: rgba(255, 0, 0, 30); }"); + else + passwordVerifyEdit->setStyleSheet("QLineEdit { background: rgba(0, 255, 0, 30); }"); + } + else { + passwordVerifyEdit->setStyleSheet(""); + } + } + } + + // standard event processing + return QObject::eventFilter(obj, event); +} + +bool RecoverFromMnemonicPage::validatePage() +{ + QString sPassword = field("recover.password").toString().normalized(QString::NormalizationForm_KD); + QString sMnemonic; + for (int i = 0; i < 24; i++) + { + if (i != 0) + sMnemonic.append(" "); + QString sWord = field(QString("recover.mnemonic.%1").arg(i)).toString().toLower().normalized(QString::NormalizationForm_KD); + sMnemonic.append(sWord); + } + + std::string sError; + std::vector vEntropy; + std::vector vSeed; + + sKey.clear(); + + // - decode to determine validity of mnemonic + if (0 == MnemonicDecode(-1, sMnemonic.toStdString(), vEntropy, sError)) + { + if (0 == MnemonicToSeed(sMnemonic.toStdString(), sPassword.toStdString(), vSeed)) + { + CExtKey ekMaster; + ekMaster.SetMaster(&vSeed[0], vSeed.size()); + if (!ekMaster.IsValid()) + sError = "Generated seed is not a valid key."; + else { + CExtKey58 eKey58; + eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY_BTC); + sKey = eKey58.ToString(); + } + } + else + sError = "MnemonicToSeed failed."; + } + + if (sKey.empty()) + { + QMessageBox::critical(this, tr("Error"), tr("Failed to recover private keys from Mnemonic Seed Words. %1").arg(sError.c_str())); + return false; + } + + return true; +} + +EncryptWalletPage::EncryptWalletPage(QWidget *parent) + : QWizardPage(parent) +{ + setTitle(tr("Wallet Encryption")); + setSubTitle(tr("Please enter a password to encrypt the wallet.dat file.")); + + topLabel = new QLabel(tr("The password protects your private keys and will be asked by the wallet on startup and for critical operations.")); + topLabel->setWordWrap(true); + + passwordLabel = new QLabel(tr("&Wallet Password:")); + passwordEdit = new QLineEdit; + passwordEdit->setEchoMode(QLineEdit::Password); + passwordLabel->setBuddy(passwordEdit); + + passwordVerifyLabel = new QLabel(tr("&Verify Password:")); + passwordVerifyEdit = new QLineEdit; + passwordVerifyEdit->setEchoMode(QLineEdit::Password); + passwordVerifyLabel->setBuddy(passwordVerifyEdit); + + registerField("encryptwallet.password*", passwordEdit); + registerField("encryptwallet.passwordverify*", passwordVerifyEdit); + + progressLabel = new QLabel(tr("Create and encrypt wallet.dat ...")); + progressLabel->setWordWrap(true); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + progressLabel->setSizePolicy(sizePolicy); + progressLabel->setAlignment(Qt::AlignHCenter); + + progressBar = new QProgressBar(); + progressBar->setRange(0, 0); + + QVBoxLayout *layout = new QVBoxLayout; + + layout->addWidget(topLabel); + layout->addSpacing(20); + + QGridLayout *formLayout = new QGridLayout; + formLayout->addWidget(passwordLabel, 0, 0); + formLayout->addWidget(passwordEdit, 0, 1); + formLayout->addWidget(passwordVerifyLabel, 1, 0); + formLayout->addWidget(passwordVerifyEdit, 1, 1); + + layout->addLayout(formLayout); + + layout->addSpacing(50); + layout->addWidget(progressLabel); + layout->addSpacing(20); + layout->addWidget(progressBar); + progressLabel->setVisible(false); + progressBar->setVisible(false); + + setLayout(layout); +} + +int EncryptWalletPage::nextId() const +{ + return -1; +} + +void EncryptWalletPage::initializePage() +{ + passwordEdit->setText(""); + passwordVerifyEdit->setText(""); +} + + +bool EncryptWalletPage::isComplete() const +{ + QString sPassword = field("encryptwallet.password").toString(); + QString sVerificationPassword = field("encryptwallet.passwordverify").toString(); + return sPassword == sVerificationPassword && sPassword.length() > 0; +} + +bool EncryptWalletPage::validatePage() +{ + progressLabel->setVisible(true); + progressBar->setVisible(true); + passwordEdit->setEnabled(false); + passwordVerifyEdit->setEnabled(false); + wizard()->button(QWizard::BackButton)->setEnabled(false); + wizard()->button(QWizard::FinishButton)->setEnabled(false); + + const std::string& sBip44Key = wizard()->hasVisitedPage(SetupWalletWizard::Page_RecoverFromMnemonic) ? + static_cast(wizard()->page(SetupWalletWizard::Page_RecoverFromMnemonic))->sKey : + static_cast(wizard()->page(SetupWalletWizard::Page_NewMnemonic_Settings))->sKey; + + QFuture future = QtConcurrent::run(this, &EncryptWalletPage::encryptWallet, + QString("wallet.dat"), + QString::fromStdString(sBip44Key), + field("encryptwallet.password").toString()); + while (!future.isResultReadyAt(0)) + QApplication::instance()->processEvents(); + + int ret = future.result(); + progressLabel->setVisible(false); + progressBar->setVisible(false); + if (ret == 0) + return true; + else { + passwordEdit->setEnabled(true); + passwordVerifyEdit->setEnabled(true); + wizard()->button(QWizard::BackButton)->setEnabled(true); + wizard()->button(QWizard::FinishButton)->setEnabled(true); + QMessageBox::critical(this, tr("Error"), tr("Failed to create wallet.dat. ErrorCode: %1").arg(ret)); + return false; + } +} + +int EncryptWalletPage::encryptWallet(const QString strWalletFile, const QString sBip44Key, const QString password) +{ + SecureString secString; + secString.reserve(MAX_PASSPHRASE_SIZE); + secString.assign(password.toStdString().c_str()); + + return SetupWalletData(strWalletFile.toStdString(), sBip44Key.toStdString(), secString); +} + + diff --git a/src/qt/setupwalletwizard.h b/src/qt/setupwalletwizard.h new file mode 100644 index 0000000000..515ec25bee --- /dev/null +++ b/src/qt/setupwalletwizard.h @@ -0,0 +1,181 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef SETUPWALLETWIZARD_H +#define SETUPWALLETWIZARD_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE +class QCheckBox; +class QComboBox; +class QLabel; +class QLineEdit; +class QRadioButton; +class QProgressBar; +class QPushButton; +QT_END_NAMESPACE + +class SetupWalletWizard : public QWizard +{ + Q_OBJECT + +public: + enum { Page_Intro, + Page_ImportWalletDat, + Page_NewMnemonic_Settings, Page_NewMnemonic_Result, Page_NewMnemonic_Verification, + Page_RecoverFromMnemonic, + Page_EncryptWallet}; + + SetupWalletWizard(QWidget *parent = nullptr); + +private Q_SLOTS: + void showHelp(); +}; + +class IntroPage : public QWizardPage +{ + Q_OBJECT + +public: + IntroPage(QWidget *parent = nullptr); + int nextId() const override; + +private: + QLabel *topLabel{nullptr}; + QRadioButton *newMnemonicRadioButton{nullptr}; + QRadioButton *recoverFromMnemonicRadioButton{nullptr}; + QRadioButton *importWalletRadioButton{nullptr}; +}; + +class ImportWalletDatPage : public QWizardPage +{ + Q_OBJECT + +public: + ImportWalletDatPage(QWidget *parent = nullptr); + int nextId() const override; + bool isComplete() const override; + bool validatePage() override; + +private Q_SLOTS: + void setOpenFileName(); + +private: + QString fileName; + QLabel *openFileNameLabel{nullptr}; + QPushButton *openFileNameButton{nullptr}; +}; + +class NewMnemonicSettingsPage : public QWizardPage +{ + Q_OBJECT + +public: + NewMnemonicSettingsPage(QWidget *parent = nullptr); + int nextId() const override; + bool validatePage() override; + bool isComplete() const override; + void cleanupPage() override; + + QStringList mnemonicList; + std::string sKey; + +private: + QLabel *noteLabel{nullptr}; + QLabel *languageLabel{nullptr}; + QLabel *passwordLabel{nullptr}; + QLabel *passwordVerifyLabel{nullptr}; + QComboBox *languageComboBox{nullptr}; + QLineEdit *passwordEdit{nullptr}; + QLineEdit *passwordVerifyEdit{nullptr}; +}; + +class NewMnemonicResultPage : public QWizardPage +{ + Q_OBJECT + +public: + NewMnemonicResultPage(QWidget *parent = nullptr); + void initializePage() override; + int nextId() const override; + + std::string sKey; + QStringList mnemonicList; + +private: + QLabel *mnemonicLabel{nullptr}; + QLabel *noticeLabel{nullptr}; + std::vector vMnemonicResultLabel; +}; + +class NewMnemonicVerificationPage : public QWizardPage +{ + Q_OBJECT + +public: + NewMnemonicVerificationPage(QWidget *parent = nullptr); + int nextId() const override; + bool isComplete() const override; + bool eventFilter(QObject *obj, QEvent *event) override; + void initializePage() override; + +private: + QLabel *mnemonicLabel{nullptr}; + QLabel *passwordLabel{nullptr}; + QLineEdit *passwordEdit{nullptr}; + std::vector vMnemonicEdit; +}; + +class RecoverFromMnemonicPage : public QWizardPage +{ + Q_OBJECT + +public: + RecoverFromMnemonicPage(QWidget *parent = nullptr); + int nextId() const override; + bool validatePage() override; + bool isComplete() const override; + bool eventFilter(QObject *obj, QEvent *event) override; + + std::string sKey; + +private: + QLabel *mnemonicLabel{nullptr}; + QLabel *passwordLabel{nullptr}; + QLabel *passwordVerifyLabel{nullptr}; + QLineEdit *passwordEdit{nullptr}; + QLineEdit *passwordVerifyEdit{nullptr}; + std::vector vMnemonicEdit; +}; + +class EncryptWalletPage : public QWizardPage +{ + Q_OBJECT + +public: + EncryptWalletPage(QWidget *parent = nullptr); + int nextId() const override; + void initializePage() override; + bool isComplete() const override; + bool validatePage() override; + +private: + int encryptWallet(const QString strWalletFile, const QString sBip44Key, const QString password); + + QLabel *progressLabel{nullptr}; + QProgressBar *progressBar{nullptr}; + QLabel *topLabel{nullptr}; + QLabel *passwordLabel{nullptr}; + QLineEdit *passwordEdit{nullptr}; + QLabel *passwordVerifyLabel{nullptr}; + QLineEdit *passwordVerifyEdit{nullptr}; +}; + +#endif // SETUPWALLETWIZARD_H diff --git a/src/qt/shadow.cpp b/src/qt/shadow.cpp deleted file mode 100644 index d6ae61c396..0000000000 --- a/src/qt/shadow.cpp +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. - -#include "shadowgui.h" -#include "clientmodel.h" -#include "walletmodel.h" -#include "optionsmodel.h" -#include "messagemodel.h" -#include "guiutil.h" -#include "guiconstants.h" -#include "paymentserver.h" - -#include "init.h" -#include "ui_interface.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(SHADOW_NEED_QT_PLUGINS) && !defined(_SHADOW_QT_PLUGINS_INCLUDED) -#define _SHADOW_NEED_QT_PLUGINS -#define __INSURE__ -#include -Q_IMPORT_PLUGIN(qcncodecs) -Q_IMPORT_PLUGIN(qjpcodecs) -Q_IMPORT_PLUGIN(qtwcodecs) -Q_IMPORT_PLUGIN(qkrcodecs) -Q_IMPORT_PLUGIN(qtaccessiblewidgets) -#endif - -// Need a global reference for the notifications to find the GUI -static ShadowGUI *guiref; -static QSplashScreen *splashref; - -static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) -{ - // Message from network thread - if(guiref) - { - bool modal = (style & CClientUIInterface::MODAL); - // in case of modal message, use blocking connection to wait for user to click OK - QMetaObject::invokeMethod(guiref, "error", - modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(caption)), - Q_ARG(QString, QString::fromStdString(message)), - Q_ARG(bool, modal)); - } else - { - LogPrintf("%s: %s\n", caption.c_str(), message.c_str()); - fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); - } -} - -static bool ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) -{ - if(!guiref) - return false; - if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon) - return true; - bool payFee = false; - - QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(), - Q_ARG(qint64, nFeeRequired), - Q_ARG(bool*, &payFee)); - - return payFee; -} - -static void ThreadSafeHandleURI(const std::string& strURI) -{ - if(!guiref) - return; - - QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(), - Q_ARG(QString, QString::fromStdString(strURI))); -} - -static void InitMessage(const std::string &message) -{ - if(splashref) - { - splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(200,0,0)); - QApplication::instance()->processEvents(); - } -} - -static void QueueShutdown() -{ - QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); -} - -/* - Translate string to current locale using Qt. - */ -static std::string Translate(const char* psz) -{ - return QCoreApplication::translate("bitcoin-core", psz).toStdString(); -} - -/* Handle runaway exceptions. Shows a message box with the problem and quits the program. - */ -static void handleRunawayException(std::exception *e) -{ - PrintExceptionContinue(e, "Runaway exception"); - QMessageBox::critical(0, "Runaway exception", ShadowGUI::tr("A fatal error occurred. Shadow can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning)); - exit(1); -} - -#ifndef SHADOW_QT_TEST -int main(int argc, char *argv[]) -{ - fHaveGUI = true; - -#if QT_VERSION < 0x050000 - // Internal string conversion is all UTF-8 - QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); - QTextCodec::setCodecForCStrings(QTextCodec::codecForTr()); -#endif - - Q_INIT_RESOURCE(shadow); - QApplication app(argc, argv); - - // Do this early as we don't want to bother initializing if we are just calling IPC - // ... but do it after creating app, so QCoreApplication::arguments is initialized: - if (PaymentServer::ipcSendCommandLine()) - exit(0); - PaymentServer* paymentServer = new PaymentServer(&app); - - // Install global event filter that makes sure that long tooltips can be word-wrapped - app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app)); - - // Command-line options take precedence: - ParseParameters(argc, argv); - - // ... then shadowcoin.conf: - if (!boost::filesystem::is_directory(GetDataDir(false))) - { - // This message can not be translated, as translation is not initialized yet - // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory) - QMessageBox::critical(0, "Shadow", - QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); - return 1; - } - ReadConfigFile(mapArgs, mapMultiArgs); - - // Application identification (must be set before OptionsModel is initialized, - // as it is used to locate QSettings) - app.setOrganizationName("The Shadow Project"); - app.setOrganizationDomain("shadow.cash"); - if(GetBoolArg("-testnet")) // Separate UI settings for testnet - app.setApplicationName("Shadow-testnet"); - else - app.setApplicationName("Shadow"); - - // ... then GUI settings: - OptionsModel optionsModel; - - // Get desired locale (e.g. "de_DE") from command line or use system locale - QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString())); - QString lang = lang_territory; - // Convert to "de" only by truncating "_DE" - lang.truncate(lang_territory.lastIndexOf('_')); - - QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; - // Load language files for configured locale: - // - First load the translator for the base language, without territory - // - Then load the more specific locale translator - - // Load e.g. qt_de.qm - if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - app.installTranslator(&qtTranslatorBase); - - // Load e.g. qt_de_DE.qm - if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) - app.installTranslator(&qtTranslator); - - // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc) - if (translatorBase.load(lang, ":/translations/")) - app.installTranslator(&translatorBase); - - // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc) - if (translator.load(lang_territory, ":/translations/")) - app.installTranslator(&translator); - - // Subscribe to global signals from core - uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox); - uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee); - uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI); - uiInterface.InitMessage.connect(InitMessage); - //uiInterface.QueueShutdown.connect(QueueShutdown); - uiInterface.Translate.connect(Translate); - - // Show help message immediately after parsing command-line options (for "-lang") and setting locale, - // but before showing splash screen. - if (mapArgs.count("-?") || mapArgs.count("--help")) - { - GUIUtil::HelpMessageBox help; - help.showOrPrint(); - return 1; - } - - QSplashScreen splash(QPixmap(":/images/splash"), 0); - if (GetBoolArg("-splash", true) && !GetBoolArg("-min")) - { - splash.show(); - splashref = &splash; - } - - app.processEvents(); - - app.setQuitOnLastWindowClosed(false); - - try - { - // Regenerate startup link, to fix links to old versions - if (GUIUtil::GetStartOnSystemStartup()) - GUIUtil::SetStartOnSystemStartup(true); - - boost::thread_group threadGroup; - - ShadowGUI window; - guiref = &window; - - QTimer* pollShutdownTimer = new QTimer(guiref); - QObject::connect(pollShutdownTimer, SIGNAL(timeout()), guiref, SLOT(detectShutdown())); - pollShutdownTimer->start(200); - - if (AppInit2(threadGroup)) - { - { - // Put this in a block, so that the Model objects are cleaned up before - // calling Shutdown(). - - paymentServer->setOptionsModel(&optionsModel); - - if (splashref) - splash.finish(&window); - - ClientModel clientModel(&optionsModel); - WalletModel walletModel(pwalletMain, &optionsModel); - MessageModel messageModel(pwalletMain, &walletModel); - - window.setClientModel(&clientModel); - window.setWalletModel(&walletModel); - window.setMessageModel(&messageModel); - - // If -min option passed, start window minimized. - if(GetBoolArg("-min")) - { - window.showMinimized(); - } else - { - window.show(); - } - - // Now that initialization/startup is done, process any command-line - // shadow: URIs - QObject::connect(paymentServer, SIGNAL(receivedURI(QString)), &window, SLOT(handleURI(QString))); - QTimer::singleShot(100, paymentServer, SLOT(uiReady())); - - app.exec(); - - window.hide(); - window.setClientModel(0); - window.setWalletModel(0); - window.setMessageModel(0); - guiref = 0; - } - // Shutdown the core and its threads, but don't exit Qt here - LogPrintf("ShadowCoin shutdown.\n\n"); - threadGroup.interrupt_all(); - threadGroup.join_all(); - Shutdown(); - } else - { - threadGroup.interrupt_all(); - threadGroup.join_all(); - Shutdown(); - return 1; - }; - } catch (std::exception& e) { - handleRunawayException(&e); - } catch (...) { - handleRunawayException(NULL); - } - return 0; -} -#endif // SHADOW_QT_TEST diff --git a/src/qt/shadowbridge.h b/src/qt/shadowbridge.h deleted file mode 100644 index 204bbf70bc..0000000000 --- a/src/qt/shadowbridge.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef SHADOWBRIDGE_H -#define SHADOWBRIDGE_H - -class ShadowGUI; -class TransactionModel; -class WalletModel; -class BlockExplorerModel; -class AddressModel; -class MessageThread; -class SendCoinsRecipient; - -#include -#include -#include - - - - -class ShadowBridge : public QObject -{ - Q_OBJECT - - /** Information about the client */ - Q_PROPERTY(QVariantMap info READ getInfo); -public: - explicit ShadowBridge(ShadowGUI *window, QObject *parent = 0); - ~ShadowBridge(); - - void setClientModel(); - void setWalletModel(); - void setMessageModel(); - - Q_INVOKABLE void copy(QString text); - Q_INVOKABLE void paste(); - - /** Get the label belonging to an address */ - Q_INVOKABLE QString getAddressLabel(QString address); - /** Create a new address or add an existing address to your Address book */ - Q_INVOKABLE QString newAddress(QString addressLabel, int addressType, QString address = "", bool send = false); - Q_INVOKABLE QString lastAddressError(); - /** Get the full transaction details */ - Q_INVOKABLE QString transactionDetails(QString txid); - /** Get the pubkey for an address */ - Q_INVOKABLE QString getPubKey(QString address); - - /** Show debug dialog */ - Q_INVOKABLE QVariantMap userAction(QVariantMap action); - - Q_INVOKABLE void populateTransactionTable(); - - Q_INVOKABLE void updateAddressLabel(QString address, QString label); - Q_INVOKABLE bool validateAddress(QString own); - Q_INVOKABLE bool deleteAddress(QString address); - - Q_INVOKABLE bool deleteMessage(QString key); - Q_INVOKABLE bool markMessageAsRead(QString key); - - Q_INVOKABLE void openCoinControl(); - - Q_INVOKABLE bool addRecipient(QString address, QString label, QString narration, qint64 amount, int txnType, int nRingSize); - Q_INVOKABLE bool sendCoins(bool fUseCoinControl, QString sChangeAddr); - Q_INVOKABLE bool setPubKey(QString address, QString pubkey); - Q_INVOKABLE bool sendMessage(const QString &address, const QString &message, const QString &from); - Q_INVOKABLE QString joinGroupChat(QString privkey, QString label); - Q_INVOKABLE QString createGroupChat(QString label); - Q_INVOKABLE QVariantList inviteGroupChat(QString address, QVariantList invites, QString from); - - Q_INVOKABLE void updateCoinControlAmount(qint64 amount); - Q_INVOKABLE void updateCoinControlLabels(unsigned int &quantity, int64_t &amount, int64_t &fee, int64_t &afterfee, unsigned int &bytes, QString &priority, QString low, int64_t &change); - - Q_INVOKABLE QVariantMap listAnonOutputs(); - - Q_INVOKABLE QVariantMap findBlock(QString searchID); - Q_INVOKABLE QVariantMap listLatestBlocks(); - Q_INVOKABLE QVariantMap blockDetails(QString blkid); - Q_INVOKABLE QVariantMap listTransactionsForBlock(QString blkid); - Q_INVOKABLE QVariantMap txnDetails(QString blkHash, QString txnHash); - - Q_INVOKABLE QVariantMap signMessage(QString address, QString message); - Q_INVOKABLE QVariantMap verifyMessage(QString address, QString message, QString signature); - - Q_INVOKABLE QVariantMap importFromMnemonic(QString inMnemonic, QString inPassword, QString inLabel, bool fBip44 = false, int64_t nCreateTime = 0); - Q_INVOKABLE QVariantMap getNewMnemonic(QString password, QString language); - Q_INVOKABLE QVariantMap extKeyAccList(); - Q_INVOKABLE QVariantMap extKeyList(); - Q_INVOKABLE QVariantMap extKeyImport(QString inKey, QString inLabel, bool fBip44 = false, int64_t nCreateTime = 0); - Q_INVOKABLE QVariantMap extKeySetDefault(QString extKeyID); - Q_INVOKABLE QVariantMap extKeySetMaster(QString extKeyID); - Q_INVOKABLE QVariantMap extKeySetActive(QString extKeySetActive, QString isActive); - - Q_INVOKABLE QString translateHtmlString(QString string); - -signals: - void emitPaste(QString text); - void emitTransactions(QVariantList transactions); - void emitAddresses(QVariantList addresses); - void emitMessages(QString messages, bool reset); - void emitMessage(QString id, QString type, qint64 sent, qint64 received, QString label_v, QString label, QString labelTo, QString to, QString from, bool read, QString message); - void emitCoinControlUpdate(unsigned int quantity, qint64 amount, qint64 fee, qint64 afterfee, unsigned int bytes, QString priority, QString low, qint64 change); - void emitAddressBookReturn(QString address, QString label); - void emitReceipient(QString address, QString label, QString narration, qint64 amount); - void triggerElement(QString element, QString trigger); - void networkAlert(QString alert); - -private: - ShadowGUI *window; - TransactionModel *transactionModel; - AddressModel *addressModel; - MessageThread *thMessage; - QList recipients; - QVariantMap *info; - QThread *async; - - friend class ShadowGUI; - - inline QVariantMap getInfo() const { return *info; }; - - void populateOptions(); - void populateAddressTable(); - void connectSignals(); - void clearRecipients(); - - void appendMessage(int row); - -private slots: - void updateTransactions(QModelIndex topLeft, QModelIndex bottomRight); - void updateAddresses(QModelIndex topLeft, QModelIndex bottomRight); - void insertTransactions(const QModelIndex &parent, int start, int end); - void insertAddresses(const QModelIndex &parent, int start, int end); - void insertMessages(const QModelIndex &parent, int start, int end); - - void appendMessages(QString messages, bool reset); - - void populateMessageTable(); - -}; - -#endif // SHADOWBRIDGE_H diff --git a/src/qt/shadowgui.cpp b/src/qt/shadowgui.cpp deleted file mode 100644 index 246eb90afc..0000000000 --- a/src/qt/shadowgui.cpp +++ /dev/null @@ -1,1017 +0,0 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. - -#include "shadowgui.h" -#include "transactiontablemodel.h" -#include "transactionrecord.h" - -#include "aboutdialog.h" -#include "clientmodel.h" -#include "walletmodel.h" -#include "messagemodel.h" -#include "optionsmodel.h" -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiconstants.h" -#include "askpassphrasedialog.h" -#include "notificator.h" -#include "guiutil.h" -#include "wallet.h" -#include "util.h" -#include "init.h" - -#ifdef Q_OS_MAC -#include "macdockiconhandler.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include - -extern CWallet* pwalletMain; -double GetPoSKernelPS(); - -ShadowGUI::ShadowGUI(QWidget *parent): - QMainWindow(parent), - bridge(new ShadowBridge(this)), - clientModel(0), - walletModel(0), - messageModel(0), - encryptWalletAction(0), - changePassphraseAction(0), - unlockWalletAction(0), - lockWalletAction(0), - aboutQtAction(0), - trayIcon(0), - notificator(0), - rpcConsole(0), - nWeight(0) -{ - webView = new QWebView(); - - webView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); - - webView->page()->action(QWebPage::Reload )->setVisible(false); - webView->page()->action(QWebPage::Back )->setVisible(false); - webView->page()->action(QWebPage::Forward)->setVisible(false); - - connect(webView, SIGNAL(linkClicked(const QUrl&)), this, SLOT(urlClicked(const QUrl&))); - - setCentralWidget(webView); - - resize(1280, 720); - setWindowTitle(tr("Umbra") + " - " + tr("Client")); -#ifndef Q_OS_MAC - qApp->setWindowIcon(QIcon(":icons/shadow")); - setWindowIcon(QIcon(":icons/shadow")); -#else - setUnifiedTitleAndToolBarOnMac(true); - QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); -#endif - - // Accept D&D of URIs - setAcceptDrops(true); - - // Create actions for the toolbar, menu bar and tray/dock icon - createActions(); - - // Create application menu bar - createMenuBar(); - - // Create the tray icon (or setup the dock icon) - createTrayIcon(); - - rpcConsole = new RPCConsole(this); - - connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); - - // prevents an oben debug window from becoming stuck/unusable on client shutdown - connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide())); - - documentFrame = webView->page()->mainFrame(); - - QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); - - //connect(webView->page()->action(QWebPage::Reload), SIGNAL(triggered()), SLOT(pageLoaded(bool))); - - connect(webView, SIGNAL(loadFinished(bool)), SLOT(pageLoaded(bool))); - connect(documentFrame, SIGNAL(javaScriptWindowObjectCleared()), SLOT(addJavascriptObjects())); - connect(documentFrame, SIGNAL(urlChanged(QUrl)), SLOT(urlClicked(const QUrl&))); - -#ifdef Q_OS_WIN - QFile html("C:/shadow/index.html"); -#else - QFile html("/opt/shadow/index.html"); -#endif - - if(html.exists()) - webView->setUrl(QUrl("file:///" + html.fileName())); - else - webView->setUrl(QUrl("qrc:///src/qt/res/index.html")); -} - -ShadowGUI::~ShadowGUI() -{ - if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) - trayIcon->hide(); - - delete webView; -#ifdef Q_OS_MAC - delete appMenuBar; -#endif -} - -void ShadowGUI::pageLoaded(bool ok) -{ - if (GetBoolArg("-staking", true)) - { - QTimer *timerStakingIcon = new QTimer(this); - connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(updateStakingIcon())); - timerStakingIcon->start(15 * 1000); - updateStakingIcon(); - } - -} - -void ShadowGUI::addJavascriptObjects() -{ - documentFrame->addToJavaScriptWindowObject("bridge", bridge); - -} - -void ShadowGUI::urlClicked(const QUrl & link) -{ - if(link.scheme() == "qrc" || link.scheme() == "file") - return; - - QDesktopServices::openUrl(link); -} - -void ShadowGUI::createActions() -{ - - quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); - quitAction->setToolTip(tr("Quit application")); - quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); - quitAction->setMenuRole(QAction::QuitRole); - aboutAction = new QAction(QIcon(":/icons/shadow"), tr("&About ShadowCoin"), this); - aboutAction->setToolTip(tr("Show information about ShadowCoin")); - aboutAction->setMenuRole(QAction::AboutRole); - aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this); - aboutQtAction->setToolTip(tr("Show information about Qt")); - aboutQtAction->setMenuRole(QAction::AboutQtRole); - optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); - optionsAction->setToolTip(tr("Modify configuration options for ShadowCoin")); - optionsAction->setMenuRole(QAction::PreferencesRole); - toggleHideAction = new QAction(QIcon(":/icons/shadow"), tr("&Show / Hide"), this); - encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this); - encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet")); - encryptWalletAction->setCheckable(true); - backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this); - backupWalletAction->setToolTip(tr("Backup wallet to another location")); - changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this); - changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); - unlockWalletAction = new QAction(QIcon(":/icons/lock_open"), tr("&Unlock Wallet..."), this); - unlockWalletAction->setToolTip(tr("Unlock wallet")); - lockWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Lock Wallet"), this); - lockWalletAction->setToolTip(tr("Lock wallet")); - - //exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this); - //exportAction->setToolTip(tr("Export the data in the current tab to a file")); - openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); - openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); - - connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); - connect(aboutAction, SIGNAL(triggered()), SLOT(aboutClicked())); - connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - connect(optionsAction, SIGNAL(triggered()), SLOT(optionsClicked())); - connect(toggleHideAction, SIGNAL(triggered()), SLOT(toggleHidden())); - connect(encryptWalletAction, SIGNAL(triggered(bool)), SLOT(encryptWallet(bool))); - connect(backupWalletAction, SIGNAL(triggered()), SLOT(backupWallet())); - connect(changePassphraseAction, SIGNAL(triggered()), SLOT(changePassphrase())); - connect(unlockWalletAction, SIGNAL(triggered()), SLOT(unlockWallet())); - connect(lockWalletAction, SIGNAL(triggered()), SLOT(lockWallet())); -} - -void ShadowGUI::createMenuBar() -{ -#ifdef Q_OS_MAC - // Create a decoupled menu bar on Mac which stays even if the window is closed - appMenuBar = new QMenuBar(); -#else - // Get the main window's menu bar on other platforms - appMenuBar = menuBar(); - appMenuBar->hide(); -#endif - - // Configure the menus - QMenu *file = appMenuBar->addMenu(tr("&File")); - file->addAction(backupWalletAction); - //file->addAction(exportAction); - file->addSeparator(); - file->addAction(quitAction); - - QMenu *settings = appMenuBar->addMenu(tr("&Settings")); - settings->addAction(encryptWalletAction); - settings->addAction(changePassphraseAction); - settings->addAction(unlockWalletAction); - settings->addAction(lockWalletAction); - settings->addSeparator(); - settings->addAction(optionsAction); - - QMenu *help = appMenuBar->addMenu(tr("&Help")); - help->addAction(openRPCConsoleAction); - help->addSeparator(); - help->addAction(aboutAction); - help->addAction(aboutQtAction); -} - -void ShadowGUI::setClientModel(ClientModel *clientModel) -{ - this->clientModel = clientModel; - if (clientModel) - { - int mode = clientModel->getClientMode(); - if (mode != NT_FULL) - { - QString sMode = QString::fromLocal8Bit(GetNodeModeName(mode)); - if (sMode.length() > 0) - sMode[0] = sMode[0].toUpper(); - - setWindowTitle(tr("Umbra") + " - " + tr("Wallet") + ", " + sMode); - }; - - // Replace some strings and icons, when using the testnet - if (clientModel->isTestNet()) - { - setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]")); -#ifndef Q_OS_MAC - qApp->setWindowIcon(QIcon(":icons/shadow_testnet")); - setWindowIcon(QIcon(":icons/shadow_testnet")); -#else - MacDockIconHandler::instance()->setIcon(QIcon(":icons/shadow_testnet")); -#endif - if(trayIcon) - { - trayIcon->setToolTip(tr("Umbra client") + QString(" ") + tr("[testnet]")); - trayIcon->setIcon(QIcon(":/icons/shadow_testnet")); - toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet")); - } - - aboutAction->setIcon(QIcon(":/icons/toolbar_testnet")); - } - - connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); - connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); - - // Report errors from network/worker thread - connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); - - rpcConsole->setClientModel(clientModel); - - bridge->setClientModel(); - } -} - -void ShadowGUI::setWalletModel(WalletModel *walletModel) -{ - this->walletModel = walletModel; - if(walletModel) - { - // Report errors from wallet thread - connect(walletModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); - - documentFrame->addToJavaScriptWindowObject("walletModel", walletModel); - documentFrame->addToJavaScriptWindowObject("optionsModel", walletModel->getOptionsModel()); - - documentFrame->evaluateJavaScript("connectSignals();"); - - walletModel->getOptionsModel()->displayUnitChanged (walletModel->getOptionsModel()->getDisplayUnit()); - walletModel->getOptionsModel()->reserveBalanceChanged(walletModel->getOptionsModel()->getReserveBalance()); - walletModel->getOptionsModel()->rowsPerPageChanged (walletModel->getOptionsModel()->getRowsPerPage()); - - // Keep up to date with client - setNumConnections(clientModel->getNumConnections()); - setNumBlocks (clientModel->getNumBlocks(), - clientModel->getNumBlocksOfPeers()); - setEncryptionStatus(walletModel->getEncryptionStatus()); - walletModel->encryptionStatusChanged(walletModel->getEncryptionStatus()); - - connect(walletModel, SIGNAL(encryptionStatusChanged(int)), SLOT(setEncryptionStatus(int))); - - // Balloon pop-up for new transaction - connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(incomingTransaction(QModelIndex,int,int))); - - // Ask for passphrase if needed - connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet())); - - bridge->setWalletModel(); - } -} - -void ShadowGUI::setMessageModel(MessageModel *messageModel) -{ - this->messageModel = messageModel; - if(messageModel) - { - // Balloon pop-up for new message - connect(messageModel, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(incomingMessage(QModelIndex,int,int))); - bridge->setMessageModel(); - } -} - -void ShadowGUI::createTrayIcon() -{ - QMenu *trayIconMenu; -#ifndef Q_OS_MAC - trayIcon = new QSystemTrayIcon(this); - trayIconMenu = new QMenu(this); - trayIcon->setContextMenu(trayIconMenu); - trayIcon->setToolTip(tr("Umbra client")); - trayIcon->setIcon(QIcon(":/icons/shadow")); - connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); - trayIcon->show(); -#else - // Note: On Mac, the dock icon is used to provide the tray's functionality. - MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); - dockIconHandler->setMainWindow((QMainWindow *)this); - trayIconMenu = dockIconHandler->dockMenu(); -#endif - - // Configuration of the tray icon (or dock icon) icon menu - trayIconMenu->addAction(toggleHideAction); - trayIconMenu->addSeparator(); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(optionsAction); - trayIconMenu->addAction(openRPCConsoleAction); -#ifndef Q_OS_MAC // This is built-in on Mac - trayIconMenu->addSeparator(); - trayIconMenu->addAction(quitAction); -#endif - - notificator = new Notificator(qApp->applicationName(), trayIcon, this); -} - -#ifndef Q_OS_MAC -void ShadowGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) -{ - if(reason == QSystemTrayIcon::Trigger) - { - // Click on system tray icon triggers show/hide of the main window - toggleHideAction->trigger(); - } -} -#endif - -void ShadowGUI::aboutClicked() -{ - AboutDialog dlg; - dlg.setModel(clientModel); - dlg.exec(); -} - -void ShadowGUI::setNumConnections(int count) -{ - QWebElement connectionsIcon = documentFrame->findFirstElement("#connectionsIcon"); - - QString className; - - switch(count) - { - case 0: className = "connect-0"; break; - case 1: case 2: className = "connect-1"; break; - case 3: case 4: className = "connect-2"; break; - case 5: case 6: className = "connect-3"; break; - case 7: case 8: className = "connect-4"; break; - case 9: case 10: className = "connect-5"; break; - default: className = "connect-6"; break; - } - - connectionsIcon.setAttribute("class", className); - connectionsIcon.setAttribute("src", "qrc:///icons/" + className.replace("-", "_")); - connectionsIcon.setAttribute("data-title", tr("%n active connection(s) to ShadowCoin network", "", count)); -} - -void ShadowGUI::setNumBlocks(int count, int nTotalBlocks) -{ - QWebElement blocksIcon = documentFrame->findFirstElement("#blocksIcon"); - QWebElement syncingIcon = documentFrame->findFirstElement("#syncingIcon"); - QWebElement syncProgressBar = documentFrame->findFirstElement("#syncProgressBar"); - - // don't show / hide progress bar and its label if we have no connection to the network - if (!clientModel || (clientModel->getNumConnections() == 0 && !clientModel->isImporting())) - { - syncProgressBar.setAttribute("style", "display:none;"); - - return; - } - - // -- translation (tr()) makes it difficult to neatly pick block/header - static QString sBlockType = nNodeMode == NT_FULL ? tr("block") : tr("header"); - static QString sBlockTypeMulti = nNodeMode == NT_FULL ? tr("blocks") : tr("headers"); - - QString strStatusBarWarnings = clientModel->getStatusBarWarnings(); - QString tooltip; - - if (nNodeMode != NT_FULL - && nNodeState == NS_GET_FILTERED_BLOCKS) - { - tooltip = tr("Synchronizing with network..."); - + "\n" - + tr("Downloading filtered blocks..."); - - int nRemainingBlocks = nTotalBlocks - pwalletMain->nLastFilteredHeight; - float nPercentageDone = pwalletMain->nLastFilteredHeight / (nTotalBlocks * 0.01f); - - tooltip += "\n" - + tr("~%1 filtered block(s) remaining (%2% done).").arg(nRemainingBlocks).arg(nPercentageDone); - - count = pwalletMain->nLastFilteredHeight; - syncProgressBar.removeAttribute("style"); - } else - if (count < nTotalBlocks) - { - int nRemainingBlocks = nTotalBlocks - count; - float nPercentageDone = count / (nTotalBlocks * 0.01f); - syncProgressBar.removeAttribute("style"); - - if (strStatusBarWarnings.isEmpty()) - { - bridge->networkAlert(""); - tooltip = clientModel->isImporting() ? tr("Importing blocks...") : tr("Synchronizing with network..."); - - if (nNodeMode == NT_FULL) - { - tooltip += "\n" - + tr("~%n block(s) remaining", "", nRemainingBlocks); - } else - { - char temp[128]; - snprintf(temp, sizeof(temp), "~%%n %s remaining", nRemainingBlocks == 1 ? qPrintable(sBlockType) : qPrintable(sBlockTypeMulti)); - - tooltip += "\n" - + tr(temp, "", nRemainingBlocks); - - }; - } - - tooltip += (tooltip.isEmpty()? "" : "\n") - + (clientModel->isImporting() ? tr("Imported") : tr("Downloaded")) + " " - + tr("%1 of %2 %3 of transaction history (%4% done).").arg(count).arg(nTotalBlocks).arg(sBlockTypeMulti).arg(nPercentageDone, 0, 'f', 2); - } else - { - tooltip = (clientModel->isImporting() ? tr("Imported") : tr("Downloaded")) + " " + tr("%1 blocks of transaction history.").arg(count); - } - - // Override progressBarLabel text when we have warnings to display - if (!strStatusBarWarnings.isEmpty()) - bridge->networkAlert(strStatusBarWarnings); - - QDateTime lastBlockDate; - if (nNodeMode == NT_FULL) - lastBlockDate = clientModel->getLastBlockDate(); - else - lastBlockDate = clientModel->getLastBlockThinDate(); - - int secs = lastBlockDate.secsTo(QDateTime::currentDateTime()); - QString text; - - // Represent time from last generated block in human readable text - if (secs <= 0) - { - // Fully up to date. Leave text empty. - } else - if (secs < 60) - { - text = tr("%n second(s) ago","",secs); - } else - if (secs < 60*60) - { - text = tr("%n minute(s) ago","",secs/60); - } else - if (secs < 24*60*60) - { - text = tr("%n hour(s) ago","",secs/(60*60)); - } else - { - text = tr("%n day(s) ago","",secs/(60*60*24)); - } - - // Set icon state: spinning if catching up, tick otherwise - if (secs < 90*60 && count >= nTotalBlocks - && nNodeState != NS_GET_FILTERED_BLOCKS) - { - tooltip = tr("Up to date") + "\n" + tooltip; - blocksIcon.removeClass("none"); - syncingIcon.addClass("none"); - - QWebElementCollection outOfSyncElements = documentFrame->findAllElements(".outofsync"); - - foreach(QWebElement outOfSync, outOfSyncElements) - outOfSync.setStyleProperty("display", "none"); - - syncProgressBar.setAttribute("style", "display:none;"); - } else - { - tooltip = tr("Catching up...") + "\n" + tooltip; - - blocksIcon.addClass("none"); - syncingIcon.removeClass("none"); - - QWebElementCollection outOfSyncElements = documentFrame->findAllElements(".outofsync"); - - foreach(QWebElement outOfSync, outOfSyncElements) - outOfSync.setStyleProperty("display", "inline"); - - syncProgressBar.removeAttribute("style"); - } - - if (!text.isEmpty()) - { - tooltip += "\n"; - tooltip += tr("Last received %1 was generated %2.").arg(sBlockType).arg(text); - }; - - blocksIcon .setAttribute("data-title", tooltip); - syncingIcon .setAttribute("data-title", tooltip); - syncProgressBar.setAttribute("data-title", tooltip); - syncProgressBar.setAttribute("value", QString::number(count)); - syncProgressBar.setAttribute("max", QString::number(nTotalBlocks)); -} - -void ShadowGUI::error(const QString &title, const QString &message, bool modal) -{ - // Report errors from network/worker thread - if(modal) - { - QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok); - } else - { - notificator->notify(Notificator::Critical, title, message); - } -} - -void ShadowGUI::changeEvent(QEvent *e) -{ - QMainWindow::changeEvent(e); -#ifndef Q_OS_MAC // Ignored on Mac - if(e->type() == QEvent::WindowStateChange) - { - if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) - { - QWindowStateChangeEvent *wsevt = static_cast(e); - if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) - { - QTimer::singleShot(0, this, SLOT(hide())); - e->ignore(); - } - } - } -#endif -} - -void ShadowGUI::closeEvent(QCloseEvent *event) -{ - if(clientModel) - { -#ifndef Q_OS_MAC // Ignored on Mac - if(!clientModel->getOptionsModel()->getMinimizeToTray() && - !clientModel->getOptionsModel()->getMinimizeOnClose()) - { - qApp->quit(); - } -#endif - } - QMainWindow::closeEvent(event); -} - -void ShadowGUI::askFee(qint64 nFeeRequired, bool *payFee) -{ - QString strMessage = - tr("This transaction is over the size limit. You can still send it for a fee of %1, " - "which goes to the nodes that process your transaction and helps to support the network. " - "Do you want to pay the fee?").arg( - BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, nFeeRequired)); - QMessageBox::StandardButton retval = QMessageBox::question( - this, tr("Confirm transaction fee"), strMessage, - QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); - *payFee = (retval == QMessageBox::Yes); -} - -void ShadowGUI::incomingTransaction(const QModelIndex & parent, int start, int end) -{ - if(!walletModel || !clientModel || clientModel->inInitialBlockDownload() || nNodeState != NS_READY) - return; - - TransactionTableModel *ttm = walletModel->getTransactionTableModel(); - - QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString(); - - // Ignore staking transactions... We should create an Option, and allow people to select/deselect what - // type of transactions they want to see - if(!(clientModel->getOptionsModel()->getNotifications().first() == "*") - && ! clientModel->getOptionsModel()->getNotifications().contains(type)) - return; - - // On new transaction, make an info balloon - // Unless the initial block download is in progress, to prevent balloon-spam - QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString(); - QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString(); - qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong(); - QIcon icon = qvariant_cast(ttm->index(start, TransactionTableModel::ToAddress, parent).data(Qt::DecorationRole)); - - notificator->notify(Notificator::Information, - (amount)<0 ? tr("Sent transaction") : - tr("Incoming transaction"), - tr("Date: %1\n" - "Amount: %2\n" - "Type: %3\n" - "Address: %4\n") - .arg(date) - .arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), amount, true)) - .arg(type) - .arg(address), icon); -} - -void ShadowGUI::incomingMessage(const QModelIndex & parent, int start, int end) -{ - if(!messageModel) - return; - - if(!(clientModel->getOptionsModel()->getNotifications().first() == "*") - && ! clientModel->getOptionsModel()->getNotifications().contains(tr("Incoming Message"))) - return; - - MessageModel *mm = messageModel; - - if (mm->index(start, MessageModel::TypeInt, parent).data().toInt() == MessageTableEntry::Received) - { - QString sent_datetime = mm->index(start, MessageModel::ReceivedDateTime, parent).data().toString(); - QString from_address = mm->index(start, MessageModel::FromAddress, parent).data().toString(); - QString to_address = mm->index(start, MessageModel::ToAddress, parent).data().toString(); - QString message = mm->index(start, MessageModel::Message, parent).data().toString(); - QTextDocument html; - html.setHtml(message); - QString messageText(html.toPlainText()); - notificator->notify(Notificator::Information, - tr("Incoming Message"), - tr("Date: %1\n" - "From Address: %2\n" - "To Address: %3\n" - "Message: %4\n") - .arg(sent_datetime) - .arg(from_address) - .arg(to_address) - .arg(messageText)); - }; -} - -void ShadowGUI::optionsClicked() -{ - bridge->triggerElement("#navitems a[href=#options]", "click"); - showNormalIfMinimized(); -} - -void ShadowGUI::dragEnterEvent(QDragEnterEvent *event) -{ - // Accept only URIs - if(event->mimeData()->hasUrls()) - event->acceptProposedAction(); -} - -void ShadowGUI::dragMoveEvent(QDragMoveEvent *event) -{ - event->accept(); -} - -void ShadowGUI::dropEvent(QDropEvent *event) -{ - if(event->mimeData()->hasUrls()) - { - int nValidUrisFound = 0; - QList uris = event->mimeData()->urls(); - foreach(const QUrl &uri, uris) - { - handleURI(uri.toString()); - nValidUrisFound++; - } - - // if valid URIs were found - if (nValidUrisFound) - bridge->triggerElement("#navitems a[href=#send]", "click"); - else - notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid ShadowCoin address or malformed URI parameters.")); - } - - event->acceptProposedAction(); -} - -void ShadowGUI::handleURI(QString strURI) -{ - - SendCoinsRecipient rv; - - // URI has to be valid - if(GUIUtil::parseBitcoinURI(strURI, &rv)) - { - CBitcoinAddress address(rv.address.toStdString()); - if (!address.IsValid()) - return; - - bridge->emitReceipient(rv.address, rv.label, rv.narration, rv.amount); - - showNormalIfMinimized(); - } - else - notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid ShadowCoin address or malformed URI parameters.")); -} - -void ShadowGUI::setEncryptionStatus(int status) -{ - QWebElement encryptionIcon = documentFrame->findFirstElement("#encryptionIcon"); - QWebElement encryptButton = documentFrame->findFirstElement("#encryptWallet"); - QWebElement encryptMenuItem = documentFrame->findFirstElement(".encryptWallet"); - QWebElement changePassphrase = documentFrame->findFirstElement("#changePassphrase"); - QWebElement toggleLock = documentFrame->findFirstElement("#toggleLock"); - QWebElement toggleLockIcon = documentFrame->findFirstElement("#toggleLock i"); - switch(status) - { - case WalletModel::Unencrypted: - encryptionIcon.setAttribute("style", "display:none;"); - changePassphrase.addClass("none"); - toggleLock.addClass("none"); - encryptMenuItem.removeClass("none"); - encryptWalletAction->setChecked(false); - changePassphraseAction->setEnabled(false); - unlockWalletAction->setVisible(false); - lockWalletAction->setVisible(false); - encryptWalletAction->setEnabled(true); - break; - case WalletModel::Unlocked: - encryptMenuItem .addClass("none"); - encryptionIcon.removeAttribute("style"); - encryptionIcon.removeClass("fa-lock"); - encryptionIcon.removeClass("encryption"); - encryptionIcon. addClass("fa-unlock"); - encryptionIcon. addClass("no-encryption"); - encryptMenuItem .addClass("none"); - toggleLockIcon.removeClass("fa-unlock"); - toggleLockIcon.removeClass("fa-unlock-alt"); - toggleLockIcon. addClass("fa-lock"); - encryptionIcon .setAttribute("src", "qrc:///icons/lock_open"); - - if (fWalletUnlockStakingOnly) - { - encryptionIcon .setAttribute("data-title", tr("Wallet is encrypted and currently unlocked for staking only")); - encryptionIcon.removeClass("red"); - encryptionIcon.addClass("orange"); - encryptionIcon.addClass("encryption-stake"); - - toggleLockIcon .removeClass("red"); - toggleLockIcon .addClass("orange"); - } else - { - encryptionIcon .setAttribute("data-title", tr("Wallet is encrypted and currently unlocked")); - encryptionIcon.addClass("red"); - encryptionIcon.removeClass("orange"); - encryptionIcon.removeClass("encryption-stake"); - - toggleLockIcon .removeClass("orange"); - toggleLockIcon .addClass("red"); - }; - - encryptButton.addClass("none"); - changePassphrase.removeClass("none"); - toggleLock.removeClass("none"); - encryptWalletAction->setChecked(true); - changePassphraseAction->setEnabled(true); - unlockWalletAction->setVisible(false); - lockWalletAction->setVisible(true); - encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported - break; - case WalletModel::Locked: - encryptionIcon.removeAttribute("style"); - encryptionIcon.removeClass("fa-unlock"); - encryptionIcon.removeClass("no-encryption"); - encryptionIcon.removeClass("encryption-stake"); - encryptionIcon. addClass("fa-lock"); - encryptionIcon. addClass("encryption"); - toggleLockIcon.removeClass("fa-lock"); - toggleLockIcon. addClass("fa-unlock-alt"); - encryptionIcon .setAttribute("data-title", tr("Wallet is encrypted and currently locked")); - - encryptionIcon .addClass("red"); - encryptionIcon .removeClass("orange"); - encryptButton .addClass("none"); - encryptMenuItem .addClass("none"); - changePassphrase.removeClass("none"); - toggleLockIcon .removeClass("orange"); - toggleLockIcon .addClass("red"); - encryptWalletAction->setChecked(true); - changePassphraseAction->setEnabled(true); - unlockWalletAction->setVisible(true); - lockWalletAction->setVisible(false); - encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported - break; - } -} - -void ShadowGUI::encryptWallet(bool status) -{ - if(!walletModel) - return; - AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt: - AskPassphraseDialog::Decrypt, this); - dlg.setModel(walletModel); - dlg.exec(); - - setEncryptionStatus(walletModel->getEncryptionStatus()); -} - -void ShadowGUI::backupWallet() -{ - QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); - QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)")); - if(!filename.isEmpty()) - { - if(!walletModel->backupWallet(filename)) - { - QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location.")); - } - } -} - -void ShadowGUI::changePassphrase() -{ - AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this); - dlg.setModel(walletModel); - dlg.exec(); -} - -void ShadowGUI::unlockWallet() -{ - if(!walletModel) - return; - - // Unlock wallet when requested by wallet model - if(walletModel->getEncryptionStatus() == WalletModel::Locked) - { - - AskPassphraseDialog::Mode mode = sender() == unlockWalletAction ? - AskPassphraseDialog::UnlockStaking : AskPassphraseDialog::Unlock; - AskPassphraseDialog dlg(mode, this); - dlg.setModel(walletModel); - dlg.exec(); - } -} - -void ShadowGUI::lockWallet() -{ - if(!walletModel) - return; - - walletModel->setWalletLocked(true); -} - -void ShadowGUI::toggleLock() -{ - if(!walletModel) - return; - WalletModel::EncryptionStatus status = walletModel->getEncryptionStatus(); - - switch(status) - { - case WalletModel::Locked: unlockWalletAction->trigger(); break; - case WalletModel::Unlocked: lockWalletAction->trigger(); break; - default: // unencrypted wallet - QMessageBox::warning(this, tr("Lock Wallet"), - tr("Error: Wallet must first be encrypted to be locked."), - QMessageBox::Ok, QMessageBox::Ok); - break; - }; - -} - -void ShadowGUI::showNormalIfMinimized(bool fToggleHidden) -{ - // activateWindow() (sometimes) helps with keyboard focus on Windows - if (isHidden()) - { - show(); - activateWindow(); - } - else if (isMinimized()) - { - showNormal(); - activateWindow(); - } - else if (GUIUtil::isObscured(this)) - { - raise(); - activateWindow(); - } - else if(fToggleHidden) - hide(); -} - -void ShadowGUI::toggleHidden() -{ - showNormalIfMinimized(true); -} - -void ShadowGUI::updateWeight() -{ - if (!pwalletMain) - return; - - TRY_LOCK(cs_main, lockMain); - if (!lockMain) - return; - - TRY_LOCK(pwalletMain->cs_wallet, lockWallet); - if (!lockWallet) - return; - - nWeight = pwalletMain->GetStakeWeight(); -} - -void ShadowGUI::updateStakingIcon() -{ - QWebElement stakingIcon = documentFrame->findFirstElement("#stakingIcon"); - uint64_t nNetworkWeight = 0; - - if(fIsStaking) - { - updateWeight(); - nNetworkWeight = GetPoSKernelPS(); - } else - nWeight = 0; - - if (fIsStaking && nWeight) - { - uint64_t nWeight = this->nWeight; - - unsigned nEstimateTime = GetTargetSpacing(nBestHeight) * nNetworkWeight / nWeight; - QString text; - - text = (nEstimateTime < 60) ? tr("%n second(s)", "", nEstimateTime) : \ - (nEstimateTime < 60 * 60) ? tr("%n minute(s)", "", nEstimateTime / 60) : \ - (nEstimateTime < 24 * 60 * 60) ? tr("%n hour(s)", "", nEstimateTime / (60 * 60)) : \ - tr("%n day(s)", "", nEstimateTime / (60 * 60 * 24)); - - stakingIcon.removeClass("not-staking"); - stakingIcon. addClass("staking"); - //stakingIcon. addClass("fa-spin"); // TODO: Replace with gif... too much cpu usage - - nWeight /= COIN, - nNetworkWeight /= COIN; - - stakingIcon.setAttribute("data-title", tr("Staking.\nYour weight is %1\nNetwork weight is %2\nExpected time to earn reward is %3").arg(nWeight).arg(nNetworkWeight).arg(text)); - } else - { - stakingIcon. addClass("not-staking"); - stakingIcon.removeClass("staking"); - //stakingIcon.removeClass("fa-spin"); // TODO: See above TODO... - - stakingIcon.setAttribute("data-title", (nNodeMode == NT_THIN) ? tr("Not staking because wallet is in thin mode") : \ - (!GetBoolArg("-staking", true)) ? tr("Not staking, staking is disabled") : \ - (pwalletMain && pwalletMain->IsLocked()) ? tr("Not staking because wallet is locked") : \ - (vNodes.empty()) ? tr("Not staking because wallet is offline") : \ - (IsInitialBlockDownload()) ? tr("Not staking because wallet is syncing") : \ - (!nWeight) ? tr("Not staking because you don't have mature coins") : \ - tr("Not staking")); - } -} - -void ShadowGUI::detectShutdown() -{ - if (ShutdownRequested()) - QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); -} diff --git a/src/qt/shadowgui.h b/src/qt/shadowgui.h deleted file mode 100644 index 6cbbdc5072..0000000000 --- a/src/qt/shadowgui.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. - -#ifndef SHADOWGUI_H -#define SHADOWGUI_H - -#include -#include -#include -#include -#include - -#include - -#include "shadowbridge.h" -#include "rpcconsole.h" - -#include - -class TransactionTableModel; -class ClientModel; -class WalletModel; -class MessageModel; -class Notificator; - -QT_BEGIN_NAMESPACE -class QLabel; -class QMenuBar; -class QToolBar; -class QUrl; -QT_END_NAMESPACE - -/** - Shadow GUI main class. This class represents the main window of the Shadow UI. It communicates with both the client and - wallet models to give the user an up-to-date view of the current core state. -*/ -class ShadowGUI : public QMainWindow -{ - Q_OBJECT -public: - explicit ShadowGUI(QWidget *parent = 0); - ~ShadowGUI(); - - /** Set the client model. - The client model represents the part of the core that communicates with the P2P network, and is wallet-agnostic. - */ - void setClientModel(ClientModel *clientModel); - /** Set the wallet model. - The wallet model represents a bitcoin wallet, and offers access to the list of transactions, address book and sending - functionality. - */ - void setWalletModel(WalletModel *walletModel); - /** Set the message model. - The message model represents encryption message database, and offers access to the list of messages, address book and sending - functionality. - */ - void setMessageModel(MessageModel *messageModel); - -protected: - void changeEvent(QEvent *e); - void closeEvent(QCloseEvent *event); - void dragEnterEvent(QDragEnterEvent *event); - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); - -private: - QWebView *webView; - QWebFrame *documentFrame; - - ShadowBridge *bridge; - - ClientModel *clientModel; - WalletModel *walletModel; - MessageModel *messageModel; - - QMenuBar *appMenuBar; - - QAction *quitAction; - QAction *aboutAction; - QAction *optionsAction; - QAction *toggleHideAction; - QAction *exportAction; - QAction *encryptWalletAction; - QAction *backupWalletAction; - QAction *changePassphraseAction; - QAction *unlockWalletAction; - QAction *lockWalletAction; - QAction *aboutQtAction; - QAction *openRPCConsoleAction; - - QSystemTrayIcon *trayIcon; - Notificator *notificator; - RPCConsole *rpcConsole; - - uint64_t nWeight; - - /** Create the main UI actions. */ - void createActions(); - /** Create the menu bar and sub-menus. */ - void createMenuBar(); - - /** Create system tray (notification) icon */ - void createTrayIcon(); - - friend class ShadowBridge; - -private slots: - /** Page finished loading */ - void pageLoaded(bool ok); - /** Add JavaScript objects to page */ - void addJavascriptObjects(); - /** Handle external URLs **/ - void urlClicked(const QUrl & link); - - /** Set number of connections shown in the UI */ - void setNumConnections(int count); - /** Set number of blocks shown in the UI */ - void setNumBlocks(int count, int nTotalBlocks); - /** Set the encryption status as shown in the UI. - @param[in] status current encryption status - @see WalletModel::EncryptionStatus - */ - void setEncryptionStatus(int status); - - /** Notify the user of an error in the network or transaction handling code. */ - void error(const QString &title, const QString &message, bool modal); - /** Asks the user whether to pay the transaction fee or to cancel the transaction. - It is currently not possible to pass a return value to another thread through - BlockingQueuedConnection, so an indirected pointer is used. - https://bugreports.qt-project.org/browse/QTBUG-10440 - - @param[in] nFeeRequired the required fee - @param[out] payFee true to pay the fee, false to not pay the fee - */ - void askFee(qint64 nFeeRequired, bool *payFee); - void handleURI(QString strURI); - -#ifndef Q_OS_MAC - /** Handle tray icon clicked */ - void trayIconActivated(QSystemTrayIcon::ActivationReason reason); -#endif - /** Show incoming transaction notification for new transactions. - - The new items are those between start and end inclusive, under the given parent item. - */ - void incomingTransaction(const QModelIndex & parent, int start, int end); - - /** Show incoming message notification for new messages. - - The new items are those between start and end inclusive, under the given parent item. - */ - void incomingMessage(const QModelIndex & parent, int start, int end); - - /** Show configuration dialog */ - void optionsClicked(); - /** Show about dialog */ - void aboutClicked(); - - /** Unlock wallet */ - void unlockWallet(); - /** Lock wallet */ - void lockWallet(); - /** Toggle whether wallet is locked or not */ - void toggleLock(); - /** Encrypt the wallet */ - void encryptWallet(bool status); - /** Backup the wallet */ - void backupWallet(); - /** Change encrypted wallet passphrase */ - void changePassphrase(); - - /** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */ - void showNormalIfMinimized(bool fToggleHidden = false); - /** simply calls showNormalIfMinimized(true) for use in SLOT() macro */ - void toggleHidden(); - - void updateWeight(); - void updateStakingIcon(); - - /** called by a timer to check if fRequestShutdown has been set **/ - void detectShutdown(); -}; - -#endif diff --git a/src/qt/spectre.cpp b/src/qt/spectre.cpp new file mode 100644 index 0000000000..5f20682ad9 --- /dev/null +++ b/src/qt/spectre.cpp @@ -0,0 +1,395 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT + +#include "spectregui.h" +#include "clientmodel.h" +#include "walletmodel.h" +#include "optionsmodel.h" +#include "guiutil.h" +#include "guiconstants.h" +#include "paymentserver.h" +#include "winshutdownmonitor.h" +#include "setupwalletwizard.h" + +#include "websocketclientwrapper.h" +#include "websockettransport.h" + +#include "init.h" +#include "interface.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +#ifndef WIN32 +#include +#endif + + +// Need a global reference for the notifications to find the GUI +static SpectreGUI *guiref; +static QSplashScreen *splashref; + +static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style) +{ + // Message from network thread + if(guiref) + { + if (splashref) + splashref->finish(guiref); + + bool modal = (style & CClientUIInterface::MODAL); + // in case of modal message, use blocking connection to wait for user to click OK + QMetaObject::invokeMethod(guiref, "error", + modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(caption)), + Q_ARG(QString, QString::fromStdString(message)), + Q_ARG(bool, modal)); + } else + { + LogPrintf("%s: %s\n", caption.c_str(), message.c_str()); + fprintf(stderr, "%s: %s\n", caption.c_str(), message.c_str()); + } +} + +static bool ThreadSafeAskFee(int64_t nFeeRequired, const std::string& strCaption) +{ + if(!guiref) + return false; + if(nFeeRequired < nMinTxFee || nFeeRequired <= nTransactionFee || fDaemon) + return true; + bool payFee = false; + + QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(), + Q_ARG(qint64, nFeeRequired), + Q_ARG(bool*, &payFee)); + + return payFee; +} + +static void ThreadSafeHandleURI(const std::string& strURI) +{ + if(!guiref) + return; + + QMetaObject::invokeMethod(guiref, "handleURI", GUIUtil::blockingGUIThreadConnection(), + Q_ARG(QString, QString::fromStdString(strURI))); +} + +static void InitMessage(const std::string &message) +{ + if(splashref) + { + splashref->showMessage(QString::fromStdString("v"+FormatClientVersion()) + "\n" + QString::fromStdString(message) + "\n", Qt::AlignBottom|Qt::AlignHCenter, QColor(138,140,142)); + QApplication::instance()->processEvents(); + } +} + +/* + Translate string to current locale using Qt. + */ +static std::string Translate(const char* psz) +{ + return QCoreApplication::translate("alias-core", psz).toStdString(); +} + +/* Handle runaway exceptions. Shows a message box with the problem and quits the program. + */ +static void handleRunawayException(std::exception *e) +{ + PrintExceptionContinue(e, "Runaway exception"); + QMessageBox::critical(nullptr, "Runaway exception", SpectreGUI::tr("A fatal error occurred. Alias can no longer continue safely and will quit.") + QString("\n\n") + QString::fromStdString(strMiscWarning)); + exit(1); +} + +#ifndef SPECTRE_QT_TEST +int main(int argc, char *argv[]) +{ + qDebug() << "App start in main.cpp"; +#ifndef WIN32 + // Block signals. We handle them in a thread. + if (BlockSignals() != 0) + return 1; +#else + // Hide the console for windows + FreeConsole(); +#endif + + fHaveGUI = true; + +#if QT_VERSION < 0x050000 + // Internal string conversion is all UTF-8 + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); + QTextCodec::setCodecForCStrings(QTextCodec::codecForTr()); +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif + + // Command-line options take precedence: + ParseParameters(argc, argv); + + // Make sure TESTNET flag and specific chainparams are set (Init in AppInit2 is to late) + fTestNet = GetBoolArg("-testnet", false); + if (!SelectParamsFromCommandLine()) + { + QMessageBox::critical(nullptr, "Alias", QString("Error: Invalid combination of -testnet and -regtest.")); + return 1; + } + + QApplication app(argc, argv); + + // Set global styles + app.setStyleSheet("a {color: #f28321; }"); + QPalette newPal(app.palette()); + newPal.setColor(QPalette::Link, QColor(242, 131, 33)); + newPal.setColor(QPalette::LinkVisited, QColor(242, 131, 33)); + app.setPalette(newPal); + + QtWebView::initialize(); + + // Do this early as we don't want to bother initializing if we are just calling IPC + // ... but do it after creating app, so QCoreApplication::arguments is initialized: + if (PaymentServer::ipcSendCommandLine()) + exit(0); + PaymentServer* paymentServer = new PaymentServer(&app); + + // Install global event filter that makes sure that long tooltips can be word-wrapped + app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app)); + + #if defined(Q_OS_WIN) + // Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION) + qApp->installNativeEventFilter(new WinShutdownMonitor()); + #endif + + // ... then alias.conf: + if (!fs::is_directory(GetDataDir(false))) + { + // This message can not be translated, as translation is not initialized yet + // (which not yet possible because lang=XX can be overridden in bitcoin.conf in the data directory) + QMessageBox::critical(nullptr, "Alias", + QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"]))); + return 1; + } + ReadConfigFile(mapArgs, mapMultiArgs); + + // Application identification (must be set before OptionsModel is initialized, + // as it is used to locate QSettings) + app.setOrganizationName("The Alias Foundation"); + app.setOrganizationDomain("alias.cash"); + if(GetBoolArg("-testnet")) // Separate UI settings for testnet + app.setApplicationName("Alias-testnet"); + else + app.setApplicationName("Alias"); + + // ... then GUI settings: + OptionsModel optionsModel; + + // Get desired locale (e.g. "de_DE") from command line or use system locale + QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString())); + QString lang = lang_territory; + // Convert to "de" only by truncating "_DE" + lang.truncate(lang_territory.lastIndexOf('_')); + + QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator; + // Load language files for configured locale: + // - First load the translator for the base language, without territory + // - Then load the more specific locale translator + + // Load e.g. qt_de.qm + if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app.installTranslator(&qtTranslatorBase); + + // Load e.g. qt_de_DE.qm + if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app.installTranslator(&qtTranslator); + + // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc) + if (translatorBase.load(lang, ":/translations/")) + app.installTranslator(&translatorBase); + + // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc) + if (translator.load(lang_territory, ":/translations/")) + app.installTranslator(&translator); + + // Subscribe to global signals from core + uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox); + uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee); + uiInterface.ThreadSafeHandleURI.connect(ThreadSafeHandleURI); + uiInterface.InitMessage.connect(InitMessage); + //uiInterface.QueueShutdown.connect(QueueShutdown); + uiInterface.Translate.connect(Translate); + + // Show help message immediately after parsing command-line options (for "-lang") and setting locale, + // but before showing splash screen. + if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help")) + { + GUIUtil::HelpMessageBox help; + help.showOrPrint(); + return 1; + } + + // Start SetupWalletWizard if no wallet.dat exists +#ifndef ANDROID // temporarly remove setupwizard until fixed for android + if (!mapArgs.count("-bip44key") && !mapArgs.count("-wallet") && !mapArgs.count("-salvagewallet") && !fs::exists(GetDataDir() / "wallet.dat")) + { + SetupWalletWizard wizard; + wizard.show(); + if (!wizard.exec()) + return 0; + if (wizard.hasVisitedPage(SetupWalletWizard::Page_RecoverFromMnemonic)) + SoftSetBoolArg("-rescan", true); + } +#endif + + QSplashScreen splash(GUIUtil::createPixmap(600, 686, QColor(40, 40, 41), QString(":/assets/svg/Alias-Stacked-Reverse.svg"), QRect(62, 87, 476, 476))); + if (GetBoolArg("-splash", true) && !GetBoolArg("-min")) + { + splash.setEnabled(false); + splash.show(); + splashref = &splash; + } + + app.processEvents(); + + app.setQuitOnLastWindowClosed(false); + + //---- Create webSocket server for JavaScript client + QWebSocketServer server( + QStringLiteral("Alias Websocket Server"), + QWebSocketServer::NonSecureMode + ); + if (!server.listen(QHostAddress::LocalHost, fTestNet ? WEBSOCKETPORT_TESTNET : WEBSOCKETPORT)) { + qFatal("QWebSocketServer failed to listen on port 52471"); + return 1; + } + qDebug() << "QWebSocketServer started: " << server.serverAddress() << ":" << server.serverPort(); + + // wrap WebSocket clients in QWebChannelAbstractTransport objects + QString webSocketToken = QUuid::createUuid().toString().remove(QChar('{')).remove(QChar('}')); + // qDebug() << "QWebSocketServer access token: " << webSocketToken; + WebSocketClientWrapper clientWrapper(&server, webSocketToken); + + // setup the channel + QWebChannel webChannel; + QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected, + &webChannel, &QWebChannel::connectTo); + + try + { + // Regenerate startup link, to fix links to old versions + if (GUIUtil::GetStartOnSystemStartup()) + GUIUtil::SetStartOnSystemStartup(true); + + boost::thread_group threadGroup; + + SpectreGUI window(&webChannel); + window.setSplashScreen(&splash); + guiref = &window; + + // Periodically check if shutdown was requested to properly quit the Qt application + #if defined(Q_OS_WIN) && QT_VERSION >= 0x050000 + WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Alias Core did't yet exit safely..."), static_cast(window.winId())); + #endif + QTimer* pollShutdownTimer = new QTimer(guiref); + QObject::connect(pollShutdownTimer, SIGNAL(timeout()), guiref, SLOT(detectShutdown())); + pollShutdownTimer->start(200); + + if (AppInit2(threadGroup)) + { + // Put this in a block, so that the Model objects are cleaned up before calling Shutdown(). + { + // Get locks upfront, to make sure we can completly setup our client before core sends notifications + ENTER_CRITICAL_SECTION(cs_main); // no RAII + ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet); // no RAII + + paymentServer->setOptionsModel(&optionsModel); + + ClientModel clientModel(&optionsModel); + WalletModel walletModel(pwalletMain, &optionsModel); + window.setClientModel(&clientModel); + window.setWalletModel(&walletModel); + + InitMessage(_("Update balance...")); + + // Manually create a blockChangedEvent to set initial values for the UI + BlockChangedEvent blockChangedEvent = { nBestHeight, GetNumBlocksOfPeers(), IsInitialBlockDownload(), nNodeMode == NT_FULL ? + pindexBest ? pindexBest->GetBlockTime() : GENESIS_BLOCK_TIME : + pindexBestHeader ? pindexBestHeader->GetBlockTime() : GENESIS_BLOCK_TIME }; + uiInterface.NotifyBlocksChanged(blockChangedEvent); + + // Check if wallet unlock is needed to determine current balance + if (pwalletMain->IsLocked()) + { + WalletModel::UnlockContext unlockContext = walletModel.requestUnlock(WalletModel::UnlockMode::login); + if (!unlockContext.isValid()) + { + InitMessage(_("Shutdown...")); + StartShutdown(); + } + } + + if (!ShutdownRequested()) + { + InitMessage(_("...Start UI...")); + window.loadIndex(webSocketToken); + + // Now that initialization/startup is done, process any command-line + // spectre: URIs + QObject::connect(paymentServer, SIGNAL(receivedURI(QString)), &window, SLOT(handleURI(QString))); + QTimer::singleShot(100, paymentServer, SLOT(uiReady())); + } + + // Release lock before starting event processing, otherwise lock would never be released + LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet); + LEAVE_CRITICAL_SECTION(cs_main); + + if (!ShutdownRequested()) + app.exec(); + else + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + + window.hide(); + window.setClientModel(nullptr); + window.setWalletModel(nullptr); + guiref = nullptr; + } + // Shutdown the core and its threads, but don't exit Qt here + LogPrintf("Alias shutdown.\n\n"); + std::cout << "interrupt_all\n"; + threadGroup.interrupt_all(); + std::cout << "join_all\n"; + threadGroup.join_all(); + std::cout << "Shutdown\n"; + Shutdown(); + } else + { + threadGroup.interrupt_all(); + threadGroup.join_all(); + Shutdown(); + return 1; + }; + } catch (std::exception& e) { + handleRunawayException(&e); + } catch (...) { + handleRunawayException(nullptr); + } + return 0; +} +#endif // SPECTRE_QT_TEST diff --git a/src/qt/shadowbridge.cpp b/src/qt/spectrebridge.cpp similarity index 62% rename from src/qt/shadowbridge.cpp rename to src/qt/spectrebridge.cpp index 7f2d520568..c26d92e63d 100644 --- a/src/qt/shadowbridge.cpp +++ b/src/qt/spectrebridge.cpp @@ -1,9 +1,19 @@ -#include "shadowbridge.h" +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT -#include "shadowgui.h" +#include "spectrebridge.h" + +#include "spectregui.h" #include "guiutil.h" +#include "chainparams_migration.h" +#ifndef Q_MOC_RUN #include +#endif #include "editaddressdialog.h" @@ -12,11 +22,8 @@ #include "transactiondesc.h" #include "addresstablemodel.h" -#include "messagemodel.h" - #include "clientmodel.h" #include "walletmodel.h" -#include "messagemodel.h" #include "optionsmodel.h" #include "bitcoinunits.h" @@ -29,22 +36,27 @@ #include "txdb.h" #include "state.h" +#include "wallet.h" + #include "extkey.h" -#include "bridgetranslations.h" +#include "aliasbridgestrings.h" #include #include -#include #include #include #include +#include +#include #include #include #include +#include +#include #include -#define ROWS_TO_REFRESH 200 +#define ROWS_TO_REFRESH 500 extern CWallet* pwalletMain; extern CBlockIndex* pindexBest; @@ -52,276 +64,221 @@ extern CBlockIndex* FindBlockByHeight(int nHeight); extern CBlockIndex *InsertBlockIndex(uint256 hash); extern double GetDifficulty(const CBlockIndex* blockindex); -class TransactionModel : public QObject -{ - Q_OBJECT - -public: - TransactionModel(QObject *parent = 0) : +TransactionModel::TransactionModel(QObject *parent) : QObject(parent), ttm(new QSortFilterProxyModel()), running(false) - { } +{ } - ~TransactionModel() - { - delete ttm; - } - - void init(ClientModel * clientModel, TransactionTableModel * transactionTableModel) - { - this->clientModel = clientModel; - - ttm->setSourceModel(transactionTableModel); - ttm->setSortRole(Qt::EditRole); - ttm->sort(TransactionTableModel::Status, Qt::DescendingOrder); - } - - QVariantMap addTransaction(int row) - { - QModelIndex status = ttm->index (row, TransactionTableModel::Status); - QModelIndex date = status.sibling(row, TransactionTableModel::Date); - QModelIndex address = status.sibling(row, TransactionTableModel::ToAddress); - QModelIndex amount = status.sibling(row, TransactionTableModel::Amount); - - QVariantMap transaction; - - transaction.insert("id", status.data(TransactionTableModel::TxIDRole).toString()); - transaction.insert("tt", status.data(Qt::ToolTipRole).toString()); - transaction.insert("c", status.data(TransactionTableModel::ConfirmationsRole).toLongLong()); - transaction.insert("s", status.data(Qt::DecorationRole).toString()); - transaction.insert("d", date.data(Qt::EditRole).toInt()); - transaction.insert("d_s", date.data().toString()); - transaction.insert("t", TransactionRecord::getTypeShort(status.data(TransactionTableModel::TypeRole).toInt())); - transaction.insert("t_l", status.sibling(row, TransactionTableModel::Type).data().toString()); - transaction.insert("ad_c", address.data(Qt::ForegroundRole).value().name()); - transaction.insert("ad", address.data(TransactionTableModel::AddressRole).toString()); - transaction.insert("ad_l", address.data(TransactionTableModel::LabelRole).toString()); - transaction.insert("ad_d", address.data().toString()); - transaction.insert("n", status.sibling(row, TransactionTableModel::Narration).data().toString()); - transaction.insert("am_c", amount.data(Qt::ForegroundRole).value().name()); - transaction.insert("am", amount.data(TransactionTableModel::AmountRole).toString()); - transaction.insert("am_d", amount.data().toString()); - - return transaction; - } - - void populateRows(int start, int end) - { - if(start > ROWS_TO_REFRESH) - return; +TransactionModel::~TransactionModel() +{ + delete ttm; +} - if(!prepare()) - return; +void TransactionModel::init(ClientModel * clientModel, TransactionTableModel * transactionTableModel) +{ + this->clientModel = clientModel; - if (end > ROWS_TO_REFRESH) - end = ROWS_TO_REFRESH; + ttm->setSourceModel(transactionTableModel); + ttm->setSortRole(Qt::EditRole); + ttm->sort(TransactionTableModel::Status, Qt::DescendingOrder); +} - QVariantList transactions; +QVariantMap TransactionModel::addTransaction(int row) +{ + QModelIndex status = ttm->index (row, TransactionTableModel::Status); + QModelIndex date = status.sibling(row, TransactionTableModel::Date); + QModelIndex address = status.sibling(row, TransactionTableModel::ToAddress); + QModelIndex amount = status.sibling(row, TransactionTableModel::Amount); + + QVariantMap transaction; + + transaction.insert("id", status.data(TransactionTableModel::TxIDRole).toString()); + transaction.insert("tt", status.data(Qt::ToolTipRole).toString()); + transaction.insert("c", status.data(TransactionTableModel::ConfirmationsRole).toLongLong()); + transaction.insert("s", status.data(Qt::DecorationRole).toString()); + transaction.insert("s_i", status.data(TransactionTableModel::StatusRole).toInt()); + transaction.insert("d", date.data(Qt::EditRole).toInt()); + transaction.insert("d_s", date.data().toString()); + transaction.insert("t", TransactionRecord::getTypeShort(status.data(TransactionTableModel::TypeRole).toInt())); + transaction.insert("t_i", status.data(TransactionTableModel::TypeRole).toInt()); + transaction.insert("t_l", status.sibling(row, TransactionTableModel::Type).data().toString()); + transaction.insert("ad_c", address.data(Qt::ForegroundRole).value().name()); + transaction.insert("ad", address.data(TransactionTableModel::AddressRole).toString()); + transaction.insert("ad_l", address.data(TransactionTableModel::LabelRole).toString()); + transaction.insert("ad_d", address.data().toString()); + transaction.insert("n", status.sibling(row, TransactionTableModel::Narration).data().toString()); + transaction.insert("am_c", amount.data(Qt::ForegroundRole).value().name()); + transaction.insert("am", amount.data(TransactionTableModel::AmountRole).toLongLong()); + transaction.insert("am_d", amount.data().toString()); + transaction.insert("am_curr", amount.data(TransactionTableModel::CurrencyRole).toString()); + transaction.insert("am_unit", amount.data(TransactionTableModel::UnitRole).toInt()); + + return transaction; +} - while(start <= end) - { - if(visibleTransactions.first() == "*"||visibleTransactions.contains(ttm->index(start, TransactionTableModel::Type).data().toString())) - transactions.append(addTransaction(start)); +void TransactionModel::populateRows(int start, int end, int max) +{ + bool flush = ttm->sourceModel()->rowCount() == (end - start) + 1; + if (flush) max += transactionsBuffer.size(); + qDebug() << "populateRows start=" << start << " end=" << end << " max=" << max << " flush=" << flush << " running=" << running; + if(!prepare()) + return; - start++; + QDateTime lastBlockDate = clientModel->getLastBlockDate(); + uint skipped = 0; + int added = 0; + for (int row = start; row <= end && (max == 0 || added < max); row++) + { + if(visibleTransactions.first() == "*"||visibleTransactions.contains(ttm->index(row, TransactionTableModel::Type).data().toString())) { + // don't populate transaction which have been created AFTER the current block (state will be unchanged) + if (max != 0 && max < (end - start) + 1 && lastBlockDate < ttm->index(row, TransactionTableModel::Date).data(TransactionTableModel::DateRole).toDateTime()) + { + skipped++; + continue; + } + added++; + QVariantMap trx = addTransaction(row); + //qDebug() << "populateRows row=" << row << " hash=" << trx.value("id") << " d_s=" << trx.value("d_s") ; + transactionsBuffer.insert(trx.value("id").toString(), trx); } - if(!transactions.isEmpty()) - emitTransactions(transactions); - - running = false; } - void populatePage() - { - - if(!prepare()) - return; - - QVariantList transactions; - - int row = -1; - - while(++row < numRows && ttm->index(row, 0).isValid()) - if(visibleTransactions.first() == "*"||visibleTransactions.contains(ttm->index(row, TransactionTableModel::Type).data().toString())) - transactions.append(addTransaction(row)); - - if(!transactions.isEmpty()) - emitTransactions(transactions); - - running = false; + if (skipped > 0) + qDebug() << "populateRows skipped=" << skipped << " added=" << added; - } - QSortFilterProxyModel * getModel() + if (flush && transactionsBuffer.size() > 0) { - return ttm; + qDebug() << "emitTransactions " << transactionsBuffer.size(); + emitTransactions(transactionsBuffer.values()); + transactionsBuffer.clear(); } - bool isRunning() { - return running; - } + running = false; +} -signals: - void emitTransactions(const QVariantList & transactions, bool reset = false); +void TransactionModel::populatePage() +{ + qDebug() << "populatePage"; + if(!prepare()) + return; -private: - ClientModel *clientModel; - QSortFilterProxyModel *ttm; - QStringList visibleTransactions; - int numRows; - int rowsPerPage; - bool running; + QVariantList transactions; - bool prepare() - { - if (this->running) - return false; + int row = -1; - numRows = ttm->rowCount(); - ttm->sort(TransactionTableModel::Status, Qt::DescendingOrder); - rowsPerPage = clientModel->getOptionsModel()->getRowsPerPage(); - visibleTransactions = clientModel->getOptionsModel()->getVisibleTransactions(); + while(++row < numRows && ttm->index(row, 0).isValid()) + if(visibleTransactions.first() == "*"||visibleTransactions.contains(ttm->index(row, TransactionTableModel::Type).data().toString())) + transactions.append(addTransaction(row)); - this->running = true; + emitTransactions(transactions, true); - return true; - } -}; + running = false; +} -class AddressModel : public QObject +QSortFilterProxyModel * TransactionModel::getModel() { - Q_OBJECT - -public: - AddressTableModel *atm; - - QVariantMap addAddress(int row) - { - QVariantMap address; - QModelIndex label = atm->index(row, AddressTableModel::Label); + return ttm; +} - address.insert("type", label.data(AddressTableModel::TypeRole).toString()); - address.insert("label_value", label.data(Qt::EditRole).toString()); - address.insert("label", label.data().toString()); - address.insert("address", label.sibling(row, AddressTableModel::Address).data().toString()); - address.insert("pubkey", label.sibling(row, AddressTableModel::Pubkey).data().toString()); - address.insert("at", label.sibling(row, AddressTableModel::AddressType).data().toString()); +bool TransactionModel::isRunning() { + return running; +} - return address; - } +bool TransactionModel::prepare() +{ + if (this->running) + return false; - void poplateRows(int start, int end) - { - QVariantList addresses; + numRows = ttm->rowCount(); + ttm->sort(TransactionTableModel::Status, Qt::DescendingOrder); + rowsPerPage = clientModel->getOptionsModel()->getRowsPerPage(); + visibleTransactions = clientModel->getOptionsModel()->getVisibleTransactions(); - while(start <= end) - { - if(!atm->index(start, 0).isValid()) - continue; + this->running = true; - addresses.append(addAddress(start++)); - } - emitAddresses(addresses); - } + return true; +} - void populateAddressTable() - { - running = true; - int row = -1; - int end = atm->rowCount(); - QVariantList addresses; +QVariantMap AddressModel::addAddress(int row) +{ + QVariantMap address; + QModelIndex label = atm->index(row, AddressTableModel::Label); - while(++row < end) - { - if(!atm->index(row, 0).isValid()) - continue; + address.insert("type", label.data(AddressTableModel::TypeRole).toString()); + address.insert("label_value", label.data(Qt::EditRole).toString()); + address.insert("label", label.data().toString()); + address.insert("address", label.sibling(row, AddressTableModel::Address).data().toString()); + address.insert("pubkey", label.sibling(row, AddressTableModel::Pubkey).data().toString()); + address.insert("at", label.sibling(row, AddressTableModel::AddressType).data().toString()); - addresses.append(addAddress(row)); - } + return address; +} - emitAddresses(addresses, true); +void AddressModel::poplateRows(int start, int end) +{ + QVariantList addresses; - running = false; - } + while(start <= end) + { + if(!atm->index(start, 0).isValid()) + continue; - bool isRunning() { - return running; + addresses.append(addAddress(start++)); } + emitAddresses(addresses); +} -signals: - void emitAddresses(const QVariantList & addresses, bool reset = false); - -private: - bool running; -}; - -class MessageThread : public QThread +void AddressModel::populateAddressTable() { - Q_OBJECT + running = true; -signals: - void emitMessages(const QString & messages, bool reset); - -public: - MessageModel *mtm; - - QString addMessage(int row) - { - //QString message = "{\"id\":\"%10\",\"type\":\"%1\",\"sent_date\":\"%2\",\"received_date\":\"%3\", \"label_value\":\"%4\",\"label\":\"%5\",\"labelTo\":\"%11\",\"to_address\":\"%6\",\"from_address\":\"%7\",\"message\":\"%8\",\"read\":%9},"; - return QString("{\"id\":\"%10\",\"type\":\"%1\",\"sent_date\":\"%2\",\"received_date\":\"%3\", \"label_value\":\"%4\",\"label\":\"%5\",\"labelTo\":\"%11\",\"to_address\":\"%6\",\"from_address\":\"%7\",\"message\":\"%8\",\"read\":%9},") - .arg(mtm->index(row, MessageModel::Type) .data().toString()) - .arg(QString::number(mtm->index(row, MessageModel::SentDateTime) .data().toDateTime().toTime_t()).toHtmlEscaped()) - .arg(QString::number(mtm->index(row, MessageModel::ReceivedDateTime).data().toDateTime().toTime_t()).toHtmlEscaped()) - .arg(mtm->index(row, MessageModel::Label) .data(MessageModel::LabelRole).toString()) - .arg(mtm->index(row, MessageModel::Label) .data().toString().replace("\\", "\\\\").replace("/", "\\/").replace("\"","\\\"")) - .arg(mtm->index(row, MessageModel::ToAddress) .data().toString()) - .arg(mtm->index(row, MessageModel::FromAddress) .data().toString()) - .arg(mtm->index(row, MessageModel::Message) .data().toString().toHtmlEscaped().replace("\\", "\\\\").replace("\"","\\\"").replace("\n", "\\n")) - .arg(mtm->index(row, MessageModel::Read) .data().toBool()) - .arg(mtm->index(row, MessageModel::Key) .data().toString()) - .arg(mtm->index(row, MessageModel::LabelTo) .data().toString().replace("\\", "\\\\").replace("/", "\\/").replace("\"","\\\"")); - } + int row = -1; + int end = atm->rowCount(); + QVariantList addresses; -protected: - void run() + while(++row < end) { - int row = -1; - QString messages; - while (mtm->index(++row, 0, QModelIndex()).isValid()) - messages.append(addMessage(row)); + if(!atm->index(row, 0).isValid()) + continue; - emitMessages(messages, true); + addresses.append(addAddress(row)); } -}; + emitAddresses(addresses, true); -#include "shadowbridge.moc" + running = false; +} + +bool AddressModel::isRunning() { + return running; +} -ShadowBridge::ShadowBridge(ShadowGUI *window, QObject *parent) : +SpectreBridge::SpectreBridge(SpectreGUI *window, QObject *parent) : QObject (parent), window (window), transactionModel(new TransactionModel()), addressModel (new AddressModel()), - thMessage (new MessageThread()), info (new QVariantMap()), async (new QThread()) { async->start(); + connect(transactionModel->getModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateTransactions(QModelIndex,QModelIndex))); + connect(transactionModel->getModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(insertTransactions(QModelIndex,int,int))); } -ShadowBridge::~ShadowBridge() +SpectreBridge::~SpectreBridge() { delete transactionModel; delete addressModel; - delete thMessage; delete async; delete info; } // This is just a hook, we won't really be setting the model... -void ShadowBridge::setClientModel() +void SpectreBridge::setClientModel() { info->insert("version", CLIENT_VERSION); info->insert("build", window->clientModel->formatFullVersion()); @@ -329,37 +286,35 @@ void ShadowBridge::setClientModel() info->insert("name", window->clientModel->clientName()); populateOptions(); -} -// This is just a hook, we won't really be setting the model... -void ShadowBridge::setWalletModel() -{ - populateTransactionTable(); - populateAddressTable(); + emit infoChanged(); +} +void SpectreBridge::setWalletModel() { connect(window->clientModel->getOptionsModel(), SIGNAL(visibleTransactionsChanged(QStringList)), SLOT(populateTransactionTable())); } - -// This is just a hook, we won't really be setting the model... -void ShadowBridge::setMessageModel() -{ - populateMessageTable(); - connectSignals(); +void SpectreBridge::jsReady() { + window->pageLoaded(true); } -void ShadowBridge::copy(QString text) +void SpectreBridge::copy(QString text) { QApplication::clipboard()->setText(text); } -void ShadowBridge::paste() +void SpectreBridge::paste() { emitPaste(QApplication::clipboard()->text()); } +void SpectreBridge::urlClicked(const QString link) +{ + emit window->urlClicked(QUrl(link)); +} + // Options -void ShadowBridge::populateOptions() +void SpectreBridge::populateOptions() { OptionsModel *optionsModel(window->clientModel->getOptionsModel()); @@ -396,10 +351,6 @@ void ShadowBridge::populateOptions() visibleTransactions.append(txType); } - QVariantList messageTypes; - - messageTypes.append(tr("Incoming Message")); - notifications.insert("messages", messageTypes); notifications.insert("transactions", visibleTransactions); options.insert("optVisibleTransactions", visibleTransactions); @@ -412,7 +363,7 @@ void ShadowBridge::populateOptions() languages.insert("", "(" + tr("default") + ")"); - foreach(const QString &langStr, translations.entryList()) + for (const QString &langStr : translations.entryList()) { QLocale locale(langStr); @@ -421,15 +372,23 @@ void ShadowBridge::populateOptions() } options.insert("optLanguage", languages); + options.insert("Fee", options.value("Fee").toLongLong()); + options.insert("ReserveBalance", options.value("ReserveBalance").toLongLong() ); info->insert("options", options); } // Transactions -bool ShadowBridge::addRecipient(QString address, QString label, QString narration, qint64 amount, int txnType, int nRingSize) +void SpectreBridge::addRecipient(QString address, QString label, QString narration, qint64 amount, int txnType) { - SendCoinsRecipient rv; + // TODO Don't validate address atm, because UI does not properly handle addRecipientResult(false), address will be validated in sendCoins + // QRemoteObjectPendingReply validateAddressPendingReply = window->walletModel->validateAddress(address); + // if (!validateAddressPendingReply.waitForFinished() || !validateAddressPendingReply.returnValue()) { + // emit addRecipientResult(false); + // return; + // } + SendCoinsRecipient rv; rv.address = address; rv.label = label; @@ -437,58 +396,68 @@ bool ShadowBridge::addRecipient(QString address, QString label, QString narratio rv.amount = amount; std::string sAddr = address.toStdString(); + if (IsBIP32(sAddr.c_str())) rv.typeInd = 3; else rv.typeInd = address.length() > 75 ? AT_Stealth : AT_Normal; rv.txnTypeInd = txnType; - rv.nRingSize = nRingSize; + rv.nRingSize = GetRingSizeMinMax().first; recipients.append(rv); - return true; + emit addRecipientResult(true); } -void ShadowBridge::clearRecipients() +void SpectreBridge::clearRecipients() { recipients.clear(); } -bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) +QString lineBreakAddress(QString address) +{ + if (address.length() > 50) + return address.left(address.length() / 2) + "
" + address.mid(address.length() / 2); + else + return address; +} + +void SpectreBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) { int inputTypes = -1; int nAnonOutputs = 0; int ringSizes = -1; // Format confirmation message QStringList formatted; - foreach(const SendCoinsRecipient &rcp, recipients) + for (const SendCoinsRecipient &rcp : recipients) { - int inputType; // 0 SDC, 1 Shadow + int inputType; // 0 XSPEC, 1 Spectre switch(rcp.txnTypeInd) { - case TXT_SDC_TO_SDC: - formatted.append(tr("%1 to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, rcp.amount), Qt::escape(rcp.label), rcp.address)); + case TXT_SPEC_TO_SPEC: + formatted.append(tr("%1 from your public balance to %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, rcp.amount), rcp.label.toHtmlEscaped(), lineBreakAddress(rcp.address))); inputType = 0; break; - case TXT_SDC_TO_ANON: - formatted.append(tr("%1 to SHADOW %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, rcp.amount), Qt::escape(rcp.label), rcp.address)); + case TXT_SPEC_TO_ANON: + formatted.append(tr("%1 from public to private, using address %2 (%3)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, rcp.amount), rcp.label.toHtmlEscaped(), lineBreakAddress(rcp.address))); inputType = 0; nAnonOutputs++; break; case TXT_ANON_TO_ANON: - formatted.append(tr("%1 SHADOW, ring size %2 to SHADOW %3 (%4)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, rcp.amount), QString::number(rcp.nRingSize), Qt::escape(rcp.label), rcp.address)); + formatted.append(tr("%1 from your private balance, ring size %2, to %3 (%4)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, rcp.amount), QString::number(rcp.nRingSize), rcp.label.toHtmlEscaped(), lineBreakAddress(rcp.address))); inputType = 1; nAnonOutputs++; break; - case TXT_ANON_TO_SDC: - formatted.append(tr("%1 SHADOW, ring size %2 to SDC %3 (%4)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, rcp.amount), QString::number(rcp.nRingSize), Qt::escape(rcp.label), rcp.address)); + case TXT_ANON_TO_SPEC: + formatted.append(tr("%1 from private to public, ring size %2, using address %3 (%4)").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, rcp.amount), QString::number(rcp.nRingSize), rcp.label.toHtmlEscaped(), lineBreakAddress(rcp.address))); inputType = 1; break; default: QMessageBox::critical(window, tr("Error:"), tr("Unknown txn type detected %1.").arg(rcp.txnTypeInd), QMessageBox::Abort, QMessageBox::Abort); - return false; + emit sendCoinsResult(false); + return; } if (inputTypes == -1) @@ -498,7 +467,8 @@ bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) { QMessageBox::critical(window, tr("Error:"), tr("Input types must match for all recipients."), QMessageBox::Abort, QMessageBox::Abort); - return false; + emit sendCoinsResult(false); + return; }; if (inputTypes == 1) @@ -510,34 +480,42 @@ bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) { QMessageBox::critical(window, tr("Error:"), tr("Ring sizes must match for all recipients."), QMessageBox::Abort, QMessageBox::Abort); - return false; + emit sendCoinsResult(false); + return; }; - if (ringSizes < (int)MIN_RING_SIZE - || ringSizes > (int)MAX_RING_SIZE) + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (ringSizes < (int)nMinRingSize || ringSizes > (int)nMaxRingSize) { - QMessageBox::critical(window, tr("Error:"), tr("Ring size outside range [%1, %2].").arg(MIN_RING_SIZE).arg(MAX_RING_SIZE), - QMessageBox::Abort, QMessageBox::Abort); - return false; + QString message = nMinRingSize == nMaxRingSize ? tr("Ring size must be %1.").arg(nMinRingSize) : + tr("Ring size outside range [%1, %2].").arg(nMinRingSize).arg(nMaxRingSize); + QMessageBox::critical(window, tr("Error:"), message, QMessageBox::Abort, QMessageBox::Abort); + emit sendCoinsResult(false); + return; }; if (ringSizes == 1) { QMessageBox::StandardButton retval = QMessageBox::question(window, - tr("Confirm send coins"), tr("Are you sure you want to send?\nRing size of one is not anonymous, and harms the network.").arg(formatted.join(tr(" and "))), + tr("Confirm send coins"), tr("Are you sure you want to send?\nRing size of one is not anonymous.").arg(formatted.join(tr(" and "))), QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel); if (retval != QMessageBox::Yes) - return false; + emit sendCoinsResult(false); + return; }; }; }; - QMessageBox::StandardButton retval = QMessageBox::question(window, - tr("Confirm send coins"), tr("Are you sure you want to send %1?").arg(formatted.join(tr(" and "))), - QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel); + bool conversionTx = recipients.size() == 1 && (recipients[0].txnTypeInd == TXT_SPEC_TO_ANON || recipients[0].txnTypeInd == TXT_ANON_TO_SPEC); + QMessageBox::StandardButton retval = QMessageBox::question(window, tr("Confirm send coins"), + (conversionTx ? tr("Are you sure you want to convert %1?") : tr("Are you sure you want to send %1?")) + .arg(formatted.join(tr(" and "))), + QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Cancel); - if(retval != QMessageBox::Yes) - return false; + if(retval != QMessageBox::Yes) { + emit sendCoinsResult(false); + return; + } WalletModel::SendCoinsReturn sendstatus; @@ -551,7 +529,8 @@ bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) QMessageBox::warning(window, tr("Send Coins"), tr("The change address is not valid, please recheck."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; }; CoinControlDialog::coinControl->destChange = addrChange.Get(); @@ -562,13 +541,15 @@ bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) WalletModel::UnlockContext ctx(window->walletModel->requestUnlock()); // Unlock wallet was cancelled - if(!ctx.isValid()) - return false; + if(!ctx.isValid()) { + emit sendCoinsResult(false); + return; + } if (inputTypes == 1 || nAnonOutputs > 0) - sendstatus = window->walletModel->sendCoinsAnon(recipients, fUseCoinControl ? CoinControlDialog::coinControl : NULL); + sendstatus = window->walletModel->sendCoinsAnon(recipients, fUseCoinControl ? CoinControlDialog::coinControl : nullptr); else - sendstatus = window->walletModel->sendCoins (recipients, fUseCoinControl ? CoinControlDialog::coinControl : NULL); + sendstatus = window->walletModel->sendCoins (recipients, fUseCoinControl ? CoinControlDialog::coinControl : nullptr); switch(sendstatus.status) { @@ -576,94 +557,143 @@ bool ShadowBridge::sendCoins(bool fUseCoinControl, QString sChangeAddr) QMessageBox::warning(window, tr("Send Coins"), tr("The recipient address is not valid, please recheck."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; + case WalletModel::StealthAddressOnlyAllowedForSPECTRE: + QMessageBox::warning(window, tr("Send Coins"), + tr("Only ALIAS from your Private balance can be send to a stealth address."), + QMessageBox::Ok, QMessageBox::Ok); + emit sendCoinsResult(false); + return; + case WalletModel::RecipientAddressNotOwnedXSPECtoSPECTRE: + QMessageBox::warning(window, tr("Send Coins"), + tr("Transfer from Public to Private is only allowed within your account."), + QMessageBox::Ok, QMessageBox::Ok); + emit sendCoinsResult(false); + return; + case WalletModel::RecipientAddressNotOwnedSPECTREtoXSPEC: + QMessageBox::warning(window, tr("Send Coins"), + tr("Transfer from Private to Public is only allowed within your account."), + QMessageBox::Ok, QMessageBox::Ok); + emit sendCoinsResult(false); + return; case WalletModel::InvalidAmount: QMessageBox::warning(window, tr("Send Coins"), tr("The amount to pay must be larger than 0."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::AmountExceedsBalance: QMessageBox::warning(window, tr("Send Coins"), tr("The amount exceeds your balance."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::AmountWithFeeExceedsBalance: QMessageBox::warning(window, tr("Send Coins"), tr("The total exceeds your balance when the %1 transaction fee is included."). - arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, sendstatus.fee)), + arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, sendstatus.fee)), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::DuplicateAddress: QMessageBox::warning(window, tr("Send Coins"), tr("Duplicate address found, can only send to each address once per send operation."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::TransactionCreationFailed: QMessageBox::warning(window, tr("Send Coins"), tr("Error: Transaction creation failed."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::TransactionCommitFailed: QMessageBox::warning(window, tr("Send Coins"), tr("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::NarrationTooLong: QMessageBox::warning(window, tr("Send Coins"), - tr("Error: Narration is too long."), + tr("Error: Note is too long."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::RingSizeError: QMessageBox::warning(window, tr("Send Coins"), tr("Error: Ring Size Error."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::InputTypeError: QMessageBox::warning(window, tr("Send Coins"), tr("Error: Input Type Error."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::SCR_NeedFullMode: QMessageBox::warning(window, tr("Send Coins"), tr("Error: Must be in full mode to send anon."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::SCR_StealthAddressFail: QMessageBox::warning(window, tr("Send Coins"), tr("Error: Invalid Stealth Address."), QMessageBox::Ok, QMessageBox::Ok); - return false; - case WalletModel::SCR_AmountWithFeeExceedsShadowBalance: + emit sendCoinsResult(false); + return; + case WalletModel::SCR_StealthAddressFailAnonToSpec: + QMessageBox::warning(window, tr("Convert Alias from Private to Public"), + tr("Error: Invalid Stealth Address. Private to public conversion requires a stealth address."), + QMessageBox::Ok, QMessageBox::Ok); + emit sendCoinsResult(false); + return; + case WalletModel::SCR_AmountExceedsBalance: + QMessageBox::warning(window, tr("Send Coins"), + tr("The amount exceeds your ALIAS balance."), + QMessageBox::Ok, QMessageBox::Ok); + emit sendCoinsResult(false); + return; + case WalletModel::SCR_AmountWithFeeExceedsSpectreBalance: QMessageBox::warning(window, tr("Send Coins"), - tr("The total exceeds your shadow balance when the %1 transaction fee is included.").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, sendstatus.fee)), + tr("The total exceeds your private ALIAS balance when the %1 transaction fee is included.").arg(BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, sendstatus.fee)), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::SCR_Error: QMessageBox::warning(window, tr("Send Coins"), tr("Error generating transaction."), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::SCR_ErrorWithMsg: QMessageBox::warning(window, tr("Send Coins"), tr("Error generating transaction: %1").arg(sendstatus.hex), QMessageBox::Ok, QMessageBox::Ok); - return false; + emit sendCoinsResult(false); + return; case WalletModel::Aborted: // User aborted, nothing to do - return false; + emit sendCoinsResult(false); + return; case WalletModel::OK: //accept(); CoinControlDialog::coinControl->UnSelectAll(); CoinControlDialog::payAmounts.clear(); CoinControlDialog::updateLabels(window->walletModel, 0, this); recipients.clear(); + QMessageBox::information(window, tr("Send Coins"), + tr("Transaction successfully created.")); break; } - return true; + emit sendCoinsResult(true); + return; } -void ShadowBridge::openCoinControl() +void SpectreBridge::openCoinControl() { if (!window || !window->walletModel) return; @@ -675,101 +705,107 @@ void ShadowBridge::openCoinControl() CoinControlDialog::updateLabels(window->walletModel, 0, this); } -void ShadowBridge::updateCoinControlAmount(qint64 amount) +void SpectreBridge::updateCoinControlAmount(qint64 amount) { CoinControlDialog::payAmounts.clear(); CoinControlDialog::payAmounts.append(amount); CoinControlDialog::updateLabels(window->walletModel, 0, this); } -void ShadowBridge::updateCoinControlLabels(unsigned int &quantity, int64_t &amount, int64_t &fee, int64_t &afterfee, unsigned int &bytes, QString &priority, QString low, int64_t &change) +void SpectreBridge::updateCoinControlLabels(unsigned int &quantity, qint64 &amount, qint64 &fee, qint64 &afterfee, unsigned int &bytes, QString &priority, QString low, qint64 &change) { emitCoinControlUpdate(quantity, amount, fee, afterfee, bytes, priority, low, change); } -QVariantMap ShadowBridge::listAnonOutputs() +QVariantMap SpectreBridge::listAnonOutputs() { QVariantMap anonOutputs; typedef std::map outputCount; outputCount mOwnedOutputCounts; outputCount mMatureOutputCounts; - outputCount mSystemOutputCounts; - - if (pwalletMain->CountOwnedAnonOutputs(mOwnedOutputCounts, false) != 0 - || pwalletMain->CountOwnedAnonOutputs(mMatureOutputCounts, true) != 0) - { - LogPrintf("Error: CountOwnedAnonOutputs failed.\n"); - return anonOutputs; - }; - - for (std::map::iterator mi(mapAnonOutputStats.begin()); mi != mapAnonOutputStats.end(); mi++) - mSystemOutputCounts[mi->first] = 0; - if (pwalletMain->CountAnonOutputs(mSystemOutputCounts, true) != 0) { - LogPrintf("Error: CountAnonOutputs failed.\n"); - return anonOutputs; - }; - - for (std::map::iterator mi(mapAnonOutputStats.begin()); mi != mapAnonOutputStats.end(); mi++) - { - CAnonOutputCount* aoc = &mi->second; - QVariantMap anonOutput; - - int nDepth = aoc->nLeastDepth == 0 ? 0 : nBestHeight - aoc->nLeastDepth; + LOCK2(cs_main, pwalletMain->cs_wallet); - anonOutput.insert("owned_mature", mMatureOutputCounts[aoc->nValue]); - anonOutput.insert("owned_outputs", mOwnedOutputCounts [aoc->nValue]); - anonOutput.insert("system_mature", mSystemOutputCounts[aoc->nValue]); - anonOutput.insert("system_outputs", aoc->nExists); - anonOutput.insert("system_spends", aoc->nSpends); - anonOutput.insert("least_depth", nDepth); - anonOutput.insert("value_s", BitcoinUnits::format(window->clientModel->getOptionsModel()->getDisplayUnit(), aoc->nValue)); + if (pwalletMain->CountOwnedAnonOutputs(mOwnedOutputCounts, CWallet::MaturityFilter::NONE) != 0 + || pwalletMain->CountOwnedAnonOutputs(mMatureOutputCounts, CWallet::MaturityFilter::FOR_SPENDING) != 0) + { + LogPrintf("Error: CountOwnedAnonOutputs failed.\n"); + emit listAnonOutputsResult(anonOutputs); + return anonOutputs; + } - anonOutputs.insert(QString::number(aoc->nValue), anonOutput); - }; + for (const auto &pair : mapAnonOutputStats) + { + const CAnonOutputCount& aoc = pair.second; + QVariantMap anonOutput; + + anonOutput.insert("owned_mature", mMatureOutputCounts[aoc.nValue]); + anonOutput.insert("owned_outputs", mOwnedOutputCounts [aoc.nValue]); + anonOutput.insert("system_mature", aoc.nMature); + anonOutput.insert("system_compromised", aoc.nCompromised); + anonOutput.insert("system_outputs", aoc.nExists); + anonOutput.insert("system_spends", aoc.nSpends); + anonOutput.insert("system_unspent", aoc.nExists - aoc.nSpends); + anonOutput.insert("system_unspent_mature", aoc.numOfMatureUnspends()); + anonOutput.insert("system_mixins", aoc.nExists - aoc.nCompromised); + anonOutput.insert("system_mixins_mature", aoc.nMixins); + anonOutput.insert("system_mixins_staking", aoc.nMixinsStaking); + + anonOutput.insert("least_depth", aoc.nLastHeight == 0 ? '-' : nBestHeight - aoc.nLastHeight + 1); + anonOutput.insert("value_s", BitcoinUnits::format(window->clientModel->getOptionsModel()->getDisplayUnit(), aoc.nValue)); + + anonOutputs.insert(QString::number(aoc.nValue), anonOutput); + } + } + emit listAnonOutputsResult(anonOutputs); return anonOutputs; }; -void ShadowBridge::populateTransactionTable() +void SpectreBridge::populateTransactionTable() { if(transactionModel->thread() == thread()) { transactionModel->init(window->clientModel, window->walletModel->getTransactionTableModel()); - connect(transactionModel, SIGNAL(emitTransactions(QVariantList)), SIGNAL(emitTransactions(QVariantList)), Qt::QueuedConnection); + connect(transactionModel, SIGNAL(emitTransactions(QVariantList, bool)), SIGNAL(emitTransactions(QVariantList, bool)), Qt::QueuedConnection); transactionModel->moveToThread(async); } transactionModel->populatePage(); } -void ShadowBridge::updateTransactions(QModelIndex topLeft, QModelIndex bottomRight) +void SpectreBridge::updateTransactions(QModelIndex topLeft, QModelIndex bottomRight) { // Updated transactions... if(topLeft.column() == TransactionTableModel::Status) - transactionModel->populateRows(topLeft.row(), bottomRight.row()); + transactionModel->populateRows(topLeft.row(), bottomRight.row(), ROWS_TO_REFRESH); } -void ShadowBridge::insertTransactions(const QModelIndex & parent, int start, int end) +void SpectreBridge::insertTransactions(const QModelIndex & parent, int start, int end) { + qDebug() << "insertTransactions"; // New Transactions... transactionModel->populateRows(start, end); } -QString ShadowBridge::transactionDetails(QString txid) +void SpectreBridge::transactionDetails(QString txid) { - return window->walletModel->getTransactionTableModel()->index(window->walletModel->getTransactionTableModel()->lookupTransaction(txid), 0).data(TransactionTableModel::LongDescriptionRole).toString(); + QString txDetails = window->walletModel->getTransactionTableModel()->index(window->walletModel->getTransactionTableModel()->lookupTransaction(txid), 0).data(TransactionTableModel::LongDescriptionRole).toString(); + qDebug() << "Emit transaction details " << txDetails; + emit transactionDetailsResult(txDetails); } + // Addresses -void ShadowBridge::populateAddressTable() +void SpectreBridge::populateAddressTable() { if(addressModel->thread() == thread()) { addressModel->atm = window->walletModel->getAddressTableModel(); - + connect(addressModel->atm, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateAddresses(QModelIndex,QModelIndex))); + connect(addressModel->atm, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(insertAddresses(QModelIndex,int,int))); connect(addressModel, SIGNAL(emitAddresses(QVariantList)), SIGNAL(emitAddresses(QVariantList)), Qt::QueuedConnection); addressModel->moveToThread(async); } @@ -777,12 +813,12 @@ void ShadowBridge::populateAddressTable() addressModel->populateAddressTable(); } -void ShadowBridge::updateAddresses(QModelIndex topLeft, QModelIndex bottomRight) +void SpectreBridge::updateAddresses(QModelIndex topLeft, QModelIndex bottomRight) { addressModel->poplateRows(topLeft.row(), bottomRight.row()); } -void ShadowBridge::insertAddresses(const QModelIndex & parent, int start, int end) +void SpectreBridge::insertAddresses(const QModelIndex & parent, int start, int end) { // NOTE: Check inInitialBlockDownload here as many stealth addresses uncovered can slow wallet // fPassGuiAddresses allows addresses added manually to still reflect @@ -793,19 +829,25 @@ void ShadowBridge::insertAddresses(const QModelIndex & parent, int start, int en addressModel->poplateRows(start, end); } -QString ShadowBridge::newAddress(QString addressLabel, int addressType, QString address, bool send) +void SpectreBridge::newAddress(QString addressLabel, int addressType, QString address, bool send) { // Generate a new address to associate with given label - - // NOTE: unlock happens in addRow - QString rv = addressModel->atm->addRow(send ? AddressTableModel::Send : AddressTableModel::Receive, addressLabel, address, addressType); + addressModel->populateAddressTable(); +} - return rv; +//replica of the above method for Javascript to diffrentiate when call backs are needed +void SpectreBridge::newAddressAsync(QString addressLabel, int addressType, QString address, bool send) +{ + // Generate a new address to associate with given label + // NOTE: unlock happens in addRow + QString rv = addressModel->atm->addRow(send ? AddressTableModel::Send : AddressTableModel::Receive, addressLabel, address, addressType); + addressModel->populateAddressTable(); + emit newAddressResult(rv); } -QString ShadowBridge::lastAddressError() +void SpectreBridge::lastAddressError() { QString sError; AddressTableModel::EditStatus status = addressModel->atm->getEditStatus(); @@ -830,341 +872,72 @@ QString ShadowBridge::lastAddressError() break; }; - return sError; -} - -QString ShadowBridge::getAddressLabel(QString address) -{ - return addressModel->atm->labelForAddress(address); + emit lastAddressErrorResult(sError); } -void ShadowBridge::updateAddressLabel(QString address, QString label) +QString SpectreBridge::getAddressLabel(QString address) { - QString actualLabel = getAddressLabel(address); - - if(actualLabel.startsWith("group_")) - label = "group_" + label; - else if(label.startsWith("group_")) - return; - - addressModel->atm->setData(addressModel->atm->index(addressModel->atm->lookupAddress(address), addressModel->atm->Label), QVariant(label), Qt::EditRole); + QString result = addressModel->atm->labelForAddress(address); + return result; } -bool ShadowBridge::validateAddress(QString address) +void SpectreBridge::getAddressLabelAsync(QString address) { - return window->walletModel->validateAddress(address); + emit getAddressLabelResult(addressModel->atm->labelForAddress(address)); } -bool ShadowBridge::deleteAddress(QString address) +void SpectreBridge::getAddressLabelForSelectorAsync(QString address, QString selector, QString fallback) { - return addressModel->atm->removeRow(addressModel->atm->lookupAddress(address)); + emit getAddressLabelForSelectorResult(addressModel->atm->labelForAddress(address), selector, fallback); } -// Messages -void ShadowBridge::appendMessages(QString messages, bool reset) +void SpectreBridge::updateAddressLabel(QString address, QString label) { - emitMessages("[" + messages + "]", reset); -} - -void ShadowBridge::appendMessage(int row) -{ - emitMessage(window->messageModel->index(row, MessageModel::Key) .data().toString().toHtmlEscaped(), - window->messageModel->index(row, MessageModel::Type) .data().toString().toHtmlEscaped(), - window->messageModel->index(row, MessageModel::SentDateTime) .data().toDateTime().toTime_t(), - window->messageModel->index(row, MessageModel::ReceivedDateTime).data().toDateTime().toTime_t(), - window->messageModel->index(row, MessageModel::Label) .data(MessageModel::LabelRole).toString().toHtmlEscaped(), - window->messageModel->index(row, MessageModel::Label) .data().toString().replace("\"","\\\"").replace("\\", "\\\\").replace("/", "\\/").toHtmlEscaped(), - window->messageModel->index(row, MessageModel::LabelTo) .data().toString().replace("\"","\\\"").replace("\\", "\\\\").replace("/", "\\/").toHtmlEscaped(), - window->messageModel->index(row, MessageModel::ToAddress) .data().toString().toHtmlEscaped(), - window->messageModel->index(row, MessageModel::FromAddress) .data().toString().toHtmlEscaped(), - window->messageModel->index(row, MessageModel::Read) .data().toBool(), - window->messageModel->index(row, MessageModel::Message) .data().toString().toHtmlEscaped()); -} - -void ShadowBridge::populateMessageTable() -{ - thMessage->mtm = window->messageModel; - - connect(thMessage, SIGNAL(emitMessages(QString, bool)), SLOT(appendMessages(QString, bool))); - thMessage->start(); + const QModelIndex &index = addressModel->atm->index(addressModel->atm->lookupAddress(address), addressModel->atm->Label); + if (index.isValid()) + addressModel->atm->setData(index, QVariant(label), Qt::EditRole); + else + // AddressTableModel::Send never creates new addresses and addresses are only added to the addressbook + // Addresstype is detected from the address itself, a owned address is automatically added to the receiving list of addresses + addressModel->atm->addRow(AddressTableModel::Send, label, address, 0); } -void ShadowBridge::insertMessages(const QModelIndex & parent, int start, int end) +void SpectreBridge::validateAddress(QString address) { - while(start <= end) - { - appendMessage(start++); - qApp->processEvents(); - } + bool result = window->walletModel->validateAddress(address); + emit validateAddressResult(result); } -bool ShadowBridge::deleteMessage(QString key) +bool SpectreBridge::deleteAddress(QString address) { - return window->messageModel->removeRow(thMessage->mtm->lookupMessage(key)); + return addressModel->atm->removeRow(addressModel->atm->lookupAddress(address)); } -bool ShadowBridge::markMessageAsRead(QString key) -{ - return window->messageModel->markMessageAsRead(key); -} -QString ShadowBridge::getPubKey(QString address) +QString SpectreBridge::getPubKey(QString address) { return addressModel->atm->pubkeyForAddress(address);; } -bool ShadowBridge::setPubKey(QString address, QString pubkey) +void SpectreBridge::translateHtmlString(QString string) { - std::string sendTo = address.toStdString(); - std::string pbkey = pubkey.toStdString(); - - int res = SecureMsgAddAddress(sendTo, pbkey); - return res == 0||res == 4; + std::string result = QCoreApplication::translate("alias-bridge", qPrintable(string)).toStdString(); + LogPrintf("translateHtmlString: '%s' -> '%s'\n", string.toStdString(), result); + emit updateElement(string, QString::fromStdString(result)); } -bool ShadowBridge::sendMessage(const QString &address, const QString &message, const QString &from) +void SpectreBridge::getOptions() { - WalletModel::UnlockContext ctx(window->walletModel->requestUnlock()); - - // Unlock wallet was cancelled - if(!ctx.isValid()) - return false; - - MessageModel::StatusCode sendstatus = thMessage->mtm->sendMessage(address, message, from); - - switch(sendstatus) - { - case MessageModel::InvalidAddress: - QMessageBox::warning(window, tr("Send Message"), - tr("The recipient address is not valid, please recheck."), - QMessageBox::Ok, QMessageBox::Ok); - return false; - case MessageModel::InvalidMessage: - QMessageBox::warning(window, tr("Send Message"), - tr("The message can't be empty."), - QMessageBox::Ok, QMessageBox::Ok); - return false; - case MessageModel::DuplicateAddress: - QMessageBox::warning(window, tr("Send Message"), - tr("Duplicate address found, can only send to each address once per send operation."), - QMessageBox::Ok, QMessageBox::Ok); - return false; - case MessageModel::MessageCreationFailed: - QMessageBox::warning(window, tr("Send Message"), - tr("Error: Message creation failed."), - QMessageBox::Ok, QMessageBox::Ok); - return false; - case MessageModel::MessageCommitFailed: - QMessageBox::warning(window, tr("Send Message"), - tr("Error: The message was rejected."), - QMessageBox::Ok, QMessageBox::Ok); - return false; - case MessageModel::Aborted: // User aborted, nothing to do - return false; - case MessageModel::FailedErrorShown: // Send failed, error message was displayed - return false; - case MessageModel::OK: - break; - } - - return true; + emit getOptionResult(info->value("options")); } -QString ShadowBridge::createGroupChat(QString label) +QJsonValue SpectreBridge::userAction(QJsonValue action) { - //return address to invite to people to. - LOCK2(cs_main, pwalletMain->cs_wallet); - - std::string strLabel = "group_" + label.toStdString(); - - RandAddSeedPerfmon(); // util.cpp - CKey secret; // hey.h - secret.MakeNewKey(true); - CPubKey pubkey = secret.GetPubKey(); - CKeyID vchAddress = pubkey.GetID(); - - pwalletMain->MarkDirty(); - CBitcoinAddress addr(vchAddress); - - std::string strAddress = addr.ToString(); - - pwalletMain->SetAddressBookName(addr.Get(), strLabel, NULL, true, true); - - if (!pwalletMain->AddKeyPubKey(secret, pubkey)) - return "false"; - - SecureMsgAddWalletAddresses(); - - return QString::fromStdString(strAddress); -} - - -QString ShadowBridge::joinGroupChat(QString privkey, QString label) -{ - /* - EXPERIMENTAL CODE, UNTESTED. - */ - std::string strSecret = privkey.toStdString(); - std::string strLabel = "group_" + label.toStdString(); - - int64_t nCreateTime = 1; - CBitcoinSecret vchSecret; - bool fGood = vchSecret.SetString(strSecret); - - if (!fGood) return "false"; //throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); - if (fWalletUnlockStakingOnly) return "false"; //throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); - - CKey key = vchSecret.GetKey(); - CPubKey pubkey = key.GetPubKey(); - CKeyID vchAddress = pubkey.GetID(); - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - pwalletMain->MarkDirty(); - pwalletMain->SetAddressBookName(vchAddress, strLabel); - - // Don't throw error in case a key is already there - if (pwalletMain->HaveKey(vchAddress)) - return "false"; - - pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = nCreateTime; - - if (!pwalletMain->AddKeyPubKey(key, pubkey)) - return "false"; - //throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - - // whenever a key is imported, we need to scan the whole chain - pwalletMain->nTimeFirstKey = nCreateTime; // 0 would be considered 'no value' - - } - - SecureMsgAddWalletAddresses(); - //TODO: return address and appendAddress with javascript - CBitcoinAddress addr(vchAddress); - return QString::fromStdString(addr.ToString()); -} - - -QVariantList ShadowBridge::inviteGroupChat(QString qsaddress, QVariantList invites, QString from) -{ - //TODO: check if part of HD wallet, if it is refuse to send invites. - QVariantList r; //Return - - QString actualLabel = getAddressLabel(qsaddress); - - if(!actualLabel.startsWith("group_")){ - LogPrintf("[inviteGroupChat] -- This should never happen, if it does please notify devteam.\n"); - QMessageBox::warning(window, tr("Sanity Error!"), - tr("Error: a sanity check prevented the transfer of a non-group private key, please close your wallet and report this error to the development team as soon as possible."), - QMessageBox::Ok, QMessageBox::Ok); - } else { - actualLabel.replace("group_",""); - } - - QString informText = "Are you sure you want to invite the following addresses to this group?\n"; - - for(int i = 0; i < invites.size(); i++) - { - QString inviteAddress = invites.at(i).toString(); - QString inviteLabel = getAddressLabel(inviteAddress); - informText.append(inviteLabel + " -- " + inviteAddress + "\n"); - } - - QMessageBox msgBox; - msgBox.setStyleSheet("QLabel{min-width: 600px;}"); - msgBox.setText("Inviting to group " + actualLabel); - msgBox.setInformativeText(informText); - msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Ok); - - if(msgBox.exec() == QMessageBox::Cancel) - { - LogPrintf("[inviteGroupChat] -- inviteGroupChat aborted.\n"); - r.append("error"); - return r; - } - - LogPrintf("[inviteGroupChat] -- start\n"); - CBitcoinAddress address; - - if (!address.SetString(qsaddress.toStdString())) - { - LogPrintf("[inviteGroupChat] -- SetString address failed.\n"); - r.append("error"); - return r; + QString key = action.toArray().at(0).toString(); + if (key == "") { + key = action.toObject().keys().at(0); } - CKeyID keyID; - if (!address.GetKeyID(keyID)) - { - LogPrintf("[inviteGroupChat] -- GetKeyID failed.\n"); - r.append("error"); - return r; - } - - CKey vchSecret; - - if (!pwalletMain->GetKey(keyID, vchSecret)) - { - LogPrintf("[inviteGroupChat] -- GetKey failed.\n"); - r.append("error"); - return r; - } - - QString message = "/invite " + QString::fromStdString(CBitcoinSecret(vchSecret).ToString()) + " " + actualLabel; - - //SecureString privkey(); //.reserve then .assign(CBitcoinSecret(vchSecret).ToString())) - - for(int i = 0; i < invites.size(); i++) - { - QString inviteAddress = invites.at(i).toString(); - LogPrintf("[inviteGroupChat] sending invite!"); - - if(thMessage->mtm->sendMessage(inviteAddress, message, from) == MessageModel::OK) - r.append(inviteAddress); - } - - return invites; -} - -void ShadowBridge::connectSignals() -{ - connect(transactionModel->getModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateTransactions(QModelIndex,QModelIndex))); - connect(transactionModel->getModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(insertTransactions(QModelIndex,int,int))); - - connect(addressModel->atm, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(updateAddresses(QModelIndex,QModelIndex))); - connect(addressModel->atm, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(insertAddresses(QModelIndex,int,int))); - - connect(thMessage->mtm, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(insertMessages(QModelIndex,int,int))); - connect(thMessage->mtm, SIGNAL(modelReset()), SLOT(populateMessageTable())); -} - - -QString ShadowBridge::translateHtmlString(QString string) -{ - int i = 0; - while (html_strings[i] != 0) - { - if (html_strings[i] == string) - return tr(html_strings[i]); - - i++; - } - - return string; -} - -QVariantMap ShadowBridge::userAction(QVariantMap action) -{ - QVariantMap::iterator it(action.begin()); - - QString key(it.key()); - bool fOK; - key.toInt(&fOK); - - if(fOK) - key = it.value().toString(); - if(key == "backupWallet") window->backupWallet(); if(key == "close") @@ -1175,33 +948,46 @@ QVariantMap ShadowBridge::userAction(QVariantMap action) window->changePassphrase(); if(key == "toggleLock") window->toggleLock(); - if(key == "developerConsole") - window->webView->page()->triggerAction(QWebPage::InspectElement); if(key == "aboutClicked") window->aboutClicked(); if(key == "aboutQtClicked") window->aboutQtAction->trigger(); if(key == "debugClicked") + { window->rpcConsole->show(); + window->rpcConsole->activateWindow(); + window->rpcConsole->raise(); + } if(key == "clearRecipients") clearRecipients(); + if(key == "optionsChanged") { OptionsModel * optionsModel(window->clientModel->getOptionsModel()); - QVariantMap value(it.value().toMap()); - for(int option = 0;option < optionsModel->rowCount(); option++) - if(value.contains(optionsModel->optionIDName(option))) - optionsModel->setData(optionsModel->index(option), value.value(optionsModel->optionIDName(option))); + QJsonObject object = action.toObject().value("optionsChanged").toObject(); + + for(int option = 0;option < optionsModel->rowCount(); option++) { + if(object.contains(optionsModel->optionIDName(option))) { + optionsModel->setData(optionsModel->index(option), object.value(optionsModel->optionIDName(option)).toVariant()); + if (optionsModel->index(option).row() == OptionsModel::Language) { + QMessageBox::warning(window, tr("Please restart wallet"), tr("The used language has changed.\nPlease restart the wallet!"), + QMessageBox::Ok, QMessageBox::Ok); + } + } + } populateOptions(); + + //update options in javascript + getOptions(); } - return QVariantMap(); + return QJsonValue(); } // Blocks -QVariantMap ShadowBridge::listLatestBlocks() +void SpectreBridge::listLatestBlocks() { CBlockIndex* recentBlock = pindexBest; CBlock block; @@ -1210,13 +996,13 @@ QVariantMap ShadowBridge::listLatestBlocks() for (int x = 0; x < 5 && recentBlock; x++) { - block.ReadFromDisk(recentBlock, true); if (block.IsNull() || block.vtx.size() < 1) { latestBlocks.insert("error_msg", "Block not found."); - return latestBlocks; + emit listLatestBlocksResult(latestBlocks); + return; }; QVariantMap latestBlock; @@ -1228,10 +1014,11 @@ QVariantMap ShadowBridge::listLatestBlocks() latestBlocks.insert(QString::number(x) , latestBlock); recentBlock = recentBlock->pprev; } - return latestBlocks; + emit listLatestBlocksResult(latestBlocks); + return; } -QVariantMap ShadowBridge::findBlock(QString searchID) +void SpectreBridge::findBlock(QString searchID) { CBlockIndex* findBlock; @@ -1257,14 +1044,15 @@ QVariantMap ShadowBridge::findBlock(QString searchID) findBlock = mi->second; } else { - findBlock = NULL; + findBlock = nullptr; }; }; if (!findBlock) { foundBlock.insert("error_msg", "Block / transaction not found."); - return foundBlock; + emit findBlockResult(foundBlock); + return; }; CBlock block; @@ -1273,7 +1061,8 @@ QVariantMap ShadowBridge::findBlock(QString searchID) if (block.IsNull() || block.vtx.size() < 1) { foundBlock.insert("error_msg", "Block not found."); - return foundBlock; + emit findBlockResult(foundBlock); + return; }; foundBlock.insert("block_hash" , QString::fromStdString(findBlock->GetBlockHash().ToString())); @@ -1283,10 +1072,10 @@ QVariantMap ShadowBridge::findBlock(QString searchID) foundBlock.insert("block_size" , findBlock->nBits); foundBlock.insert("error_msg" , ""); - return foundBlock; + emit findBlockResult(foundBlock); } -QVariantMap ShadowBridge::blockDetails(QString blkHash) +void SpectreBridge::blockDetails(QString blkHash) { QVariantMap blockDetail; @@ -1300,7 +1089,8 @@ QVariantMap ShadowBridge::blockDetails(QString blkHash) if (mi == mapBlockIndex.end()) { blockDetail.insert("error_msg", "Block not found."); - return blockDetail; + emit blockDetailsResult(blockDetail); + return; }; blkIndex = mi->second; @@ -1309,7 +1099,8 @@ QVariantMap ShadowBridge::blockDetails(QString blkHash) if (block.IsNull() || block.vtx.size() < 1) { blockDetail.insert("error_msg", "Block not found."); - return blockDetail; + emit blockDetailsResult(blockDetail); + return; }; CTxDB txdb("r"); @@ -1364,10 +1155,11 @@ QVariantMap ShadowBridge::blockDetails(QString blkHash) blockDetail.insert("block_nonce" , blkIndex->nNonce); blockDetail.insert("error_msg" , ""); - return blockDetail; + emit blockDetailsResult(blockDetail); + return; } -QVariantMap ShadowBridge::listTransactionsForBlock(QString blkHash) +void SpectreBridge::listTransactionsForBlock(QString blkHash) { QVariantMap blkTransactions; @@ -1381,7 +1173,8 @@ QVariantMap ShadowBridge::listTransactionsForBlock(QString blkHash) if (mi == mapBlockIndex.end()) { blkTransactions.insert("error_msg", "Block not found."); - return blkTransactions; + emit listTransactionsForBlockResult(blkHash, blkTransactions); + return; }; selectedBlkIndex = mi->second; @@ -1390,7 +1183,8 @@ QVariantMap ShadowBridge::listTransactionsForBlock(QString blkHash) if (block.IsNull() || block.vtx.size() < 1) { blkTransactions.insert("error_msg", "Block not found."); - return blkTransactions; + emit listTransactionsForBlockResult(blkHash, blkTransactions); + return; }; for (uint x = 0; x < block.vtx.size(); x++) @@ -1407,10 +1201,11 @@ QVariantMap ShadowBridge::listTransactionsForBlock(QString blkHash) blkTransactions.insert(QString::number(x), blockTxn); } - return blkTransactions; + emit listTransactionsForBlockResult(blkHash, blkTransactions); + return; } -QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) +void SpectreBridge::txnDetails(QString blkHash, QString txnHash) { QVariantMap txnDetail; @@ -1427,7 +1222,8 @@ QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) if (mi == mapBlockIndex.end()) { txnDetail.insert("error_msg", "Block not found."); - return txnDetail; + emit txnDetailsResult(txnDetail); + return; }; selectedBlkIndex = mi->second; block.ReadFromDisk(selectedBlkIndex, true); @@ -1435,7 +1231,8 @@ QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) if (block.IsNull() || block.vtx.size() < 1) { txnDetail.insert("error_msg", "Block not found."); - return txnDetail; + emit txnDetailsResult(txnDetail); + return; }; for (uint x = 0; x < block.vtx.size(); x++) @@ -1475,7 +1272,7 @@ QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) if (txn.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) { - sAddr = "Shadow"; + sAddr = "ALIAS (private)"; std::vector vchImage; txin.ExtractKeyImage(vchImage); @@ -1531,7 +1328,7 @@ QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) if( txn.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput() ) - sAddr = "Shadow"; + sAddr = "ALIAS (private)"; else { CTxDestination address; @@ -1559,10 +1356,11 @@ QVariantMap ShadowBridge::txnDetails(QString blkHash, QString txnHash) break; } - return txnDetail; + emit txnDetailsResult(txnDetail); + return; } -QVariantMap ShadowBridge::signMessage(QString address, QString message) +QVariantMap SpectreBridge::signMessage(QString address, QString message) { QVariantMap result; @@ -1609,7 +1407,7 @@ QVariantMap ShadowBridge::signMessage(QString address, QString message) return result; } -QVariantMap ShadowBridge::verifyMessage(QString address, QString message, QString signature) +QVariantMap SpectreBridge::verifyMessage(QString address, QString message, QString signature) { QVariantMap result; @@ -1658,7 +1456,7 @@ QVariantMap ShadowBridge::verifyMessage(QString address, QString message, QStrin return result; } -QVariantMap ShadowBridge::getNewMnemonic(QString password, QString language) +void SpectreBridge::getNewMnemonic(QString password, QString language) { QVariantMap result; int nLanguage = language.toInt(); @@ -1683,13 +1481,15 @@ QVariantMap ShadowBridge::getNewMnemonic(QString password, QString language) if (0 != MnemonicEncode(nLanguage, vEntropy, sMnemonic, sError)) { result.insert("error_msg", strprintf("MnemonicEncode failed %s.", sError.c_str()).c_str()); - return result; + emit getNewMnemonicResult(result); + return; } if (0 != MnemonicToSeed(sMnemonic, sPassword, vSeed)) { result.insert("error_msg", "MnemonicToSeed failed."); - return result; + emit getNewMnemonicResult(result); + return; } ekMaster.SetMaster(&vSeed[0], vSeed.size()); @@ -1715,10 +1515,11 @@ QVariantMap ShadowBridge::getNewMnemonic(QString password, QString language) result.insert("mnemonic", QString::fromStdString(sMnemonic)); //result.insert("master", QString::fromStdString(sKey)); - return result; + emit getNewMnemonicResult(result); + return; } -QVariantMap ShadowBridge::importFromMnemonic(QString inMnemonic, QString inPassword, QString inLabel, bool fBip44, int64_t nCreateTime) +void SpectreBridge::importFromMnemonic(QString inMnemonic, QString inPassword, QString inLabel, bool fBip44, quint64 nCreateTime) { std::string sPassword = inPassword.toStdString(); std::string sMnemonic = inMnemonic.toStdString(); @@ -1731,13 +1532,15 @@ QVariantMap ShadowBridge::importFromMnemonic(QString inMnemonic, QString inPassw if (0 != MnemonicDecode(-1, sMnemonic, vEntropy, sError)) { result.insert("error_msg", QString::fromStdString(strprintf("MnemonicDecode failed %s.", sError.c_str()).c_str() )); - return result; + emit importFromMnemonicResult(result); + return; } if (0 != MnemonicToSeed(sMnemonic, sPassword, vSeed)) { result.insert("error_msg", "MnemonicToSeed failed."); - return result; + emit importFromMnemonicResult(result); + return; } CExtKey ekMaster; @@ -1747,7 +1550,8 @@ QVariantMap ShadowBridge::importFromMnemonic(QString inMnemonic, QString inPassw if (!ekMaster.IsValid()) { result.insert("error_msg", "Invalid key."); - return result; + emit importFromMnemonicResult(result); + return; } eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY); @@ -1762,7 +1566,7 @@ QVariantMap ShadowBridge::importFromMnemonic(QString inMnemonic, QString inPassw // m / purpose' / coin_type' / account' / change / address_index CExtKey ekDerived; ekMaster.Derive(ekDerived, BIP44_PURPOSE); - ekDerived.Derive(ekDerived, Params().BIP44ID()); + ekDerived.Derive(ekDerived, ChainParamsMigration::GetBIP44ID()); eKey58.SetKey(ekDerived, CChainParams::EXT_SECRET_KEY); @@ -1776,15 +1580,16 @@ QVariantMap ShadowBridge::importFromMnemonic(QString inMnemonic, QString inPassw // - in c++11 strings are definitely contiguous, and before they're very unlikely not to be // OPENSSL_cleanse(&sMnemonic[0], sMnemonic.size()); // OPENSSL_cleanse(&sPassword[0], sPassword.size()); - return result = extKeyImport(QString::fromStdString(eKey58.ToString()), inLabel, fBip44, nCreateTime); - + connect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + extKeyImport(QString::fromStdString(eKey58.ToString()), inLabel, fBip44, nCreateTime); + return; } inline uint32_t reversePlace(uint8_t *p) { uint32_t rv = 0; for (int i = 0; i < 4; ++i) - rv |= (uint32_t) *(p+i) << (8 * (3-i)); + rv |= static_cast(*(p+i)) << (8 * (3-i)); return rv; }; @@ -2019,7 +1824,7 @@ class GUIListExtCallback : public LoopExtKeyCallback QVariantMap *resultMap; }; -QVariantMap ShadowBridge::extKeyAccList() { +void SpectreBridge::extKeyAccList() { QVariantMap result; GUIListExtCallback extKeys(&result, 10 ); @@ -2033,10 +1838,11 @@ QVariantMap ShadowBridge::extKeyAccList() { addr.GetKeyID(extKeys.idMaster); - return result; + emit extKeyAccListResult(result); + return; } -QVariantMap ShadowBridge::extKeyList() { +void SpectreBridge::extKeyList() { QVariantMap result; GUIListExtCallback extKeys(&result, 10 ); @@ -2046,10 +1852,11 @@ QVariantMap ShadowBridge::extKeyList() { LoopExtKeysInDB(true, false, extKeys); } //cs_wallet - return result; + emit extKeyListResult(result); + return; } -QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip44, int64_t nCreateTime) +void SpectreBridge::extKeyImport(QString inKey, QString inLabel, bool fBip44, quint64 nCreateTime) { QVariantMap result; std::string sInKey = inKey.toStdString(); @@ -2065,15 +1872,18 @@ QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip if (!eKey58.IsValid(CChainParams::EXT_SECRET_KEY) && !eKey58.IsValid(CChainParams::EXT_PUBLIC_KEY_BTC)) { - result.insert("error_msg", "Import failed - Key must begin with Shadowcoin prefix."); - return result; + result.insert("error_msg", "Import failed - Key must begin with Alias prefix."); + emit extKeyImportResult(result); + return; } sek.kp = eKey58.GetKey(); } else { result.insert("error_msg", "Import failed - Invalid key."); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; }; { @@ -2082,19 +1892,25 @@ QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip if (!wdb.TxnBegin()) { result.insert("error_msg", "TxnBegin failed."); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; } int rv; - if (0 != (rv = pwalletMain->ExtKeyImportLoose(&wdb, sek, fBip44, false))) + if (0 != (rv = pwalletMain->ExtKeyImportLoose(&wdb, sek, fBip44, fBip44))) { wdb.TxnAbort(); result.insert("error_msg", QString("ExtKeyImportLoose failed, %1").arg(ExtKeyGetString(rv))); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; } else if (!wdb.TxnCommit()) { result.insert("error_msg", "TxnCommit failed."); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; }; } // cs_wallet @@ -2103,7 +1919,7 @@ QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip { CExtKey ekDerived; sek.kp.Derive(ekDerived, BIP44_PURPOSE); - ekDerived.Derive(ekDerived, Params().BIP44ID()); + ekDerived.Derive(ekDerived, ChainParamsMigration::GetBIP44ID()); sek.kp = ekDerived; } extKeySetMaster(QString::fromStdString(sek.GetIDString58())); @@ -2125,7 +1941,9 @@ QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip if (!wdb.TxnCommit()) { result.insert("error_msg", "TxnCommit failed!"); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; }; } // cs_wallet @@ -2137,10 +1955,12 @@ QVariantMap ShadowBridge::extKeyImport(QString inKey, QString inLabel, bool fBip // If we get here all went well and the message is valid result.insert("error_msg", ""); - return result; + emit extKeyImportResult(result); + disconnect(this, SIGNAL(extKeyImportResult(QVariantMap)), this, SIGNAL(importFromMnemonicResult(QVariantMap))); + return; } -QVariantMap ShadowBridge::extKeySetDefault(QString extKeyID) +void SpectreBridge::extKeySetDefault(QString extKeyID) { QVariantMap result; @@ -2148,7 +1968,8 @@ QVariantMap ShadowBridge::extKeySetDefault(QString extKeyID) if (extKeyID.length() == 0) { result.insert("error_msg", "Must specify ext key or id."); - return result; + emit extKeySetDefaultResult(result); + return; }; CKeyID idNewDefault; @@ -2166,25 +1987,29 @@ QVariantMap ShadowBridge::extKeySetDefault(QString extKeyID) if (!wdb.TxnBegin()) { result.insert("error_msg", "TxnBegin failed."); - return result; + emit extKeySetDefaultResult(result); + return; } if (!wdb.ReadExtAccount(idNewDefault, *sea)) { result.insert("error_msg", "Account not in wallet."); - return result; + emit extKeySetDefaultResult(result); + return; } if (!wdb.WriteNamedExtKeyId("defaultAccount", idNewDefault)) { wdb.TxnAbort(); result.insert("error_msg", "WriteNamedExtKeyId failed."); - return result; + emit extKeySetDefaultResult(result); + return; }; if (!wdb.TxnCommit()) { result.insert("error_msg", "TxnCommit failed."); - return result; + emit extKeySetDefaultResult(result); + return; } pwalletMain->idDefaultAccount = idNewDefault; @@ -2201,18 +2026,19 @@ QVariantMap ShadowBridge::extKeySetDefault(QString extKeyID) // If we get here all went well result.insert("error_msg", ""); - return result; + emit extKeySetDefaultResult(result); + return; } -QVariantMap ShadowBridge::extKeySetMaster(QString extKeyID) +void SpectreBridge::extKeySetMaster(QString extKeyID) { QVariantMap result; std::string sInKey = extKeyID.toStdString(); if (extKeyID.length() == 0) { result.insert("error_msg", "Must specify ext key or id."); - - return result; + emit extKeySetMasterResult(result); + return; }; CKeyID idNewMaster; @@ -2233,7 +2059,8 @@ QVariantMap ShadowBridge::extKeySetMaster(QString extKeyID) } else { result.insert("error_msg", "Invalid key: " + extKeyID); - return result; + emit extKeySetMasterResult(result); + return; }; { @@ -2242,7 +2069,8 @@ QVariantMap ShadowBridge::extKeySetMaster(QString extKeyID) if (!wdb.TxnBegin()) { result.insert("error_msg", "TxnBegin failed."); - return result; + emit extKeySetMasterResult(result); + return; } int rv; @@ -2250,12 +2078,14 @@ QVariantMap ShadowBridge::extKeySetMaster(QString extKeyID) { wdb.TxnAbort(); result.insert("error_msg", QString::fromStdString(strprintf("ExtKeySetMaster failed, %s.", ExtKeyGetString(rv)))); - return result; + emit extKeySetMasterResult(result); + return; }; if (!wdb.TxnCommit()) { result.insert("error_msg", "TxnCommit failed."); - return result; + emit extKeySetMasterResult(result); + return; } } // cs_wallet @@ -2263,10 +2093,11 @@ QVariantMap ShadowBridge::extKeySetMaster(QString extKeyID) result.insert("error_msg", ""); result.insert("result", "Success."); - return result; + emit extKeySetMasterResult(result); + return; } -QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) +void SpectreBridge::extKeySetActive(QString extKeyID, QString isActive) { QVariantMap result; std::string sInKey = extKeyID.toStdString(); @@ -2274,7 +2105,8 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) if (extKeyID.length() == 0) { result.insert("error_msg", "Must specify ext key or id."); - return result; + emit extKeySetActiveResult(result); + return; }; @@ -2284,7 +2116,8 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) if (!addr.SetString(sInKey)) { result.insert("error_msg", "Invalid key or account id."); - return result; + emit extKeySetActiveResult(result); + return; } bool fAccount = false; @@ -2303,7 +2136,8 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) } else { result.insert("error_msg", "Invalid key or account id."); - return result; + emit extKeySetActiveResult(result); + return; } CStoredExtKey sek; @@ -2314,7 +2148,8 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) if (!wdb.TxnBegin()) { result.insert("error_msg", "TxnBegin failed."); - return result; + emit extKeySetActiveResult(result); + return; } @@ -2333,13 +2168,15 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) { wdb.TxnAbort(); result.insert("error_msg", "Write failed."); - return result; + emit extKeySetActiveResult(result); + return; }; } else { wdb.TxnAbort(); result.insert("error_msg", "Account not in wallet."); - return result; + emit extKeySetActiveResult(result); + return; }; }; @@ -2358,20 +2195,23 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) { wdb.TxnAbort(); result.insert("error_msg", "Write failed."); - return result; + emit extKeySetActiveResult(result); + return; }; } else { wdb.TxnAbort(); result.insert("error_msg", "Account not in wallet."); - return result; + emit extKeySetActiveResult(result); + return; }; }; if (!wdb.TxnCommit()) { result.insert("error_msg", "TxnCommit failed."); - return result; + emit extKeySetActiveResult(result); + return; } } // cs_wallet @@ -2379,5 +2219,6 @@ QVariantMap ShadowBridge::extKeySetActive(QString extKeyID, QString isActive) // If we get here all went well result.insert("error_msg", ""); result.insert("result", "Success."); - return result; + emit extKeySetActiveResult(result); + return; } diff --git a/src/qt/spectrebridge.h b/src/qt/spectrebridge.h new file mode 100644 index 0000000000..4591e6bed2 --- /dev/null +++ b/src/qt/spectrebridge.h @@ -0,0 +1,197 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef SPECTREBRIDGE_H +#define SPECTREBRIDGE_H + +class SpectreGUI; +class ClientModel; +class TransactionTableModel; +class AddressTableModel; +class TransactionModel; +class QSortFilterProxyModel; +class WalletModel; +class BlockExplorerModel; +class AddressModel; +class MessageModel; +class MessageThread; +class SendCoinsRecipient; + +#include +#include +#include +#include +#include +#include +#include + +class TransactionModel : public QObject +{ + Q_OBJECT + +public: + TransactionModel(QObject *parent = nullptr); + ~TransactionModel(); + void init(ClientModel * clientModel, TransactionTableModel * transactionTableModel); + QVariantMap addTransaction(int row); + void populateRows(int start, int end, int max = 0); + void populatePage(); + QSortFilterProxyModel * getModel(); + bool isRunning(); + +Q_SIGNALS: + void emitTransactions(const QVariantList & transactions, bool reset = false); + +private: + ClientModel *clientModel{nullptr}; + QSortFilterProxyModel *ttm{nullptr}; + QStringList visibleTransactions; + QVariantMap transactionsBuffer; + int numRows{0}; + int rowsPerPage{0}; + bool running{false}; + + bool prepare(); +}; + +class AddressModel : public QObject +{ + Q_OBJECT + +public: + AddressTableModel *atm{nullptr}; + + QVariantMap addAddress(int row); + void poplateRows(int start, int end); + void populateAddressTable(); + bool isRunning(); + +Q_SIGNALS: + void emitAddresses(const QVariantList & addresses, bool reset = false); + +private: + bool running{false}; +}; + +class SpectreBridge : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariantMap info READ getInfo NOTIFY infoChanged) + +public: + explicit SpectreBridge(SpectreGUI *window, QObject *parent = nullptr); + ~SpectreBridge(); + + void setClientModel(); + void setWalletModel(); + void setTransactionModel(); + void setAddressModel(); + +public Q_SLOTS: + Q_INVOKABLE void jsReady(); + Q_INVOKABLE void copy(QString text); + Q_INVOKABLE void paste(); + Q_INVOKABLE void urlClicked(const QString link); + Q_INVOKABLE QString getAddressLabel(QString address); + Q_INVOKABLE void getAddressLabelAsync(QString address); + Q_INVOKABLE void getAddressLabelForSelectorAsync(QString address, QString selector, QString fallback = ""); + Q_INVOKABLE void newAddress(QString addressLabel, int addressType, QString address = "", bool send = false); + Q_INVOKABLE void newAddressAsync(QString addressLabel, int addressType, QString address = "", bool send = false); + Q_INVOKABLE void lastAddressError(); + Q_INVOKABLE void transactionDetails(QString txid); + Q_INVOKABLE QString getPubKey(QString address); + Q_INVOKABLE QJsonValue userAction(QJsonValue action); + Q_INVOKABLE void populateTransactionTable(); + Q_INVOKABLE void updateAddressLabel(QString address, QString label); + Q_INVOKABLE void validateAddress(QString own); + Q_INVOKABLE bool deleteAddress(QString address); + Q_INVOKABLE void openCoinControl(); + Q_INVOKABLE void addRecipient(QString address, QString label, QString narration, qint64 amount, int txnType); + Q_INVOKABLE void sendCoins(bool fUseCoinControl, QString sChangeAddr); + Q_INVOKABLE void updateCoinControlAmount(qint64 amount); + Q_INVOKABLE void updateCoinControlLabels(unsigned int &quantity, qint64 &amount, qint64 &fee, qint64 &afterfee, unsigned int &bytes, QString &priority, QString low, qint64 &change); + Q_INVOKABLE QVariantMap listAnonOutputs(); + Q_INVOKABLE void findBlock(QString searchID); + Q_INVOKABLE void listLatestBlocks(); + Q_INVOKABLE void blockDetails(QString blkid); + Q_INVOKABLE void listTransactionsForBlock(QString blkid); + Q_INVOKABLE void txnDetails(QString blkHash, QString txnHash); + Q_INVOKABLE QVariantMap signMessage(QString address, QString message); + Q_INVOKABLE QVariantMap verifyMessage(QString address, QString message, QString signature); + Q_INVOKABLE void importFromMnemonic(QString inMnemonic, QString inPassword, QString inLabel, bool fBip44 = false, quint64 nCreateTime = 0); + Q_INVOKABLE void getNewMnemonic(QString password, QString language); + Q_INVOKABLE void extKeyAccList(); + Q_INVOKABLE void extKeyList(); + Q_INVOKABLE void extKeyImport(QString inKey, QString inLabel, bool fBip44 = false, quint64 nCreateTime = 0); + Q_INVOKABLE void extKeySetDefault(QString extKeyID); + Q_INVOKABLE void extKeySetMaster(QString extKeyID); + Q_INVOKABLE void extKeySetActive(QString extKeySetActive, QString isActive); + Q_INVOKABLE void translateHtmlString(QString string); + Q_INVOKABLE void getOptions(); + +Q_SIGNALS: + void emitPaste(QString text); + void emitTransactions(QVariantList transactions, bool reset); + void emitAddresses(QVariantList addresses); + void emitCoinControlUpdate(unsigned int quantity, qint64 amount, qint64 fee, qint64 afterfee, unsigned int bytes, QString priority, QString low, qint64 change); + void emitAddressBookReturn(QString address, QString label); + void emitReceipient(QString address, QString label, QString narration, qint64 amount); + void triggerElement(QString element, QString trigger); + void networkAlert(QString alert); + void infoChanged(); + void validateAddressResult(bool result); + void addRecipientResult(bool result); + void sendCoinsResult(bool result); + void transactionDetailsResult(QString result); + void findBlockResult(QVariantMap result); + void listLatestBlocksResult(QVariantMap result); + void blockDetailsResult(QVariantMap result); + void listTransactionsForBlockResult(QString blkHash, QVariantMap result); + void txnDetailsResult(QVariantMap result); + void newAddressResult(QString result); + void lastAddressErrorResult(QString result); + void importFromMnemonicResult(QVariantMap result); + void getNewMnemonicResult(QVariantMap result); + void extKeyAccListResult(QVariantMap result); + void extKeyListResult(QVariantMap result); + void extKeyImportResult(QVariantMap result); + void extKeySetDefaultResult(QVariantMap result); + void extKeySetMasterResult(QVariantMap result); + void extKeySetActiveResult(QVariantMap result); + void getAddressLabelResult(QString result); + void getAddressLabelToSendBalanceResult(QString result); + void getAddressLabelForSelectorResult(QString result, QString selector, QString fallback); + void getOptionResult(QVariant result); + void listAnonOutputsResult(QVariantMap result); + void updateElement(QString sourceString, QString translatedString); + +private: + SpectreGUI *window{nullptr}; + TransactionModel *transactionModel{nullptr}; + AddressModel *addressModel{nullptr}; + QList recipients; + QVariantMap *info{nullptr}; + QThread *async{nullptr}; + + friend class SpectreGUI; + + inline QVariantMap getInfo() const { return *info; } + + void populateOptions(); + void populateAddressTable(); + void connectSignals(); + void clearRecipients(); + void appendMessage(int row); + +private Q_SLOTS: + void updateTransactions(QModelIndex topLeft, QModelIndex bottomRight); + void updateAddresses(QModelIndex topLeft, QModelIndex bottomRight); + void insertTransactions(const QModelIndex &parent, int start, int end); + void insertAddresses(const QModelIndex &parent, int start, int end); +}; + +#endif // SPECTREBRIDGE_H diff --git a/src/qt/spectregui.cpp b/src/qt/spectregui.cpp new file mode 100644 index 0000000000..8b5e009366 --- /dev/null +++ b/src/qt/spectregui.cpp @@ -0,0 +1,1153 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT + +#include "spectregui.h" +#include "transactiontablemodel.h" +#include "transactionrecord.h" + +#include "aboutdialog.h" +#include "clientmodel.h" +#include "walletmodel.h" +#include "optionsmodel.h" +#include "addresstablemodel.h" +#include "bitcoinunits.h" +#include "guiconstants.h" +#include "askpassphrasedialog.h" +#include "notificator.h" +#include "guiutil.h" +#include "wallet.h" +#include "util.h" +#include "init.h" +#include "version.h" +#include "stealth.h" + +#ifdef Q_OS_MACOS +#include "macdockiconhandler.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CWallet* pwalletMain; +double GetPoSKernelPS(); +double GetPoSKernelPSRecent(); + +void SpectreGUI::runJavaScript(QString javascriptCode) +{ + if (uiReady) + QMetaObject::invokeMethod(qmlWebView, "runJavaScript", Q_ARG(QString, javascriptCode)); +} + +SpectreGUI::WebElement::WebElement(SpectreGUI* spectreGUI, QString name, SelectorType type) +{ + this->spectreGUI = spectreGUI; + this->name = name; + switch (type) { + case SelectorType::ID: + this->getElementJS = "document.getElementById('" + this->name +"')."; + break; + case SelectorType::CLASS: + this->getElementJS = "document.getElementsByClassName('" + this->name +"')[0]."; + break; + default: + qFatal("SelectorType not reconized at WebElement::WebElement"); + break; + } +} + +void SpectreGUI::WebElement::setAttribute(QString attribute, QString value) +{ + //"setAttribute('data-title', '" + dataTitle + "');"; + value = value.replace("\n"," "); + QString javascriptCode = getElementJS + "setAttribute(\"" + attribute + "\", \"" + value + "\");"; + spectreGUI->runJavaScript(javascriptCode); +} + +void SpectreGUI::WebElement::removeAttribute(QString attribute) +{ + //"setAttribute('data-title', '" + dataTitle + "');"; + QString javascriptCode = getElementJS + "removeAttribute(\"" + attribute + "\");"; + spectreGUI->runJavaScript(javascriptCode); +} + +void SpectreGUI::WebElement::addClass(QString className) +{ + QString javascriptCode = getElementJS + "classList.add(\""+className+"\");"; + spectreGUI->runJavaScript(javascriptCode); +} + +void SpectreGUI::WebElement::removeClass(QString className) +{ + QString javascriptCode = getElementJS + "classList.remove(\""+className+"\");"; + spectreGUI->runJavaScript(javascriptCode); +} + +void SpectreGUI::WebElement::setContent(QString value) +{ + value = value.replace("\n"," "); + QString javascriptCode = getElementJS + "innerHTML = \"" + value + "\";"; + spectreGUI->runJavaScript(javascriptCode); +} + +QString webviewResource(QString resource) +{ +#ifdef ANDROID + return resource; +#else + return "qrc:///" + resource; +#endif +} + +SpectreGUI::SpectreGUI(QWebChannel *webChannel, QWidget *parent): + QMainWindow(parent), + bridge(new SpectreBridge(this)), + clientModel(nullptr), + walletModel(nullptr), + messageModel(nullptr), + encryptWalletAction(nullptr), + changePassphraseAction(nullptr), + unlockWalletAction(nullptr), + lockWalletAction(nullptr), + aboutQtAction(nullptr), + trayIcon(nullptr), + notificator(nullptr), + rpcConsole(nullptr), + nWeight(0), + uiReady(false) +{ + // Make bridge available for JS client + this->webChannel = webChannel; + addJavascriptObjects(QStringLiteral("bridge"), bridge); + + resize(1280, 720); + setWindowTitle(tr("Alias") + " - " + tr("Client") + " - " + tr(CLIENT_PLAIN_VERSION.c_str())); +#ifndef Q_OS_MAC + qApp->setWindowIcon(QIcon(":icons/alias-app")); + setWindowIcon(QIcon(":icons/alias-app")); +#else + setUnifiedTitleAndToolBarOnMac(true); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); +#endif + + // Accept D&D of URIs + setAcceptDrops(true); + + // Create actions for the toolbar, menu bar and tray/dock icon + createActions(); + + // Create application menu bar + createMenuBar(); + +#ifndef ANDROID // chrash in setupUi(QDialog *RPCConsole) + rpcConsole = new RPCConsole(this); + + connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(show())); + connect(openRPCConsoleAction, SIGNAL(triggered()), rpcConsole, SLOT(raise())); + + // prevents an oben debug window from becoming stuck/unusable on client shutdown + connect(quitAction, SIGNAL(triggered()), rpcConsole, SLOT(hide())); +#endif + + // This timer will be fired repeatedly to update the balance + pollTimer = new QTimer(this); +} + +void initMessage(QSplashScreen *splashScreen, const std::string &message) +{ + if(splashScreen) + { + splashScreen->showMessage(QString::fromStdString("v"+FormatClientVersion()) + "\n" + QString::fromStdString(message) + "\n", Qt::AlignBottom|Qt::AlignHCenter, QColor(138,140,142)); + QApplication::instance()->processEvents(); + } +} + +unsigned short const onion_port = 9089; + +void SpectreGUI::loadIndex(QString webSocketToken) { +#ifdef Q_OS_WIN + QFile html("C:/alias-wallet-ui/index.html"); + QFileInfo webchannelJS("C:/alias-wallet-ui/qtwebchannel/qwebchannel.js"); +#else + QFile html("/opt/alias-wallet-ui/index.html"); + QFileInfo webchannelJS("/opt/alias-wallet-ui/qtwebchannel/qwebchannel.js"); +#endif + // Check if external qwebchannel exists and if not, create it! (this is how you get the right qwebchannel.js) + if (html.exists() && !webchannelJS.exists()) { + qDebug() << "Copy qwebchannel.js to" << webchannelJS.absoluteFilePath(); + QFile::copy(":/qtwebchannel/qwebchannel.js",webchannelJS.absoluteFilePath()); + } + + QQuickWidget *view = new QQuickWidget(this); + view->setResizeMode(QQuickWidget::SizeRootObjectToView); + view->setSource(QUrl("qrc:///qml/main")); + qmlWebView = view->rootObject()->findChild("webView"); + QUrl url((html.exists() ? "file:///" + html.fileName() : "qrc:///src/qt/res/index.html") + + (fTestNet ? "?websocketport=" + QString::number(WEBSOCKETPORT_TESTNET) + "&" : "?") + + "token=" + webSocketToken); + qmlWebView->setProperty("url", url); + + setCentralWidget(view); + view->show(); + +//#ifdef TEST_TOR +// QNetworkProxy proxy; +// proxy.setType(QNetworkProxy::Socks5Proxy); +// proxy.setHostName("127.0.0.1"); +// proxy.setPort(onion_port); +// QNetworkProxy::setApplicationProxy(proxy); + +// //https://check.torproject.org +// webEngineView->setUrl(QUrl("https://check.torproject.org")); +//#endif +} + +SpectreGUI::~SpectreGUI() +{ + if(trayIcon) // Hide tray icon, as deleting will let it linger until quit (on Ubuntu) + trayIcon->hide(); + +#ifdef Q_OS_MACOS + delete appMenuBar; +#endif +} + +void SpectreGUI::pageLoaded(bool ok) +{ + uiReady = true; + initMessage(splashScreen, tr("..Start UI..").toStdString()); + + // Create the tray icon (or setup the dock icon) + if (!initialized) createTrayIcon(); + + // Populate data + walletModel->getOptionsModel()->emitDisplayUnitChanged(walletModel->getOptionsModel()->getDisplayUnit()); + walletModel->getOptionsModel()->emitReserveBalanceChanged(walletModel->getOptionsModel()->getReserveBalance()); + walletModel->getOptionsModel()->emitRowsPerPageChanged(walletModel->getOptionsModel()->getRowsPerPage()); + setNumConnections(clientModel->getNumConnections()); + setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers()); + setEncryptionStatus(walletModel->getEncryptionStatus()); + walletModel->emitEncryptionStatusChanged(walletModel->getEncryptionStatus()); + + bridge->populateTransactionTable(); + bridge->populateAddressTable(); + + initMessage(splashScreen, tr(".Start UI.").toStdString()); + { + LOCK2(cs_main, pwalletMain->cs_wallet); + walletModel->checkBalanceChanged(true); + updateStakingIcon(); + if (!initialized) + { + QTimer *timerStakingIcon = new QTimer(this); + connect(timerStakingIcon, SIGNAL(timeout()), this, SLOT(updateStakingIcon())); + timerStakingIcon->start(5 * 1000); + } + } + + // Customize UI + if (!fDebug) + runJavaScript(QString("var sheet = document.createElement('style'); sheet.innerHTML = '.only-debug { display: none !important }'; document.body.appendChild(sheet);")); +#ifdef ANDROID + runJavaScript(QString("var sheet = document.createElement('style'); sheet.innerHTML = '.only-desktop { display: none !important }'; document.body.appendChild(sheet);")); +#endif + + initMessage(splashScreen, tr("Ready!").toStdString()); + if (splashScreen) splashScreen->finish(this); + initialized = true; + + // If -min option passed, start window minimized. + if(GetBoolArg("-min")) + showMinimized(); + else + show(); + + pollTimer->start(MODEL_UPDATE_DELAY); +} + +void SpectreGUI::addJavascriptObjects(const QString &id, QObject *object) +{ + //register a QObject to be exposed to JavaScript + webChannel->registerObject(id, object); +} + +void SpectreGUI::urlClicked(const QUrl & link) +{ + if(link.scheme() == "qrc" || link.scheme() == "file") + return; + + QDesktopServices::openUrl(link); +} + +void SpectreGUI::createActions() +{ + + quitAction = new QAction(QIcon(":/icons/quit"), tr("E&xit"), this); + quitAction->setToolTip(tr("Quit application")); + quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + quitAction->setMenuRole(QAction::QuitRole); + aboutAction = new QAction(QIcon(":/icons/spectre"), tr("&About Alias"), this); + aboutAction->setToolTip(tr("Show information about Alias")); + aboutAction->setMenuRole(QAction::AboutRole); + aboutQtAction = new QAction(QIcon(":/trolltech/qmessagebox/images/qtlogo-64.png"), tr("About &Qt"), this); + aboutQtAction->setToolTip(tr("Show information about Qt")); + aboutQtAction->setMenuRole(QAction::AboutQtRole); + optionsAction = new QAction(QIcon(":/icons/options"), tr("&Options..."), this); + optionsAction->setToolTip(tr("Modify configuration options for Alias")); + optionsAction->setMenuRole(QAction::PreferencesRole); + toggleHideAction = new QAction(QIcon(":/icons/alias-app"), tr("&Show / Hide"), this); + encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this); + encryptWalletAction->setToolTip(tr("Encrypt or decrypt wallet")); + encryptWalletAction->setCheckable(true); + backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this); + backupWalletAction->setToolTip(tr("Backup wallet to another location")); + changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this); + changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); + unlockWalletAction = new QAction(QIcon(":/icons/lock_open"), tr("&Unlock Wallet..."), this); + unlockWalletAction->setToolTip(tr("Unlock wallet")); + lockWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Lock Wallet"), this); + lockWalletAction->setToolTip(tr("Lock wallet")); + + //exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this); + //exportAction->setToolTip(tr("Export the data in the current tab to a file")); + openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); + openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); + + connect(quitAction, SIGNAL(triggered()), SLOT(requestShutdown())); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + connect(aboutAction, SIGNAL(triggered()), SLOT(aboutClicked())); + connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + connect(optionsAction, SIGNAL(triggered()), SLOT(optionsClicked())); + connect(toggleHideAction, SIGNAL(triggered()), SLOT(toggleHidden())); + connect(encryptWalletAction, SIGNAL(triggered(bool)), SLOT(encryptWallet(bool))); + connect(backupWalletAction, SIGNAL(triggered()), SLOT(backupWallet())); + connect(changePassphraseAction, SIGNAL(triggered()), SLOT(changePassphrase())); + connect(unlockWalletAction, SIGNAL(triggered()), SLOT(unlockWallet())); + connect(lockWalletAction, SIGNAL(triggered()), SLOT(lockWallet())); +} + +void SpectreGUI::createMenuBar() +{ +#ifdef ANDROID + // no menubar for android + return; +#elif defined(Q_OS_MACOS) + // Create a decoupled menu bar on Mac which stays even if the window is closed + appMenuBar = new QMenuBar(); +#else + // Get the main window's menu bar on other platforms + appMenuBar = menuBar(); + appMenuBar->hide(); +#endif + + // Configure the menus + QMenu *file = appMenuBar->addMenu(tr("&File")); + file->addAction(backupWalletAction); + //file->addAction(exportAction); + file->addSeparator(); + file->addAction(quitAction); + + QMenu *settings = appMenuBar->addMenu(tr("&Settings")); + settings->addAction(encryptWalletAction); + settings->addAction(changePassphraseAction); + settings->addAction(unlockWalletAction); + settings->addAction(lockWalletAction); + settings->addSeparator(); + settings->addAction(optionsAction); + + QMenu *help = appMenuBar->addMenu(tr("&Help")); + help->addAction(openRPCConsoleAction); + help->addSeparator(); + help->addAction(aboutAction); + help->addAction(aboutQtAction); +} + +void SpectreGUI::setClientModel(ClientModel *clientModel) +{ + this->clientModel = clientModel; + if (clientModel) + { + int mode = clientModel->getClientMode(); + if (mode != NT_FULL) + { + QString sMode = QString::fromLocal8Bit(GetNodeModeName(mode)); + if (sMode.length() > 0) + sMode[0] = sMode[0].toUpper(); + + setWindowTitle(tr("Alias") + " - " + tr("Wallet") + ", " + sMode); + }; + + // Replace some strings and icons, when using the testnet + if (clientModel->isTestNet()) + { + setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]")); +#ifndef Q_OS_MAC + qApp->setWindowIcon(QIcon(":icons/alias-app_testnet")); + setWindowIcon(QIcon(":icons/alias-app_testnet")); +#else + MacDockIconHandler::instance()->setIcon(QIcon(":icons/alias-app_testnet")); +#endif + if(trayIcon) + { + trayIcon->setToolTip(tr("Alias") + QString(" ") + tr("[testnet]")); + trayIcon->setIcon(QIcon(":/icons/alias-app_testnet")); + toggleHideAction->setIcon(QIcon(":/icons/toolbar_testnet")); + } + + aboutAction->setIcon(QIcon(":/icons/toolbar_testnet")); + } + + connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); + connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int))); + + // Report errors from network/worker thread + connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); + + rpcConsole->setClientModel(clientModel); + + bridge->setClientModel(); + } +} + +void SpectreGUI::setWalletModel(WalletModel *walletModel) +{ + this->walletModel = walletModel; + if(walletModel) + { + // Report errors from wallet thread + connect(walletModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool))); + + connect(walletModel, SIGNAL(encryptionStatusChanged(int)), SLOT(setEncryptionStatus(int))); + + // Balloon pop-up for new transaction + connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(incomingTransaction(QModelIndex,int,int))); + + // Ask for passphrase if needed + connect(walletModel, SIGNAL(requireUnlock(WalletModel::UnlockMode)), this, SLOT(unlockWallet(WalletModel::UnlockMode))); + + connect(pollTimer, SIGNAL(timeout()), walletModel, SLOT(pollBalanceChanged())); + + bridge->setWalletModel(); + + //register a QObject to be exposed to JavaScript + addJavascriptObjects(QStringLiteral("walletModel"), walletModel); + if (walletModel->getOptionsModel() != nullptr) + //register a QObject to be exposed to JavaScript + addJavascriptObjects(QStringLiteral("optionsModel"), walletModel->getOptionsModel()); + } +} + +void SpectreGUI::setSplashScreen(QSplashScreen * splashScreen) +{ + this->splashScreen = splashScreen; +} + +void SpectreGUI::createTrayIcon() +{ + QMenu *trayIconMenu; +#ifndef Q_OS_MACOS + trayIcon = new QSystemTrayIcon(this); + trayIconMenu = new QMenu(this); + trayIcon->setContextMenu(trayIconMenu); + trayIcon->setToolTip(tr("Alias")); + trayIcon->setIcon(QIcon(":/icons/alias-app")); + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); + trayIcon->show(); +#else + // Note: On Mac, the dock icon is used to provide the tray's functionality. + MacDockIconHandler *dockIconHandler = MacDockIconHandler::instance(); + dockIconHandler->setMainWindow(static_cast(this)); + trayIconMenu = dockIconHandler->dockMenu(); +#endif + + // Configuration of the tray icon (or dock icon) icon menu + trayIconMenu->addAction(toggleHideAction); + trayIconMenu->addSeparator(); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(optionsAction); + trayIconMenu->addAction(openRPCConsoleAction); +#ifndef Q_OS_MACOS // This is built-in on Mac + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); +#endif + + notificator = new Notificator(qApp->applicationName(), trayIcon, this); +} + +//#ifndef Q_OS_MACOS // commented because with QT 5.9.9 moc processor did not consider ifndef +void SpectreGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason) +{ + if(reason == QSystemTrayIcon::Trigger) + { + // Click on system tray icon triggers show/hide of the main window + toggleHideAction->trigger(); + } +} +//#endif + +void SpectreGUI::aboutClicked() +{ + AboutDialog dlg; + dlg.setModel(clientModel); + dlg.exec(); +} + +void SpectreGUI::setNumConnections(int count) +{ + WebElement connectionIcon = WebElement(this, "connectionsIcon"); + WebElement connectionIconText = WebElement(this, "connectionsIconText"); + WebElement syncingIcon = WebElement(this, "syncingIcon"); + WebElement syncingIconText = WebElement(this, "syncingIconText"); + + if (count <= 0) + { + fConnectionInit = true; + syncingIcon.addClass("none"); + syncingIconText.addClass("none"); + } + else if (fConnectionInit) + { + fConnectionInit = false; + syncingIconText.addClass("none"); + syncingIconText.removeClass("syncing"); + syncingIcon.removeClass("syncing"); + syncingIcon.setAttribute("src", webviewResource("assets/svg/spinner.svg")); + syncingIcon.setAttribute("data-title", "Checking wallet state with network"); + syncingIcon.addClass("fa-spin"); + syncingIcon.removeClass("none"); + } + + connectionIconText.setContent(QString::number(count)); + if (count <= 0) + { + connectionIconText.addClass("none"); + connectionIcon.setAttribute("src", webviewResource("assets/svg/connection-0.svg")); + connectionIcon.addClass("fa-spin"); + } + else { + connectionIcon.removeClass("fa-spin"); + connectionIcon.setAttribute("src", webviewResource("assets/svg/connection-" + (count < 12 ? QString::number(count) : "12") + ".svg")); + connectionIconText.removeClass("none"); + } + + QString dataTitle = tr("%n active connection(s) to Alias network", "", count); + connectionIcon.setAttribute("data-title", dataTitle); +} + +void SpectreGUI::setNumBlocks(int count, int nTotalBlocks) +{ + WebElement syncingIcon = WebElement(this, "syncingIcon"); + WebElement syncingIconText = WebElement(this, "syncingIconText"); + + // don't show / hide syncing icon and its text if we have no connection to the network + if (!clientModel || (clientModel->getNumConnections() == 0 && !clientModel->isImporting())) + { + syncingIcon.addClass("none"); + syncingIconText.addClass("none"); + return; + } + + fConnectionInit = false; + + // -- translation (tr()) makes it difficult to neatly pick block/header + static QString sBlockType = nNodeMode == NT_FULL ? tr("block") : tr("header"); + static QString sBlockTypeMulti = nNodeMode == NT_FULL ? tr("blocks") : tr("headers"); + + QString strStatusBarWarnings = clientModel->getStatusBarWarnings(); + QString tooltip; + + float nPercentageDone = -1; + if (nNodeMode != NT_FULL + && nNodeState == NS_GET_FILTERED_BLOCKS) + { + tooltip = tr("Synchronizing with network..."); + + "
" + + tr("Downloading filtered blocks..."); + + int nRemainingBlocks = nTotalBlocks - pwalletMain->nLastFilteredHeight; + nPercentageDone = pwalletMain->nLastFilteredHeight / (nTotalBlocks * 0.01f); + + tooltip += "
" + + tr("~%1 filtered block(s) remaining (%2% done).").arg(nRemainingBlocks).arg(nPercentageDone); + + count = pwalletMain->nLastFilteredHeight; + } else + if (count < nTotalBlocks) + { + int nRemainingBlocks = nTotalBlocks - count; + nPercentageDone = count / (nTotalBlocks * 0.01f); + + if (strStatusBarWarnings.isEmpty()) + { + bridge->networkAlert(""); + tooltip = clientModel->isImporting() ? tr("Importing blocks...") : tr("Synchronizing with network..."); + + if (nNodeMode == NT_FULL) + { + tooltip += "
" + + tr("~%n block(s) remaining", "", nRemainingBlocks); + } else + { + char temp[128]; + snprintf(temp, sizeof(temp), "~%%n %s remaining", nRemainingBlocks == 1 ? qPrintable(sBlockType) : qPrintable(sBlockTypeMulti)); + + tooltip += "
" + + tr(temp, "", nRemainingBlocks); + + }; + } + + tooltip += (tooltip.isEmpty()? "" : "
") + + (clientModel->isImporting() + ? tr("Imported %1 of %2 %3 of transaction history (%4% done).").arg(count).arg(nTotalBlocks).arg(sBlockTypeMulti).arg(nPercentageDone, 0, 'f', 3) + : tr("Downloaded %1 of %2 %3 of transaction history (%4% done).").arg(count).arg(nTotalBlocks).arg(sBlockTypeMulti).arg(nPercentageDone, 0, 'f', 3)); + } else + { + tooltip = clientModel->isImporting() ? tr("Imported %n block(s) of transaction history.", "", count) : tr("Downloaded %n block(s) of transaction history.", "", count); + } + + // Override progressBarLabel text when we have warnings to display + if (!strStatusBarWarnings.isEmpty()) + bridge->networkAlert(strStatusBarWarnings); + + QDateTime lastBlockDate = clientModel->getLastBlockDate(); + int secs = lastBlockDate.secsTo(QDateTime::currentDateTime().addSecs(GetTimeOffset())); + QString text; + + // Represent time from last generated block in human readable text + if (secs <= 0) + { + // Fully up to date. Leave text empty. + } else + if (secs < 60) + { + text = tr("%n second(s) ago","",secs); + } else + if (secs < 60*60) + { + text = tr("%n minute(s) ago","",secs/60); + } else + if (secs < 24*60*60) + { + text = tr("%n hour(s) ago","",secs/(60*60)); + } else + { + text = tr("%n day(s) ago","",secs/(60*60*24)); + } + + // Set icon state: spinning if catching up, tick otherwise + if (secs < 30*60 && count >= nTotalBlocks + && nNodeState != NS_GET_FILTERED_BLOCKS) + { + tooltip = tr("Up to date") + "
" + tooltip; + + syncingIconText.addClass("none"); + syncingIconText.removeClass("syncing"); + syncingIcon.removeClass("fa-spin"); + syncingIcon.setAttribute("src", webviewResource("assets/svg/synced.svg")); + syncingIcon.removeClass("syncing"); + + //a js script to change the style property display to none for all outofsync elements + QString javascript = "var divsToHide = document.getElementsByClassName('outofsync');"; + javascript+= "for(var i = 0; i < divsToHide.length; i++) {"; + javascript+= " divsToHide[i].style.display = 'none';"; + javascript+= "}"; + + runJavaScript(javascript); + } else + { + tooltip = tr("Catching up...") + "
" + tooltip; + + if (nPercentageDone >= 0) + { + QString svgPercent = nPercentageDone < 2.5 ? "2.5" : nPercentageDone > 95 ? "95" : QString::number(nPercentageDone); + QString svgData = "data:image/svg+xml;utf8," + "" + " " + " " + " " + ""; + syncingIcon.setAttribute("src", svgData); + syncingIcon.addClass("fa-spin"); + syncingIcon.addClass("syncing"); + syncingIconText.addClass("syncing"); + syncingIconText.setContent(QString::number(nPercentageDone > 99 ? 99 : + nPercentageDone >= 10 ? std::floor(nPercentageDone) : + std::floor(nPercentageDone * 10) / 10 + ,'f', nPercentageDone < 10 ? 1 : 0) + QString("%")); + syncingIconText.removeClass("none"); + } + else { + syncingIconText.addClass("none"); + syncingIconText.removeClass("syncing"); + syncingIcon.removeClass("syncing"); + syncingIcon.setAttribute("src", webviewResource("assets/svg/spinner.svg")); + syncingIcon.addClass("fa-spin"); + } + + //a js script to change the style property display to inline for all outofsync elements + QString javascript = "var divsToHide = document.getElementsByClassName('outofsync');"; + javascript+= "for(var i = 0; i < divsToHide.length; i++) {"; + javascript+= " divsToHide[i].style.display = 'inline';"; + javascript+= "}"; + + runJavaScript(javascript); + } + + if (!text.isEmpty()) + { + tooltip += "
"; + tooltip += tr("Last received %1 was generated %2.").arg(sBlockType).arg(text); + }; + syncingIcon.setAttribute("data-title", tooltip); + syncingIcon.removeClass("none"); +} + +void SpectreGUI::error(const QString &title, const QString &message, bool modal) +{ + // Report errors from network/worker thread + if(modal) + { + QMessageBox::critical(this, title, message, QMessageBox::Ok, QMessageBox::Ok); + } else + { + notificator->notify(Notificator::Critical, title, message); + } +} + +void SpectreGUI::changeEvent(QEvent *e) +{ + QMainWindow::changeEvent(e); +#ifndef Q_OS_MACOS // Ignored on Mac + if(e->type() == QEvent::WindowStateChange) + { + if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray()) + { + QWindowStateChangeEvent *wsevt = static_cast(e); + if(!(wsevt->oldState() & Qt::WindowMinimized) && isMinimized()) + { + QTimer::singleShot(0, this, SLOT(hide())); + e->ignore(); + } + } + } +#endif +} + +void SpectreGUI::closeEvent(QCloseEvent *event) +{ + if(clientModel) + { +#ifndef Q_OS_MACOS // Ignored on Mac + if(!clientModel->getOptionsModel()->getMinimizeToTray() && + !clientModel->getOptionsModel()->getMinimizeOnClose()) + { + qApp->quit(); + } +#endif + } + QMainWindow::closeEvent(event); +} + +void SpectreGUI::askFee(qint64 nFeeRequired, bool *payFee) +{ + QString strMessage = + tr("To process this transaction, a fee of %1 will be charged to support the network. " + "Do you want to submit the transaction?").arg( + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, nFeeRequired)); + QMessageBox::StandardButton retval = QMessageBox::question( + this, tr("Confirm transaction fee"), strMessage, + QMessageBox::Yes|QMessageBox::Cancel, QMessageBox::Yes); + *payFee = (retval == QMessageBox::Yes); +} + +void SpectreGUI::incomingTransaction(const QModelIndex & parent, int start, int end) +{ + qDebug() << "SpectreGUI::incomingTransaction"; + if(!walletModel || !clientModel || clientModel->inInitialBlockDownload() || (nNodeMode != NT_FULL && nNodeState != NS_READY)) + return; + + TransactionTableModel *ttm = walletModel->getTransactionTableModel(); + + QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString(); + + // Ignore staking transactions... We should create an Option, and allow people to select/deselect what + // type of transactions they want to see + if(!(clientModel->getOptionsModel()->getNotifications().first() == "*") + && ! clientModel->getOptionsModel()->getNotifications().contains(type)) + return; + + // On new transaction, make an info balloon + // Unless the initial block download is in progress, to prevent balloon-spam + QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString(); + QString narration = ttm->index(start, TransactionTableModel::Narration, parent).data().toString(); + QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString(); + qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong(); + QIcon icon = qvariant_cast(ttm->index(start, TransactionTableModel::ToAddress, parent).data(Qt::DecorationRole)); + + notificator->notify(Notificator::Information, + tr("%1 %2") + .arg(BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), amount, true)) + .arg(type), + narration.size() > 0 ? tr("Address: %1\n" "Note: %2\n").arg(address).arg(narration) : + tr("Address: %1\n").arg(address), + icon); +} + +void SpectreGUI::optionsClicked() +{ + bridge->triggerElement("#navitems a[href=#options]", "click"); + showNormalIfMinimized(); +} + +void SpectreGUI::dragEnterEvent(QDragEnterEvent *event) +{ + // Accept only URIs + if(event->mimeData()->hasUrls()) + event->acceptProposedAction(); +} + +void SpectreGUI::dragMoveEvent(QDragMoveEvent *event) +{ + event->accept(); +} + +void SpectreGUI::dropEvent(QDropEvent *event) +{ + if(event->mimeData()->hasUrls()) + { + int nValidUrisFound = 0; + QList uris = event->mimeData()->urls(); + for (const QUrl &uri : uris) + { + handleURI(uri.toString()); + nValidUrisFound++; + } + + // if valid URIs were found + if (nValidUrisFound) + bridge->triggerElement("#navitems a[href=#send]", "click"); + else + notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Alias address or malformed URI parameters.")); + } + + event->acceptProposedAction(); +} + +void SpectreGUI::handleURI(QString strURI) +{ + SendCoinsRecipient rv; + + // URI has to be valid + if(GUIUtil::parseBitcoinURI(strURI, &rv)) + { + CBitcoinAddress address(rv.address.toStdString()); + if (!address.IsValid() && !IsStealthAddress(rv.address.toStdString())) + return; + + bridge->emitReceipient(rv.address, rv.label, rv.narration, rv.amount); + + showNormalIfMinimized(); + } + else + notificator->notify(Notificator::Warning, tr("URI handling"), tr("URI can not be parsed! This can be caused by an invalid Alias address or malformed URI parameters.")); +} + +void SpectreGUI::setEncryptionStatus(int status) +{ + WebElement encryptionIcon = WebElement(this, "encryptionIcon"); + WebElement encryptButton = WebElement(this, "encryptWallet"); + WebElement encryptMenuItem = WebElement(this, "encryptWallet", WebElement::SelectorType::CLASS); + WebElement changePassphrase = WebElement(this, "changePassphrase"); + WebElement toggleLock = WebElement(this, "toggleLock"); + WebElement toggleLockIcon = WebElement(this, "toggleLockIcon"); + switch(status) + { + case WalletModel::Unencrypted: + encryptionIcon.addClass("none"); + changePassphrase.addClass("none"); + toggleLock.addClass("none"); + encryptMenuItem.removeClass("none"); + encryptWalletAction->setChecked(false); + changePassphraseAction->setEnabled(false); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(false); + encryptWalletAction->setEnabled(true); + break; + case WalletModel::Unlocked: + encryptMenuItem .addClass("none"); + encryptionIcon.removeClass("none"); + encryptionIcon.removeClass("encryption"); + encryptMenuItem .addClass("none"); + toggleLockIcon.removeClass("fa-unlock"); + toggleLockIcon.removeClass("fa-unlock-alt"); + toggleLockIcon. addClass("fa-lock"); + + if (fWalletUnlockStakingOnly) + { + encryptionIcon.setAttribute("data-title", tr("Wallet is encrypted and currently unlocked for staking only")); + encryptionIcon. removeClass("no-encryption"); + encryptionIcon. addClass("encryption-stake"); + } else + { + encryptionIcon.setAttribute("data-title", tr("Wallet is encrypted and currently unlocked")); + encryptionIcon. removeClass("encryption-stake"); + encryptionIcon. addClass("no-encryption"); + }; + + encryptButton.addClass("none"); + changePassphrase.removeClass("none"); + toggleLock.removeClass("none"); + encryptWalletAction->setChecked(true); + changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(false); + lockWalletAction->setVisible(true); + encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + break; + case WalletModel::Locked: + encryptionIcon.removeClass("none"); + encryptionIcon.removeClass("no-encryption"); + encryptionIcon.removeClass("encryption-stake"); + encryptionIcon. addClass("encryption"); + toggleLockIcon.removeClass("fa-lock"); + toggleLockIcon. addClass("fa-unlock-alt"); + encryptionIcon .setAttribute("data-title", tr("Wallet is encrypted and currently locked")); + + encryptButton .addClass("none"); + encryptMenuItem .addClass("none"); + changePassphrase.removeClass("none"); + encryptWalletAction->setChecked(true); + changePassphraseAction->setEnabled(true); + unlockWalletAction->setVisible(true); + lockWalletAction->setVisible(false); + encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + break; + } +} + +void SpectreGUI::encryptWallet(bool status) +{ + if(!walletModel) + return; + AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt: + AskPassphraseDialog::Decrypt, this); + dlg.setModel(walletModel); + dlg.exec(); + + setEncryptionStatus(walletModel->getEncryptionStatus()); +} + +void SpectreGUI::backupWallet() +{ + if (QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).count() == 0) { + qFatal("QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).count() == 0"); + } + QString saveDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).at(0); + QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)")); + if(!filename.isEmpty()) + { + if(!walletModel->backupWallet(filename)) + { + QMessageBox::warning(this, tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location.")); + } + } +} + +void SpectreGUI::changePassphrase() +{ + AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this); + dlg.setModel(walletModel); + dlg.exec(); +} + +void SpectreGUI::unlockWallet(WalletModel::UnlockMode unlockMode) +{ + if(!walletModel) + return; + + AskPassphraseDialog::Mode mode; + if (unlockMode == WalletModel::UnlockMode::rescan) { + mode = AskPassphraseDialog::UnlockRescan; + } + else if (unlockMode == WalletModel::UnlockMode::login) { + mode = AskPassphraseDialog::UnlockLogin; + } + else { + mode = sender() == unlockWalletAction ? + AskPassphraseDialog::UnlockStaking : AskPassphraseDialog::Unlock; + } + + // Unlock wallet when requested by wallet model + if(walletModel->getEncryptionStatus() == WalletModel::Locked) + { + AskPassphraseDialog dlg(mode, this); + dlg.setModel(walletModel); + dlg.exec(); + } +} + +void SpectreGUI::lockWallet() +{ + if(!walletModel) + return; + + walletModel->setWalletLocked(true); +} + +void SpectreGUI::toggleLock() +{ + if(!walletModel) + return; + WalletModel::EncryptionStatus status = walletModel->getEncryptionStatus(); + + switch(status) + { + case WalletModel::Locked: unlockWalletAction->trigger(); break; + case WalletModel::Unlocked: lockWalletAction->trigger(); break; + default: // unencrypted wallet + QMessageBox::warning(this, tr("Lock Wallet"), + tr("Error: Wallet must first be encrypted to be locked."), + QMessageBox::Ok, QMessageBox::Ok); + break; + }; +} + +void SpectreGUI::showNormalIfMinimized(bool fToggleHidden) +{ + // activateWindow() (sometimes) helps with keyboard focus on Windows + if (isHidden()) + { + show(); + activateWindow(); + } + else if (isMinimized()) + { + showNormal(); + activateWindow(); + } + else if (GUIUtil::isObscured(this)) + { + raise(); + activateWindow(); + } + else if(fToggleHidden) + hide(); +} + +void SpectreGUI::toggleHidden() +{ + showNormalIfMinimized(true); +} + +void SpectreGUI::updateWeight() +{ + if (!pwalletMain) + return; + + TRY_LOCK(cs_main, lockMain); + if (!lockMain) + return; + + TRY_LOCK(pwalletMain->cs_wallet, lockWallet); + if (!lockWallet) + return; + + nWeight = pwalletMain->GetStakeWeight() + pwalletMain->GetSpectreStakeWeight(); +} + +void SpectreGUI::updateStakingIcon() +{ + WebElement stakingIcon = WebElement(this, "stakingIcon"); + uint64_t nNetworkWeight = 0, nNetworkWeightRecent; + + if(fIsStaking) + { + updateWeight(); + nNetworkWeight = GetPoSKernelPS(); + nNetworkWeightRecent = GetPoSKernelPSRecent(); + } else + nWeight = 0; + + if (fIsStaking && nWeight) + { + uint64_t nWeight = this->nWeight; + + unsigned nEstimateTime = GetTargetSpacing(nBestHeight, GetAdjustedTime()) * nNetworkWeight / nWeight; + QString text, textDebug; + + text = (nEstimateTime < 60) ? tr("%1 second(s)").arg(nEstimateTime) : \ + (nEstimateTime < 60 * 60) ? tr("%1 minute(s), %2 second(s)").arg(nEstimateTime / 60).arg(nEstimateTime % 60) : \ + (nEstimateTime < 24 * 60 * 60) ? tr("%1 hour(s), %2 minute(s)").arg(nEstimateTime / (60 * 60)).arg((nEstimateTime % (60 * 60)) / 60) : \ + tr("%1 day(s), %2 hour(s)").arg(nEstimateTime / (60 * 60 * 24)).arg((nEstimateTime % (60 * 60 * 24)) / (60 * 60)); + + stakingIcon.removeClass("not-staking"); + stakingIcon. addClass("staking"); + + nWeight /= COIN; + nNetworkWeight /= COIN; + nNetworkWeightRecent /= COIN; + + if (fDebug) + textDebug = tr(" (last 72 blocks %1)").arg(nNetworkWeightRecent); + + stakingIcon.setAttribute("data-title", tr("Staking.
Your weight is %1
Network weight is %2%3
Average time between rewards is %4").arg(nWeight).arg(nNetworkWeight).arg(textDebug).arg(text)); + } else + { + stakingIcon.addClass("not-staking"); + stakingIcon.removeClass("staking"); + + stakingIcon.setAttribute("data-title", (nNodeMode == NT_THIN) ? tr("Not staking because wallet is in thin mode") : \ + (!fIsStakingEnabled) ? tr("Not staking, staking is disabled") : \ + (pwalletMain && pwalletMain->IsLocked()) ? tr("Not staking because wallet is locked") : \ + (vNodes.empty()) ? tr("Not staking because wallet is offline") : \ + (clientModel->inInitialBlockDownload()) ? tr("Not staking because wallet is syncing") : \ + (!fIsStaking) ? tr("Initializing staking...") : \ + (!nWeight) ? tr("Not staking because you don't have mature coins") : \ + tr("Not staking")); + } +} + +void SpectreGUI::requestShutdown() +{ + StartShutdown(); +} + +void SpectreGUI::detectShutdown() +{ + if (ShutdownRequested()) + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); +} diff --git a/src/qt/spectregui.h b/src/qt/spectregui.h new file mode 100644 index 0000000000..f8995d2c03 --- /dev/null +++ b/src/qt/spectregui.h @@ -0,0 +1,148 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef SPECTREGUI_H +#define SPECTREGUI_H + +#include +#include +#include +#include +#include +#include +#include + +#include "spectrebridge.h" +#include "walletmodel.h" +#include "askpassphrasedialog.h" +#include "rpcconsole.h" + +#include + +class TransactionTableModel; +class ClientModel; +class WalletModel; +class MessageModel; +class Notificator; + +QT_BEGIN_NAMESPACE +class QLabel; +class QMenuBar; +class QToolBar; +class QUrl; +QT_END_NAMESPACE + +static const int WEBSOCKETPORT = 52471; +static const int WEBSOCKETPORT_TESTNET = 52472; + +class SpectreGUI : public QMainWindow +{ + Q_OBJECT + +public: + explicit SpectreGUI(QWebChannel *webChannel, QWidget *parent = nullptr); + ~SpectreGUI(); + + void setClientModel(ClientModel *clientModel); + void setWalletModel(WalletModel *walletModel); + void setMessageModel(MessageModel *messageModel); + void setSplashScreen(QSplashScreen* splash); + void loadIndex(QString webSocketToken); + void runJavaScript(QString javascriptCode); + +protected: + void changeEvent(QEvent *e) override; + void closeEvent(QCloseEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private: + SpectreBridge *bridge{nullptr}; + QWebChannel *webChannel{nullptr}; + QObject *qmlWebView{nullptr}; + bool uiReady{false}; + + ClientModel *clientModel{nullptr}; + WalletModel *walletModel{nullptr}; + MessageModel *messageModel{nullptr}; + + QMenuBar *appMenuBar{nullptr}; + QSplashScreen *splashScreen{nullptr}; + + QAction *quitAction{nullptr}; + QAction *aboutAction{nullptr}; + QAction *optionsAction{nullptr}; + QAction *toggleHideAction{nullptr}; + QAction *exportAction{nullptr}; + QAction *encryptWalletAction{nullptr}; + QAction *backupWalletAction{nullptr}; + QAction *changePassphraseAction{nullptr}; + QAction *unlockWalletAction{nullptr}; + QAction *lockWalletAction{nullptr}; + QAction *aboutQtAction{nullptr}; + QAction *openRPCConsoleAction{nullptr}; + + QSystemTrayIcon *trayIcon{nullptr}; + Notificator *notificator{nullptr}; + RPCConsole *rpcConsole{nullptr}; + QTimer *pollTimer{nullptr}; + + uint64_t nWeight{0}; + bool fConnectionInit{true}; + + void createActions(); + void createMenuBar(); + void createTrayIcon(); + void pageLoaded(bool ok); + bool initialized{false}; + + friend class SpectreBridge; + + class WebElement { + public: + enum SelectorType {ID, CLASS}; + WebElement(SpectreGUI* spectreGUI, QString name, SelectorType type = SelectorType::ID); + void setAttribute(QString attribute, QString value); + void removeAttribute(QString attribute); + void addClass(QString className); + void removeClass(QString className); + void setContent(QString value); + private: + SpectreGUI* spectreGUI; + QString name; + QString getElementJS; + }; + +private Q_SLOTS: + void addJavascriptObjects(const QString &id, QObject *object); + void urlClicked(const QUrl & link); + void setNumConnections(int count); + void setNumBlocks(int count, int nTotalBlocks); + void setEncryptionStatus(int status); + void error(const QString &title, const QString &message, bool modal); + void askFee(qint64 nFeeRequired, bool *payFee); + void handleURI(QString strURI); + void trayIconActivated(QSystemTrayIcon::ActivationReason reason); + void incomingTransaction(const QModelIndex & parent, int start, int end); + void optionsClicked(); + void aboutClicked(); + void unlockWallet(WalletModel::UnlockMode unlockMode = WalletModel::UnlockMode::standard); + void lockWallet(); + void toggleLock(); + void encryptWallet(bool status); + void backupWallet(); + void changePassphrase(); + void showNormalIfMinimized(bool fToggleHidden = false); + void toggleHidden(); + void updateWeight(); + void updateStakingIcon(); + void detectShutdown(); + void requestShutdown(); +}; + +#endif diff --git a/src/qt/test/CMakeLists.txt b/src/qt/test/CMakeLists.txt new file mode 100644 index 0000000000..595b279151 --- /dev/null +++ b/src/qt/test/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(Spectre + PUBLIC + "${CMAKE_CURRENT_LIST_DIR}/uritests.h" + PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/uritests.cpp" + ) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index af2d358fc4..b11864bac6 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -1,16 +1,32 @@ -#include -#include - -#include "uritests.h" - -// This is all you need to run all the tests -int main(int argc, char *argv[]) -{ - bool fInvalid = false; - - URITests test1; - if (QTest::qExec(&test1) != 0) - fInvalid = true; - - return fInvalid; -} +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#include +#include + +#define BOOST_TEST_MODULE Spectre_tests +#include + +#include "uritests.h" + +#ifdef SPECTRE_QT_TEST +// This is all you need to run all the tests +int RunQtTests() +{ + bool fInvalid = false; + + URITests test1; + if (QTest::qExec(&test1) != 0) + fInvalid = true; + + return fInvalid; +} + +BOOST_AUTO_TEST_CASE(universeInOrder) { + BOOST_CHECK(RunQtTests() == false); +} +#endif diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 4662f5ed31..cdeead7490 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include "uritests.h" #include "../guiutil.h" #include "../walletmodel.h" @@ -17,55 +24,55 @@ void URITests::uriTests() { SendCoinsRecipient rv; QUrl uri; - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist=")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist=")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist=")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist=")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); QVERIFY(rv.amount == 0); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString("Wikipedia Example Address")); QVERIFY(rv.amount == 0); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); QVERIFY(rv.amount == 100000); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); QVERIFY(rv.amount == 100100000); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.amount == 10000000000LL); QVERIFY(rv.label == QString("Wikipedia Example")); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); - QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv)); + QVERIFY(GUIUtil::parseBitcoinURI("alias://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv)); QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W")); QVERIFY(rv.label == QString()); // We currently don't implement the message parameter (ok, yea, we break spec...) - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); - uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example")); + uri.setUrl(QString("alias:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); } diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h index 1237516e5f..10b23fc164 100644 --- a/src/qt/test/uritests.h +++ b/src/qt/test/uritests.h @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef URITESTS_H #define URITESTS_H diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 74565bb6d0..07735a245d 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "trafficgraphwidget.h" #include "clientmodel.h" @@ -28,7 +31,7 @@ TrafficGraphWidget::TrafficGraphWidget(QWidget *parent) : clientModel(0) { timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(updateRates())); + connect(timer, &QTimer::timeout, this, &TrafficGraphWidget::updateRates); } void TrafficGraphWidget::setClientModel(ClientModel *model) diff --git a/src/qt/trafficgraphwidget.h b/src/qt/trafficgraphwidget.h index efab6e7fc5..e9728a75a8 100644 --- a/src/qt/trafficgraphwidget.h +++ b/src/qt/trafficgraphwidget.h @@ -1,12 +1,16 @@ -// Copyright (c) 2011-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef TRAFFICGRAPHWIDGET_H #define TRAFFICGRAPHWIDGET_H #include #include +#include class ClientModel; @@ -20,14 +24,14 @@ class TrafficGraphWidget : public QWidget Q_OBJECT public: - explicit TrafficGraphWidget(QWidget *parent = 0); + explicit TrafficGraphWidget(QWidget *parent = nullptr); void setClientModel(ClientModel *model); int getGraphRangeMins() const; protected: - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; -public slots: +public Q_SLOTS: void updateRates(); void setGraphRangeMins(int mins); void clear(); @@ -35,14 +39,14 @@ public slots: private: void paintPath(QPainterPath &path, QQueue &samples); - QTimer *timer; - float fMax; - int nMins; + QTimer *timer{nullptr}; + float fMax{0.0f}; + int nMins{0}; QQueue vSamplesIn; QQueue vSamplesOut; - quint64 nLastBytesIn; - quint64 nLastBytesOut; - ClientModel *clientModel; + quint64 nLastBytesIn{0}; + quint64 nLastBytesOut{0}; + ClientModel *clientModel{nullptr}; }; #endif // TRAFFICGRAPHWIDGET_H diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 0d6d1fec01..1b276e7da7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include "transactiondesc.h" #include "guiutil.h" @@ -6,8 +13,29 @@ #include "main.h" #include "wallet.h" #include "txdb.h" -#include "ui_interface.h" +#include "interface.h" #include "base58.h" +#include "chainparams_migration.h" + +void toHTML(CWallet *wallet, CWalletTx &wtx, QString& strHTML, const bool& debit, const CTxDestination& destination, const std::vector& destSubs, const int64_t& amount, const Currency& currency, const std::string& narration, bool& narrationHandled); +void toHTML(CWallet *wallet, CWalletTx &wtx, QString& strHTML, const Currency& sCurrency, const CTxDestination& destination, const std::vector& destSubs, const int64_t& amount, const Currency& currency, const std::string& narration, bool& narrationHandled); +void toHTML(CWallet *wallet, QString& strHTML, const CTxDestination& destination, const std::vector& destSubs, const std::string& narration, bool& narrationHandled); +void toHTML(CWallet *wallet, QString& strHTML, const std::vector& destSubs); + +static QString explorer; + +bool addressLink(CWallet *wallet, const CTxDestination& destination, QString& strHTML) +{ + CBitcoinAddress address(destination); + if (!address.IsValid()) + return false; + + strHTML += "" + + ((wallet->mapAddressBook.count(destination) && !wallet->mapAddressBook[destination].empty()) ? + GUIUtil::HtmlEscape(wallet->mapAddressBook[destination]) : GUIUtil::HtmlEscape(address.ToString())) + + ""; + return true; +} QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) { @@ -34,18 +62,28 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) { + if (explorer.isEmpty()) + explorer = fTestNet ? "https://chainz.cryptoid.info/alias-test/" : "https://chainz.cryptoid.info/alias/"; + QString strHTML; - QString explorer(fTestNet ? "http://testnet.shadowchain.info/" : "http://explorer.shadow.cash/"); LOCK2(cs_main, wallet->cs_wallet); strHTML.reserve(4000); - strHTML += ""; + strHTML += ""; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; + QString txid(wtx.GetHash().ToString().c_str()); + strHTML += "" + tr("Transaction ID") + ": " + txid + "
"; + if (wtx.hashBlock != 0) + { + QString blockHash = QString::fromStdString(wtx.hashBlock.GetHex()); + strHTML += "" + tr("Block Hash") + ": " + blockHash + "
"; + } + strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); int nRequests = wtx.GetRequestCount(); if (nRequests != -1) @@ -60,177 +98,82 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += "" + tr("Date") + ": " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "
"; + bool narrationHandled = false; + // - // From + // CoinBase/CoinStake // if (wtx.IsCoinBase() || wtx.IsCoinStake()) { strHTML += "" + tr("Source") + ": " + tr("Generated") + "
"; - } else - if (wtx.mapValue.count("from") && !wtx.mapValue["from"].empty()) - { - // Online transaction - strHTML += "" + tr("From") + ": " + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "
"; - } else - { - // Offline transaction - if (nNet > 0) + if (nCredit == 0) { - // Credit - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + int64_t nUnmatured = 0; + for (const CTxOut& txout : wtx.vout) + nUnmatured += txout.IsAnonOutput() ? wallet->GetSpectreCredit(txout) : wallet->GetCredit(txout); + strHTML += "" + tr("Credit") + ": "; + if (wtx.IsInMainChain()) { - if (wtx.nVersion == ANON_TXN_VERSION - && txout.IsAnonOutput()) - { - const CScript &s = txout.scriptPubKey; - CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); - std::string sAnonPrefix("ao "); - if (wallet->HaveKey(ckidD) && (wallet->mapAddressBook[ckidD].empty() || !wallet->mapAddressBook[ckidD].compare(0, sAnonPrefix.length(), sAnonPrefix) == 0)) - { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(ckidD).ToString()); - if (!wallet->mapAddressBook[ckidD].empty()) - strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[ckidD]) + ")"; - else - strHTML += " (" + tr("own address") + ")"; - strHTML += "
"; - }; - continue; - } + strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, nUnmatured); + strHTML += wtx.IsAnonCoinStake() ? " (private)" : " (public)"; + strHTML += " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; + } + else + strHTML += "(" + tr("not accepted") + ")"; + strHTML += "
"; + } + } - if (wallet->IsMine(txout)) - { - CTxDestination address; - if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*wallet, address)) - { - if (wallet->mapAddressBook.count(address)) - { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); - if (!wallet->mapAddressBook[address].empty()) - strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; - else - strHTML += " (" + tr("own address") + ")"; - strHTML += "
"; - }; - }; - break; - }; - }; - }; - }; + int64_t allFee; + std::string strSentAccount; + std::list listReceived; + std::list listSent; - // - // To - // - if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty()) - { - // Online transaction - std::string strAddress = wtx.mapValue["to"]; - strHTML += "" + tr("To") + ": "; - CTxDestination dest = CBitcoinAddress(strAddress).Get(); - if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) - strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; - strHTML += GUIUtil::HtmlEscape(strAddress) + "
"; - }; + wtx.GetDestinationDetails(listReceived, listSent, allFee, strSentAccount); - // - // Amount - // - if (wtx.IsCoinBase() && nCredit == 0) - { - // - // Coinbase - // - int64_t nUnmatured = 0; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout); - strHTML += "" + tr("Credit") + ": "; - if (wtx.IsInMainChain()) - strHTML += BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; - else - strHTML += "(" + tr("not accepted") + ")"; - strHTML += "
"; - } else - if (nNet > 0) - { - // - // Credit - // - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, nNet) + "
"; - } else - { - bool fAllFromMe = true; - BOOST_FOREACH(const CTxIn& txin, wtx.vin) - fAllFromMe = fAllFromMe && wallet->IsMine(txin); + if (listSent.size() > 0 && allFee > 0) { + const auto & destination = listSent.front(); + strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnitCurrency(BitcoinUnits::ALIAS, -allFee, destination.currency) + "
"; + } + + Currency netCurrency = PUBLIC; + if (listSent.size() > 0) + netCurrency = listSent.front().currency; + else if (listReceived.size() > 0) + netCurrency = listReceived.front().currency; - bool fAllToMe = true; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) - fAllToMe = fAllToMe && wallet->IsMine(txout); + if (wtx.GetBlocksToMaturity() == 0) + { + strHTML += "" + tr("Net amount") + ": " + BitcoinUnits::formatWithUnitCurrency(BitcoinUnits::ALIAS, nNet, netCurrency, true) + "
"; + } - if (fAllFromMe) + if (!(wtx.IsCoinBase() || wtx.IsCoinStake()) && listReceived.size() > 0 && listSent.size() > 0) + { + // Transfer within account + const auto & destinationSent = listSent.front(); + for (const auto & destination: listReceived) { - // - // Debit - // - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + ::toHTML(wallet, wtx, strHTML, destinationSent.currency, destination.address, destination.vAddressElements, destination.amount, destination.currency, destination.narration, narrationHandled); + } + } + else { + for (const auto & destination : listReceived) + { + ::toHTML(wallet, wtx, strHTML, false, destination.address, destination.vAddressElements, destination.amount, destination.currency, destination.narration, narrationHandled); + } + for (const auto & destination : listSent) + { + if (wtx.IsCoinStake()) { - if (wallet->IsMine(txout)) + // only add contributions/donations + std::string strAddress = CBitcoinAddress(destination.address).ToString(); + if (strAddress != ChainParamsMigration::GetDevContributionAddress() && strAddress != ChainParamsMigration::GetSupplyIncreaseAddress()) continue; - - if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) - { - // Offline transaction - CTxDestination address; - if (ExtractDestination(txout.scriptPubKey, address)) - { - strHTML += "" + tr("To") + ": "; - if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) - strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); - strHTML += "
"; - }; - }; - - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, -txout.nValue) + "
"; - } - - if (fAllToMe) - { - // Payment to self - int64_t nChange = wtx.GetChange(); - int64_t nValue = nCredit - nChange; - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, -nValue) + "
"; - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, nValue) + "
"; } - - int64_t nTxFee = nDebit - wtx.GetValueOut(); - if (nTxFee > 0) - strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, -nTxFee) + "
"; - } else - { - // - // Mixed debit transaction - // - BOOST_FOREACH(const CTxIn& txin, wtx.vin) - { - - if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, -wallet->GetDebit(txin)) + "
"; - }; - - BOOST_FOREACH(const CTxOut& txout, wtx.vout) - if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, wallet->GetCredit(txout)) + "
"; + ::toHTML(wallet, wtx, strHTML, true, destination.address, destination.vAddressElements, destination.amount, destination.currency, destination.narration, narrationHandled); } } - strHTML += "" + tr("Net amount") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, nNet, true) + "
"; - // // Message // @@ -238,34 +181,34 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += "
" + tr("Message") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "
"; if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty()) strHTML += "
" + tr("Comment") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "
"; + if (wtx.mapValue.count("to") && !wtx.mapValue["to"].empty()) + strHTML += "
" + tr("Comment-To") + ":
" + GUIUtil::HtmlEscape(wtx.mapValue["to"], true) + "
"; - char cbuf[256]; - for (uint32_t k = 0; k < wtx.vout.size(); ++k) - { - snprintf(cbuf, sizeof(cbuf), "n_%d", k); - if (wtx.mapValue.count(cbuf) && !wtx.mapValue[cbuf].empty()) - strHTML += "
" + tr(cbuf) + ": " + GUIUtil::HtmlEscape(wtx.mapValue[cbuf], true) + "
"; + if (!narrationHandled) { + char cbuf[256]; + for (uint32_t k = 0; k < wtx.vout.size(); ++k) + { + snprintf(cbuf, sizeof(cbuf), "n_%d", k); + if (wtx.mapValue.count(cbuf) && !wtx.mapValue[cbuf].empty()) + strHTML += "
" + tr(cbuf) + ": " + GUIUtil::HtmlEscape(wtx.mapValue[cbuf], true) + "
"; + } } - QString txid(wtx.GetHash().ToString().c_str()); - - strHTML += "" + tr("Transaction ID") + ": " + txid + "
"; - if (wtx.IsCoinBase() || wtx.IsCoinStake()) - strHTML += "
" + tr("Generated coins must mature 120 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "
"; + strHTML += "
" + tr("Generated coins must mature 450 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.") + "
"; // // Debug view // if (fDebug) { - strHTML += "

" + tr("Debug information") + "

"; - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + strHTML += "
" + tr("Debug information") + "

"; + for (const CTxIn& txin : wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, -wallet->GetDebit(txin)) + "
"; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, -wallet->GetDebit(txin)) + "
"; + for (const CTxOut& txout : wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, wallet->GetCredit(txout)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); @@ -275,7 +218,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += "
" + tr("Inputs") + ":"; strHTML += "
    "; - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { COutPoint prevout = txin.prevout; @@ -310,13 +253,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) const CTxOut &vout = prev.vout[prevout.n]; CTxDestination address; if (ExtractDestination(vout.scriptPubKey, address)) - { - strHTML +=""; - if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) - strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; - strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()) + ""; - } - strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::SDC, vout.nValue); + addressLink(wallet, address, strHTML); + + strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, vout.nValue); strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + ""; } } @@ -328,3 +267,80 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx) strHTML += ""; return strHTML; } + +void toHTML(CWallet *wallet, CWalletTx &wtx, QString& strHTML, const bool& debit, const CTxDestination& destination, const std::vector& destSubs, const int64_t& amount, const Currency& currency, const std::string& narration, bool& narrationHandled) +{ + strHTML += "
    "; + strHTML += "
    " + TransactionDesc::tr(debit ? !wtx.IsCoinStake() ? "Debit" : wtx.GetDepthAndHeightInMainChain().second % 6 == 0 ? "Contributed" : "Donated" : + wtx.IsCoinBase() ? "Mined" : wtx.IsCoinStake() ? "Staked" : "Credit") + ":
    "; + strHTML += BitcoinUnits::formatWithUnitCurrency(BitcoinUnits::ALIAS, debit ? -amount : amount, currency) + "
    "; + strHTML += "
    " + TransactionDesc::tr(debit ? "Sent to": "With") + ":
    "; + + toHTML(wallet, strHTML, destination, currency == PUBLIC ? destSubs : std::vector(), narration, narrationHandled); + + strHTML += "
    "; +} + +void toHTML(CWallet *wallet, CWalletTx &wtx, QString& strHTML, const Currency& sCurrency, const CTxDestination& destination, const std::vector& destSubs, const int64_t& amount, const Currency& currency, const std::string& narration, bool& narrationHandled) +{ + strHTML += "
    "; + if (sCurrency == currency) { + strHTML += "
    " + TransactionDesc::tr(wtx.IsCoinBase() ? "Mined" : wtx.IsCoinStake() ? "Staked" : "Sent to self") + ":
    "; + strHTML += BitcoinUnits::formatWithUnitCurrency(BitcoinUnits::ALIAS, amount, currency) + "
    "; + } + else { + if (sCurrency == PUBLIC && currency == PRIVATE) + strHTML += "
    " + TransactionDesc::tr("Converted") + ":
    " + + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, amount) + TransactionDesc::tr(" from public to private") + "
    "; + else + strHTML += "
    " + TransactionDesc::tr("Converted") + ":
    " + + BitcoinUnits::formatWithUnit(BitcoinUnits::ALIAS, amount) + TransactionDesc::tr(" from private to public") + "
    "; + } + + strHTML += "
    " + TransactionDesc::tr("Address") + ":
    "; + + toHTML(wallet, strHTML, destination, currency == PUBLIC ? destSubs : std::vector(), narration, narrationHandled); + + strHTML += "
    "; +} + +void toHTML(CWallet *wallet, QString& strHTML, const CTxDestination& destination, const std::vector& destSubs, const std::string& narration, bool& narrationHandled) +{ + if (destination.type() == typeid(CStealthAddress)) { + CStealthAddress stealthAddress = boost::get(destination); + if (!stealthAddress.label.empty()) + strHTML += GUIUtil::HtmlEscape(stealthAddress.label) + "
    "; + strHTML += GUIUtil::HtmlEscape(stealthAddress.Encoded()) + "
    "; + toHTML(wallet, strHTML, destSubs); + + narrationHandled = true; + if (!narration.empty()) + strHTML += "
    " + TransactionDesc::tr("Note") + ":
    " + GUIUtil::HtmlEscape(narration) + "
    "; + } + else { + if (addressLink(wallet, destination, strHTML)) + { + strHTML += ""; + narrationHandled = true; + if (!narration.empty()) + strHTML += "
    " + TransactionDesc::tr("Note") + ":
    " + GUIUtil::HtmlEscape(narration) + "
    "; + } + else + strHTML += TransactionDesc::tr("unknown") + ""; + } +} + +void toHTML(CWallet *wallet, QString& strHTML, const std::vector& destSubs) +{ + for (const auto& destination : destSubs) { + QString strAddress; + if (addressLink(wallet, destination, strAddress)) + { + strHTML += "
    -
    "; + strHTML += TransactionDesc::tr("
    "); + strHTML += strAddress; + strHTML += "
    "; + } + } + +} diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h index 2523f9aa69..38a83b4a23 100644 --- a/src/qt/transactiondesc.h +++ b/src/qt/transactiondesc.h @@ -1,23 +1,30 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef TRANSACTIONDESC_H #define TRANSACTIONDESC_H #include #include + #include class CWallet; class CWalletTx; -/** Provide a human-readable extended HTML description of a transaction. - */ class TransactionDesc: public QObject { Q_OBJECT + public: static QString toHTML(CWallet *wallet, CWalletTx &wtx); + private: TransactionDesc() {} - static QString FormatTxStatus(const CWalletTx& wtx); }; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index e1bbfd8c06..cb2703aae6 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -1,9 +1,16 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include "transactionrecord.h" -#include "wallet.h" #include "base58.h" +#include "chainparams_migration.h" -#include "shadowgui.h" +#include "spectregui.h" /* Return positive answer if transaction should be shown in list. */ @@ -20,22 +27,38 @@ QString TransactionRecord::getTypeLabel(const int &type) switch(type) { case RecvWithAddress: - return ShadowGUI::tr("Received with"); + return SpectreGUI::tr("Public received with"); case RecvFromOther: - return ShadowGUI::tr("Received from"); + return SpectreGUI::tr("Public received from"); case SendToAddress: case SendToOther: - return ShadowGUI::tr("Sent to"); + return SpectreGUI::tr("Public sent to"); case SendToSelf: - return ShadowGUI::tr("Payment to yourself"); + return SpectreGUI::tr("Public sent to self"); + case SendToSelfSPECTRE: + return SpectreGUI::tr("Private sent to self"); case Generated: - return ShadowGUI::tr("Mined"); - case RecvShadow: - return ShadowGUI::tr("Received shadow"); - case SendShadow: - return ShadowGUI::tr("Sent shadow"); + return SpectreGUI::tr("Public staked"); + case GeneratedDonation: + return SpectreGUI::tr("Public donated"); + case GeneratedContribution: + return SpectreGUI::tr("Public contributed"); + case GeneratedSPECTRE: + return SpectreGUI::tr("Private staked"); + case GeneratedSPECTREDonation: + return SpectreGUI::tr("Private donated"); + case GeneratedSPECTREContribution: + return SpectreGUI::tr("Private contributed"); + case RecvSpectre: + return SpectreGUI::tr("Private received with"); + case SendSpectre: + return SpectreGUI::tr("Private sent to"); + case ConvertSPECTREtoXSPEC: + return SpectreGUI::tr("Private to Public"); + case ConvertXSPECtoSPECTRE: + return SpectreGUI::tr("Public to Private"); case Other: - return ShadowGUI::tr("Other"); + return SpectreGUI::tr("Other"); default: return ""; } @@ -46,17 +69,29 @@ QString TransactionRecord::getTypeShort(const int &type) switch(type) { case TransactionRecord::Generated: - return "mined"; + case TransactionRecord::GeneratedSPECTRE: + return "staked"; + case TransactionRecord::GeneratedDonation: + case TransactionRecord::GeneratedSPECTREDonation: + return "donated"; + case TransactionRecord::GeneratedContribution: + case TransactionRecord::GeneratedSPECTREContribution: + return "contributed"; case TransactionRecord::RecvWithAddress: case TransactionRecord::RecvFromOther: - case TransactionRecord::RecvShadow: + case TransactionRecord::RecvSpectre: return "input"; case TransactionRecord::SendToAddress: case TransactionRecord::SendToOther: - case TransactionRecord::SendShadow: + case TransactionRecord::SendSpectre: return "output"; + case TransactionRecord::SendToSelf: + case TransactionRecord::SendToSelfSPECTRE: + case TransactionRecord::ConvertXSPECtoSPECTRE: + case TransactionRecord::ConvertSPECTREtoXSPEC: + return "inout"; default: - return "inout"; + return "other"; } } @@ -68,62 +103,83 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); - int64_t nCredSDC, nCredShadow; - wtx.GetCredit(nCredSDC, nCredShadow, true); - int64_t nCredit = nCredSDC + nCredShadow; + int64_t nCredit = wtx.GetCredit(); int64_t nDebit = wtx.GetDebit(); int64_t nNet = nCredit - nDebit; - uint256 hash = wtx.GetHash(), hashPrev = 0; + uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; char cbuf[256]; if (wtx.nVersion == ANON_TXN_VERSION) { - if (nNet > 0 && nCredShadow > 0) - { - // -- credit - TransactionRecord sub(hash, nTime, TransactionRecord::RecvShadow, "", "", nNet, 0); + int64_t allFee; + std::string strSentAccount; + std::list listReceived; + std::list listSent; - for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) - { - // display 1st transaction - snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); - mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); - if (mi != wtx.mapValue.end() && !mi->second.empty()) - { - sub.narration = mi->second; - break; - }; - }; + wtx.GetDestinationDetails(listReceived, listSent, allFee, strSentAccount); - parts.append(sub); - return parts; - } else - if (nNet <= 0) + if (wtx.IsAnonCoinStake() && !listReceived.empty()) { - // -- debit - TransactionRecord sub(hash, nTime, TransactionRecord::SendShadow, "", "", nNet, 0); + const auto & destinationR = listReceived.front(); + int64_t stakingReward = allFee < 0 ? -allFee : destinationR.amount; + TransactionRecord sub = TransactionRecord(hash, nTime, TransactionRecord::GeneratedSPECTRE, + destinationR.address.type() == typeid(CStealthAddress) ? boost::get(destinationR.address).Encoded(): "", + destinationR.narration, 0, stakingReward, destinationR.currency, parts.size()); - for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) + for (const auto & destination: listSent) { - // display 1st transaction - snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); - mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); - if (mi != wtx.mapValue.end() && !mi->second.empty()) + std::string strAddress = CBitcoinAddress(destination.address).ToString(); + if (strAddress == ChainParamsMigration::GetDevContributionAddress() || strAddress == ChainParamsMigration::GetSupplyIncreaseAddress()) { - sub.narration = mi->second; - break; + sub.address = strAddress; + int blockHeight = wtx.GetDepthAndHeightInMainChain().second; + if (blockHeight < 0 || blockHeight % 6 == 0) + sub.type = TransactionRecord::GeneratedSPECTREContribution; + else + sub.type = TransactionRecord::GeneratedSPECTREDonation; + break; } - }; - + } parts.append(sub); - return parts; - }; - - // continue on - }; + } + else if (listReceived.size() > 0 && listSent.size() > 0) + { + // Transfer within account + TransactionRecord::Type trxType = TransactionRecord::SendToSelfSPECTRE; + const auto & destinationS = listSent.front(); + const auto & destinationR = listReceived.front(); + + if (destinationS.currency == PUBLIC && destinationR.currency == PRIVATE) + trxType = TransactionRecord::ConvertXSPECtoSPECTRE; + else if (destinationS.currency == PRIVATE && destinationR.currency == PUBLIC) + trxType = TransactionRecord::ConvertSPECTREtoXSPEC; + + for (const auto & destination : listReceived) + parts.append(TransactionRecord(hash, nTime, trxType, + destination.address.type() == typeid(CStealthAddress) ? boost::get(destination.address).Encoded(): "", + destination.narration, 0, destination.amount, destination.currency, parts.size()) + ); + } + else + { + for (const auto & destination: listSent) + parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendSpectre, + destination.address.type() == typeid(CStealthAddress) ? boost::get(destination.address).Encoded(): "", + destination.narration, parts.size() == 0 ? -(destination.amount + allFee): -destination.amount, // add trx fees to first trx record + 0, destination.currency, parts.size()) + ); + + for (const auto & destination : listReceived) + parts.append(TransactionRecord(hash, nTime, TransactionRecord::RecvSpectre, + destination.address.type() == typeid(CStealthAddress) ? boost::get(destination.address).Encoded(): "", + destination.narration, 0, destination.amount, destination.currency, parts.size()) + ); + } + return parts; + } if (nNet > 0 || wtx.IsCoinBase() || wtx.IsCoinStake()) { @@ -135,32 +191,6 @@ QList TransactionRecord::decomposeTransaction(const CWallet * { const CTxOut& txout = wtx.vout[nOut]; - if (wtx.nVersion == ANON_TXN_VERSION - && txout.IsAnonOutput()) - { - const CScript &s = txout.scriptPubKey; - CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); - - if (wallet->HaveKey(ckidD)) - { - TransactionRecord sub(hash, nTime); - sub.idx = parts.size(); // sequence number - - sub.credit = txout.nValue; - - sub.type = TransactionRecord::RecvShadow; - sub.address = CBitcoinAddress(ckidD).ToString(); - //sub.address = wallet->mapAddressBook[ckidD] - - snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); - mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); - if (mi != wtx.mapValue.end() && !mi->second.empty()) - sub.narration = mi->second; - - parts.append(sub); - }; - }; - if (wallet->IsMine(txout)) { TransactionRecord sub(hash, nTime); @@ -195,39 +225,42 @@ QList TransactionRecord::decomposeTransaction(const CWallet * if (wtx.IsCoinStake()) { // Generated (proof-of-stake) - - if (hashPrev == hash) - continue; // last coinstake output - sub.type = TransactionRecord::Generated; - sub.credit = nNet > 0 ? nNet : wtx.GetValueOut() - nDebit; - hashPrev = hash; - }; - + if (nDebit > 0) // handle foreign stakes + { + sub.credit = nNet > 0 ? nNet : fabs(wtx.GetValueOut() - nDebit); + + // check if stake was contributed + for (const auto & txout : wtx.vout) + { + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address)) + { + std::string strAddress = CBitcoinAddress(address).ToString(); + if (strAddress == ChainParamsMigration::GetDevContributionAddress() || strAddress == ChainParamsMigration::GetSupplyIncreaseAddress()) + { + sub.address = strAddress; + int blockHeight = wtx.GetDepthAndHeightInMainChain().second; + if (blockHeight < 0 || blockHeight % 6 == 0) + sub.type = TransactionRecord::GeneratedContribution; + else + sub.type = TransactionRecord::GeneratedDonation; + break; + } + } + } + } + parts.append(sub); + break; + } parts.append(sub); } } } else { bool fAllFromMe = true; - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { - if (wtx.nVersion == ANON_TXN_VERSION - && txin.IsAnonInput()) - { - std::vector vchImage; - txin.ExtractKeyImage(vchImage); - - CWalletDB walletdb(wallet->strWalletFile, "r"); - COwnedAnonOutput oao; - if (!walletdb.ReadOwnedAnonOutput(vchImage, oao)) - { - fAllFromMe = false; - break; // display as send/recv shadow - }; - continue; - }; - if (wallet->IsMine(txin)) continue; fAllFromMe = false; @@ -235,14 +268,8 @@ QList TransactionRecord::decomposeTransaction(const CWallet * }; bool fAllToMe = true; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) { - if (wtx.nVersion == ANON_TXN_VERSION - && txout.IsAnonOutput()) - { - fAllToMe = false; - break; // display as send/recv shadow - } opcodetype firstOpCode; CScript::const_iterator pc = txout.scriptPubKey.begin(); if (txout.scriptPubKey.GetOp(pc, firstOpCode) @@ -271,7 +298,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * }; parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", narration, - -(nDebit - nChange), nCredit - nChange)); + -(nDebit - nChange), nCredit - nChange, PUBLIC)); } else if (fAllFromMe) { @@ -288,47 +315,31 @@ QList TransactionRecord::decomposeTransaction(const CWallet * TransactionRecord sub(hash, nTime); sub.idx = parts.size(); - if (wtx.nVersion == ANON_TXN_VERSION - && txout.IsAnonOutput()) - { - const CScript &s = txout.scriptPubKey; - CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); - - CTxDestination address; - sub.idx = parts.size(); // sequence number - sub.credit = txout.nValue; + opcodetype firstOpCode; + CScript::const_iterator pc = txout.scriptPubKey.begin(); + if (txout.scriptPubKey.GetOp(pc, firstOpCode) + && firstOpCode == OP_RETURN) + continue; - sub.type = TransactionRecord::SendShadow; - sub.address = CBitcoinAddress(ckidD).ToString(); + if (wallet->IsMine(txout)) + { + // Ignore parts sent to self, as this is usually the change + // from a transaction sent back to our own address. + continue; + } + CTxDestination address; + if (ExtractDestination(txout.scriptPubKey, address)) + { + // Sent to Bitcoin Address + sub.type = TransactionRecord::SendToAddress; + sub.address = CBitcoinAddress(address).ToString(); } else { - opcodetype firstOpCode; - CScript::const_iterator pc = txout.scriptPubKey.begin(); - if (txout.scriptPubKey.GetOp(pc, firstOpCode) - && firstOpCode == OP_RETURN) - continue; - - if (wallet->IsMine(txout)) - { - // Ignore parts sent to self, as this is usually the change - // from a transaction sent back to our own address. - continue; - } - - CTxDestination address; - if (ExtractDestination(txout.scriptPubKey, address)) - { - // Sent to Bitcoin Address - sub.type = TransactionRecord::SendToAddress; - sub.address = CBitcoinAddress(address).ToString(); - } else - { - // Sent to IP, or other non-address transaction like OP_EVAL - sub.type = TransactionRecord::SendToOther; - sub.address = mapValue["to"]; - } - }; + // Sent to IP, or other non-address transaction like OP_EVAL + sub.type = TransactionRecord::SendToOther; + sub.address = mapValue["to"]; + } snprintf(cbuf, sizeof(cbuf), "n_%u", nOut); mapValue_t::const_iterator mi = wtx.mapValue.find(cbuf); @@ -351,7 +362,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // // Mixed debit transaction, can't break down payees // - TransactionRecord sub(hash, nTime, TransactionRecord::Other, "", "", nNet, 0); + TransactionRecord sub(hash, nTime, TransactionRecord::Other, "", "", nNet, 0, PUBLIC); /* for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++) { @@ -380,7 +391,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) // Find the block the tx is in if (nNodeMode == NT_FULL) { - CBlockIndex* pindex = NULL; + CBlockIndex* pindex = nullptr; std::map::iterator mi = mapBlockIndex.find(wtx.hashBlock); if (mi != mapBlockIndex.end()) { @@ -389,7 +400,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) }; } else { - CBlockThinIndex* pindex = NULL; + CBlockThinIndex* pindex = nullptr; std::map::iterator mi = mapBlockThinIndex.find(wtx.hashBlock); if (mi != mapBlockThinIndex.end()) { @@ -398,12 +409,14 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) }; }; - // Sort order, unrecorded transactions sort to the top + // Sort order nTime has priority (also for unrecorded transactions with nHeight=max) + // only the first 200 transactions are updated in updateTransactions(), + // sorted by nTime makes sure the newest trx are considered for update status.sortKey = strprintf("%010d-%01d-%010u-%03d", - nHeight, - (wtx.IsCoinBase() ? 1 : 0), - wtx.nTimeReceived, - idx); + wtx.nTime, + nHeight, + (wtx.IsCoinBase() ? 1 : 0), + idx); status.countsForBalance = wtx.IsTrusted() && !(wtx.GetBlocksToMaturity() > 0); status.depth = wtx.GetDepthInMainChain(); @@ -421,7 +434,9 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) status.open_for = wtx.nLockTime; }; } else - if (type == TransactionRecord::Generated) + if (type == TransactionRecord::Generated || type == TransactionRecord::GeneratedSPECTRE || + type == TransactionRecord::GeneratedDonation || type == TransactionRecord::GeneratedSPECTREDonation || + type == TransactionRecord::GeneratedContribution || type == TransactionRecord::GeneratedSPECTREContribution) { // For generated transactions, determine maturity if (wtx.GetBlocksToMaturity() > 0) @@ -447,7 +462,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx) status.status = TransactionStatus::Offline; else if (status.depth == 0) status.status = TransactionStatus::Unconfirmed; - else if (status.depth < RecommendedNumConfirmations) + else if (status.depth < (currency == PRIVATE ? MIN_ANON_SPEND_DEPTH : RecommendedNumConfirmations)) status.status = TransactionStatus::Confirming; else status.status = TransactionStatus::Confirmed; diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index fa267cd8eb..ec30896349 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -1,6 +1,14 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef TRANSACTIONRECORD_H #define TRANSACTIONRECORD_H +#include "wallet.h" #include "uint256.h" #include @@ -9,55 +17,35 @@ class CWallet; class CWalletTx; -/** UI model for transaction status. The transaction status is the part of a transaction that will change over time. - */ class TransactionStatus { public: - TransactionStatus(): - countsForBalance(false), sortKey(""), - matures_in(0), status(Offline), depth(0), open_for(0), cur_num_blocks(-1) - { } + TransactionStatus() + : countsForBalance(false), sortKey(""), matures_in(0), + status(Offline), depth(0), open_for(0), cur_num_blocks(-1) {} enum Status { - Confirmed, /**< Have 6 or more confirmations (normal tx) or fully mature (mined tx) **/ - /// Normal (sent/received) transactions - OpenUntilDate, /**< Transaction not yet final, waiting for date */ - OpenUntilBlock, /**< Transaction not yet final, waiting for block */ - Offline, /**< Not sent to any other nodes **/ - Unconfirmed, /**< Not yet mined into a block **/ - Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/ - Conflicted, /**< Conflicts with other transaction or mempool **/ - /// Generated (mined) transactions - Immature, /**< Mined but waiting for maturity */ - MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */ - NotAccepted /**< Mined but not accepted */ + Confirmed, + OpenUntilDate, + OpenUntilBlock, + Offline, + Unconfirmed, + Confirming, + Conflicted, + Immature, + MaturesWarning, + NotAccepted }; - /// Transaction counts towards available balance bool countsForBalance; - /// Sorting key based on status std::string sortKey; - - /** @name Generated (mined) transactions - @{*/ int matures_in; - /**@}*/ - - /** @name Reported status - @{*/ Status status; int64_t depth; - int64_t open_for; /**< Timestamp if status==OpenUntilDate, otherwise number of blocks */ - /**@}*/ - - /** Current number of blocks (to know whether cached status is still valid) */ + int64_t open_for; int cur_num_blocks; }; -/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has - multiple outputs. - */ class TransactionRecord { public: @@ -65,47 +53,51 @@ class TransactionRecord { Other, Generated, + GeneratedSPECTRE, + GeneratedDonation, + GeneratedSPECTREDonation, + GeneratedContribution, + GeneratedSPECTREContribution, SendToAddress, SendToOther, RecvWithAddress, RecvFromOther, SendToSelf, - RecvShadow, - SendShadow, + SendToSelfSPECTRE, + RecvSpectre, + SendSpectre, + ConvertXSPECtoSPECTRE, + ConvertSPECTREtoXSPEC }; static QString getTypeLabel(const int &type); static QString getTypeShort(const int &type); - /** Number of confirmation recommended for accepting a transaction */ - static const int RecommendedNumConfirmations = 10; + static const int RecommendedNumConfirmations = 6; - TransactionRecord(): - hash(), time(0), type(Other), address(""), narration(""), debit(0), credit(0), idx(0) - { - } + TransactionRecord() + : hash(), time(0), type(Other), address(""), narration(""), + debit(0), credit(0), currency(PUBLIC), idx(0) {} - TransactionRecord(uint256 hash, int64_t time): - hash(hash), time(time), type(Other), address(""), narration(""), debit(0), - credit(0), idx(0) - { - } + TransactionRecord(uint256 hash, int64_t time) + : hash(hash), time(time), type(Other), address(""), narration(""), + debit(0), credit(0), currency(PUBLIC), idx(0) {} - TransactionRecord(uint256 hash, int64_t time, - Type type, const std::string &address, const std::string &narration, - int64_t debit, int64_t credit): - hash(hash), time(time), type(type), address(address), narration(narration), debit(debit), credit(credit), - idx(0) - { - } + TransactionRecord(uint256 hash, int64_t time, Type type, const std::string &address, + const std::string &narration, int64_t debit, int64_t credit, + const Currency ¤cy) + : hash(hash), time(time), type(type), address(address), narration(narration), + debit(debit), credit(credit), currency(currency), idx(0) {} + + TransactionRecord(uint256 hash, int64_t time, Type type, const std::string &address, + const std::string &narration, int64_t debit, int64_t credit, + const Currency ¤cy, int idx) + : hash(hash), time(time), type(type), address(address), narration(narration), + debit(debit), credit(credit), currency(currency), idx(idx) {} - /** Decompose CWallet transaction to model transaction records. - */ static bool showTransaction(const CWalletTx &wtx); static QList decomposeTransaction(const CWallet *wallet, const CWalletTx &wtx); - /** @name Immutable transaction attributes - @{*/ uint256 hash; qint64 time; Type type; @@ -113,25 +105,13 @@ class TransactionRecord std::string narration; qint64 debit; qint64 credit; - /**@}*/ - - /** Subtransaction index, for sort key */ + Currency currency; int idx; - - /** Status: can change with block chain update */ TransactionStatus status; - /** Return the unique identifier for this transaction (part) */ std::string getTxID(); - QString getTypeLabel(); - - /** Update status from core wallet tx. - */ void updateStatus(const CWalletTx &wtx); - - /** Return whether a status update is needed. - */ bool statusUpdateNeeded(); }; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 01a5445643..07a2c5c2f0 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include "transactiontablemodel.h" #include "guiutil.h" #include "transactionrecord.h" @@ -7,9 +14,12 @@ #include "optionsmodel.h" #include "addresstablemodel.h" #include "bitcoinunits.h" +#include "sync.h" #include "wallet.h" -#include "ui_interface.h" +#include "interface.h" +#include "shutdown.h" +#include "chainparams_migration.h" #include #include @@ -17,6 +27,7 @@ #include #include #include +#include // Amount column is right-aligned it contains numbers static int column_alignments[] = { @@ -79,9 +90,9 @@ class TransactionTablePriv { // Find bounds of this transaction in model - QList::iterator lower = qLowerBound( + QList::iterator lower = std::lower_bound( cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); - QList::iterator upper = qUpperBound( + QList::iterator upper = std::upper_bound( cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); int lowerIndex = (lower - cachedWallet.begin()); int upperIndex = (upper - cachedWallet.begin()); @@ -93,7 +104,12 @@ class TransactionTablePriv status = CT_NEW; /* Not in model, but want to show, treat as new */ if (!showTransaction && inModel) status = CT_DELETED; /* In model, but want to hide, treat as deleted */ - }; + } + else if (status == CT_NEW && inModel) + { + LogPrintf("Warning: updateWallet: Got CT_NEW, but transaction is already in model => treat as update\n"); + status = CT_UPDATED; + } LogPrintf(" inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i\n", inModel, lowerIndex, upperIndex, showTransaction, status); @@ -101,11 +117,6 @@ class TransactionTablePriv switch(status) { case CT_NEW: - if(inModel) - { - LogPrintf("Warning: updateWallet: Got CT_NEW, but transaction is already in model\n"); - break; - } if(showTransaction) { QList toInsert; @@ -119,12 +130,14 @@ class TransactionTablePriv LogPrintf("Warning: updateWallet: Got CT_NEW, but transaction is not in wallet\n"); break; } + + // Check if spend state of incoming staking rewards cant be determined + if (wallet->IsLocked() && wallet->IsForeignAnonCoinStake(mi->second)) + QMetaObject::invokeMethod(parent->walletModel, "requestUnlockRescan", Qt::QueuedConnection); + // Added -- insert at the right position toInsert = TransactionRecord::decomposeTransaction(wallet, mi->second); - } - if(!toInsert.isEmpty()) /* only if something to insert */ - { parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); int insert_idx = lowerIndex; Q_FOREACH(const TransactionRecord &rec, toInsert) @@ -134,9 +147,9 @@ class TransactionTablePriv } parent->endInsertRows(); } + } break; - break; case CT_DELETED: if(!inModel) { @@ -149,8 +162,31 @@ class TransactionTablePriv parent->endRemoveRows(); break; case CT_UPDATED: - // Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for - // visible transactions. + // Miscellaneous updates, we cant rely on status update since for SPECTRE not only the state of a trx can change. + if(showTransaction) + { + QList toUpdate; + { + LOCK2(cs_main, wallet->cs_wallet); + // Find transaction in wallet + std::map::iterator mi = wallet->mapWallet.find(hash); + if(mi == wallet->mapWallet.end()) + { + LogPrintf("Warning: updateWallet: Got CT_UPDATED, but transaction is not in wallet\n"); + break; + } + toUpdate = TransactionRecord::decomposeTransaction(wallet, mi->second); + + if (toUpdate.size() != (upperIndex - lowerIndex)) + LogPrintf("Warning: updateWallet: Got CT_UPDATED, but existing transaction has different TransactionRecords. (should never happen, not handled)\n"); + else { + int insert_idx = lowerIndex; + Q_FOREACH(const TransactionRecord &rec, toUpdate) + cachedWallet.replace(insert_idx++, rec); + parent->emitDataChanged(lowerIndex, upperIndex-1); + } + } + } break; } } @@ -214,11 +250,11 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren walletModel(parent), priv(new TransactionTablePriv(wallet, this)) { - columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Narration") << tr("Amount"); + columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Note") << tr("Amount"); priv->refreshWallet(); - connect(walletModel->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); + connect(walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &TransactionTableModel::updateDisplayUnit); subscribeToCoreSignals(); } @@ -230,10 +266,36 @@ TransactionTableModel::~TransactionTableModel() void TransactionTableModel::updateTransaction(const QString &hash, int status, bool showTransaction) { - uint256 updated; - updated.SetHex(hash.toStdString()); + TransactionNotification notification(hash, status, showTransaction); + vQueueNotifications.push_back(notification); + + if (fProcessTransactionNotifications) + return; + + fProcessTransactionNotifications = true; - priv->updateWallet(updated, status, showTransaction); + while(!vQueueNotifications.empty() && !QApplication::instance()->closingDown() && !ShutdownRequested()) + { + TRY_LOCK(cs_main, lockMain); + if(!lockMain) { + QApplication::instance()->processEvents(QEventLoop::AllEvents, 100); + continue; + } + LOCK(wallet->cs_wallet); + + auto itTrx = vQueueNotifications.begin(); + while (itTrx !=vQueueNotifications.end()) + { + // Process transaction notification + uint256 updated; + updated.SetHex(itTrx->hash.toStdString()); + priv->updateWallet(updated, itTrx->status, itTrx->showTransaction); + // Remove processed notificaiton from vector + itTrx = vQueueNotifications.erase(itTrx); + } + } + + fProcessTransactionNotifications = false; } void TransactionTableModel::updateConfirmations() @@ -242,8 +304,8 @@ void TransactionTableModel::updateConfirmations() // Invalidate status (number of confirmations) and (possibly) description // for all rows. Qt is smart enough to only actually request the data for the // visible rows. - emit dataChanged(index(0, Status), index(priv->size()-1, Status)); - emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); + Q_EMIT dataChanged(index(0, Status), index(priv->size()-1, Status)); + Q_EMIT dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); } int TransactionTableModel::rowCount(const QModelIndex &parent) const @@ -277,7 +339,10 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons status = tr("Unconfirmed"); break; case TransactionStatus::Confirming: - status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations); + status = wtx->currency == PRIVATE ? tr("Confirming (%1 of %2 required confirmations)"). + arg(wtx->status.depth).arg(MIN_ANON_SPEND_DEPTH) : + tr("Confirming (%1 of %2 recommended confirmations)"). + arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations); break; case TransactionStatus::Confirmed: status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth); @@ -286,13 +351,16 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons status = tr("Conflicted"); break; case TransactionStatus::Immature: - status = tr("Immature (%1 confirmations, will be available after %2)").arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in); + status = tr("Immature (%1 confirmations, will be available after %2)"). + arg(wtx->status.depth).arg(wtx->status.depth + wtx->status.matures_in); break; case TransactionStatus::MaturesWarning: - status = tr("This block was not received by any other nodes and will probably not be accepted!"); + status = tr("Orphan %1 stake, block was not received by any other nodes and will probably not be accepted!"). + arg(wtx->currency == PRIVATE ? "ALIAS (private)" : "ALIAS (public)");; break; case TransactionStatus::NotAccepted: - status = tr("Generated but not accepted"); + status = tr("Orphan %1 stake, someone else submitted the block before you."). + arg(wtx->currency == PRIVATE ? "ALIAS (private)" : "ALIAS (public)"); break; } @@ -309,14 +377,30 @@ QString TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const */ QString TransactionTableModel::lookupAddress(const std::string &address, bool tooltip) const { + if (address.empty()) + return "unknown"; + QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address)); + + bool hasLabel = !label.isEmpty(); QString description; - if(!label.isEmpty()) + + if(hasLabel) description += label + QString(" "); - if(label.isEmpty() || walletModel->getOptionsModel()->getDisplayAddresses() || tooltip) - description += QString("(") + QString::fromStdString(address) + QString(")"); + if(!hasLabel || walletModel->getOptionsModel()->getDisplayAddresses() || tooltip) + { + if (hasLabel) + description += QString("("); + if (address.length() == 102) + description += QString::fromStdString(address.substr(0, 34)) + "..."; + else + description += QString::fromStdString(address); + + if (hasLabel) + description += QString(")"); + } return description; } @@ -334,10 +418,18 @@ QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, b case TransactionRecord::RecvWithAddress: case TransactionRecord::SendToAddress: case TransactionRecord::Generated: + case TransactionRecord::GeneratedDonation: + case TransactionRecord::GeneratedContribution: + case TransactionRecord::GeneratedSPECTRE: + case TransactionRecord::GeneratedSPECTREDonation: + case TransactionRecord::GeneratedSPECTREContribution: + case TransactionRecord::RecvSpectre: + case TransactionRecord::SendSpectre: + case TransactionRecord::ConvertSPECTREtoXSPEC: + case TransactionRecord::ConvertXSPECtoSPECTRE: + case TransactionRecord::SendToSelfSPECTRE: return lookupAddress(wtx->address, tooltip); case TransactionRecord::SendToOther: - case TransactionRecord::RecvShadow: - case TransactionRecord::SendShadow: return QString::fromStdString(wtx->address); case TransactionRecord::SendToSelf: default: @@ -359,14 +451,22 @@ QVariant TransactionTableModel::addressColor(const TransactionRecord *wtx) const case TransactionRecord::RecvWithAddress: case TransactionRecord::SendToAddress: case TransactionRecord::Generated: - case TransactionRecord::RecvShadow: - case TransactionRecord::SendShadow: + case TransactionRecord::GeneratedDonation: + case TransactionRecord::GeneratedContribution: + case TransactionRecord::GeneratedSPECTRE: + case TransactionRecord::GeneratedSPECTREDonation: + case TransactionRecord::GeneratedSPECTREContribution: + case TransactionRecord::RecvSpectre: + case TransactionRecord::SendSpectre: + case TransactionRecord::ConvertSPECTREtoXSPEC: + case TransactionRecord::ConvertXSPECtoSPECTRE: { QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(wtx->address)); if(label.isEmpty()) return COLOR_BAREADDRESS; } break; case TransactionRecord::SendToSelf: + case TransactionRecord::SendToSelfSPECTRE: return COLOR_BAREADDRESS; default: break; @@ -401,33 +501,41 @@ QString TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) return "grey"; case TransactionStatus::Immature: case TransactionStatus::Confirming: - status_switch = wtx->status.status == TransactionStatus::Confirming ? confirmations : (confirmations * 5 / nCoinbaseMaturity + 1); - + status_switch = (confirmations * 3) / (wtx->status.status == TransactionStatus::Confirming ? + wtx->currency == PRIVATE ? MIN_ANON_SPEND_DEPTH : TransactionRecord::RecommendedNumConfirmations : + ChainParamsMigration::GetStakeMinConfirmations(wtx->time)) + 1; switch(status_switch) { - case 1: return "fa-clock-o red"; - case 2: return "fa-clock-o lightred"; - case 3: return "fa-clock-o orange"; - case 4: return "fa-clock-o yellow"; + case 1: return "fa-clock-o grey"; + case 2: return "fa-clock-o lightgreen"; default: return "fa-clock-o green"; }; case TransactionStatus::Confirmed: return "fa-check-circle green"; + case TransactionStatus::NotAccepted: + return "fa-exclamation-triangle grey"; case TransactionStatus::Conflicted: - return "fa-exclamation-triange orange"; + return "fa-exclamation-triangle red"; default: - return "fa-question-circle black"; + return "fa-question-circle grey"; } } QString TransactionTableModel::formatTooltip(const TransactionRecord *rec) const { + if (rec->status.status == TransactionStatus::MaturesWarning || rec->status.status == TransactionStatus::NotAccepted) + { + return formatTxStatus(rec); + } QString tooltip = formatTxStatus(rec) + QString("\n") + rec->getTypeLabel(rec->type); if(rec->type==TransactionRecord::RecvFromOther || rec->type==TransactionRecord::SendToOther || - rec->type==TransactionRecord::SendToAddress || rec->type==TransactionRecord::RecvWithAddress) + rec->type==TransactionRecord::SendToAddress || rec->type==TransactionRecord::RecvWithAddress || + rec->type==TransactionRecord::SendSpectre || rec->type==TransactionRecord::RecvSpectre || + rec->type==TransactionRecord::SendToSelfSPECTRE || + rec->type==TransactionRecord::ConvertSPECTREtoXSPEC || rec->type==TransactionRecord::ConvertXSPECtoSPECTRE) { tooltip += QString(" ") + formatTxToAddress(rec, true); } @@ -513,6 +621,10 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address)); case AmountRole: return rec->credit + rec->debit; + case CurrencyRole: + return rec->currency == PRIVATE ? "PRIVATE" : "PUBLIC"; + case UnitRole: + return walletModel->getOptionsModel()->getDisplayUnit(); case TxIDRole: return QString::fromStdString(rec->getTxID()); case ConfirmedRole: @@ -588,34 +700,13 @@ int TransactionTableModel::lookupTransaction(const QString &txid) const void TransactionTableModel::updateDisplayUnit() { - // emit dataChanged to update Amount column with the current unit - emit dataChanged(index(0, Amount), index(priv->size()-1, Amount)); + Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount)); } -// queue notifications to show a non freezing progress dialog e.g. for rescan -struct TransactionNotification +void TransactionTableModel::emitDataChanged(int rowTop, int rowBottom) { -public: - TransactionNotification() {} - TransactionNotification(uint256 hash, ChangeType status, bool showTransaction): - hash(hash), status(status), showTransaction(showTransaction) {} - - void invoke(QObject *ttm) - { - LogPrintf("NotifyTransactionChanged: %s status= %i", hash.GetHex(), status); - QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(hash.GetHex())), - Q_ARG(int, status), - Q_ARG(bool, showTransaction)); - } -private: - uint256 hash; - ChangeType status; - bool showTransaction; -}; - -static bool fQueueNotifications = false; -static std::vector< TransactionNotification > vQueueNotifications; + Q_EMIT dataChanged(index(rowTop, 0), index(rowBottom, columns.length()-1)); +} static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet, const uint256 &hash, ChangeType status) { @@ -625,26 +716,23 @@ static void NotifyTransactionChanged(TransactionTableModel *ttm, CWallet *wallet bool inWallet = mi != wallet->mapWallet.end(); bool showTransaction = (inWallet && TransactionRecord::showTransaction(mi->second)); - TransactionNotification notification(hash, status, showTransaction); - - if (fQueueNotifications) - { - vQueueNotifications.push_back(notification); - return; - } - notification.invoke(ttm); + LogPrintf("NotifyTransactionChanged: %s status= %i", hash.GetHex(), status); + QMetaObject::invokeMethod(ttm, "updateTransaction", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(hash.GetHex())), + Q_ARG(int, status), + Q_ARG(bool, showTransaction)); } void TransactionTableModel::subscribeToCoreSignals() { // Connect signals to wallet - wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); + wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); //wallet->ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); TODO: Queue notifications... } void TransactionTableModel::unsubscribeFromCoreSignals() { // Disconnect signals from wallet - wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); + wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); //wallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index fcaebfd3f1..e3b7386918 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -1,79 +1,90 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef TRANSACTIONTABLEMODEL_H #define TRANSACTIONTABLEMODEL_H #include #include +#include + class CWallet; class TransactionTablePriv; class TransactionRecord; class WalletModel; -/** UI model for the transaction table of a wallet. - */ +struct TransactionNotification +{ +public: + TransactionNotification() {} + TransactionNotification(QString hash, int status, bool showTransaction) + : hash(hash), status(status), showTransaction(showTransaction) {} + + QString hash; + int status{0}; + bool showTransaction{false}; +}; + class TransactionTableModel : public QAbstractTableModel { Q_OBJECT + public: - explicit TransactionTableModel(CWallet* wallet, WalletModel *parent = 0); + explicit TransactionTableModel(CWallet* wallet, WalletModel *parent = nullptr); ~TransactionTableModel(); enum ColumnIndex { Status = 0, Date = 1, - Type = 2, - ToAddress = 3, - Narration = 4, - Amount = 5 + Amount = 2, + Type = 3, + ToAddress = 4, + Narration = 5 }; - /** Roles to get specific information from a transaction row. - These are independent of column. - */ enum RoleIndex { - /** Type of transaction */ TypeRole = Qt::UserRole, - /** Date and time this transaction was created */ DateRole, - /** Long description (HTML format) */ LongDescriptionRole, - /** Address of transaction */ AddressRole, - /** Label of address related to transaction */ LabelRole, - /** Net amount of transaction */ AmountRole, - /** Unique identifier */ + CurrencyRole, + UnitRole, TxIDRole, - /** Is transaction confirmed? */ ConfirmedRole, - /** Formatted amount, without brackets when unconfirmed */ FormattedAmountRole, - /** Transaction status (TransactionRecord::Status) */ StatusRole, - /** Amount of Confirmations */ ConfirmationsRole }; - int rowCount(const QModelIndex &parent) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const; + int rowCount(const QModelIndex &parent) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override; int lookupTransaction(const QString &txid) const; + private: CWallet* wallet; WalletModel *walletModel; QStringList columns; - TransactionTablePriv *priv; + TransactionTablePriv *priv{nullptr}; + std::vector vQueueNotifications; + bool fProcessTransactionNotifications{false}; QString lookupAddress(const std::string &address, bool tooltip) const; QVariant addressColor(const TransactionRecord *wtx) const; QString formatTxStatus(const TransactionRecord *wtx) const; QString formatTxDate(const TransactionRecord *wtx) const; QString formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const; - QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed=true) const; + QString formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed = true) const; QString formatNarration(const TransactionRecord *wtx) const; QString formatTooltip(const TransactionRecord *rec) const; QString txStatusDecoration(const TransactionRecord *wtx) const; @@ -81,8 +92,9 @@ class TransactionTableModel : public QAbstractTableModel void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); + void emitDataChanged(int rowTop, int rowBottom); -public slots: +public Q_SLOTS: void updateTransaction(const QString &hash, int status, bool showTransaction); void updateConfirmations(); void updateDisplayUnit(); @@ -91,4 +103,3 @@ public slots: }; #endif - diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 99f03bbf1b..ec4a9fe442 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,10 +1,17 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include "walletmodel.h" #include "guiconstants.h" #include "optionsmodel.h" #include "addresstablemodel.h" #include "transactiontablemodel.h" -#include "ui_interface.h" +#include "interface.h" #include "wallet.h" #include "walletdb.h" // for BackupWallet #include "base58.h" @@ -13,22 +20,13 @@ #include WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), - transactionTableModel(0), - cachedBalance(0), cachedShadowBal(0), cachedStake(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), - cachedNumTransactions(0), - cachedEncryptionStatus(Unencrypted), - cachedNumBlocks(0), - fForceCheckBalanceChanged(false) + QObject(parent), + wallet(wallet), + optionsModel(optionsModel) { addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); - // This timer will be fired repeatedly to update the balance - pollTimer = new QTimer(this); - connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged())); - pollTimer->start(MODEL_UPDATE_DELAY); - subscribeToCoreSignals(); } @@ -42,9 +40,9 @@ qint64 WalletModel::getBalance() const return wallet->GetBalance(); } -qint64 WalletModel::getShadowBalance() const +qint64 WalletModel::getSpectreBalance() const { - return wallet->GetShadowBalance(); + return wallet->GetSpectreBalance(); } qint64 WalletModel::getUnconfirmedBalance() const @@ -52,16 +50,31 @@ qint64 WalletModel::getUnconfirmedBalance() const return wallet->GetUnconfirmedBalance(); } +qint64 WalletModel::getUnconfirmedSpectreBalance() const +{ + return wallet->GetUnconfirmedSpectreBalance(); +} + qint64 WalletModel::getStake() const { return wallet->GetStake(); } +qint64 WalletModel::getSpectreStake() const +{ + return wallet->GetSpectreStake(); +} + qint64 WalletModel::getImmatureBalance() const { return wallet->GetImmatureBalance(); } +qint64 WalletModel::getImmatureSpectreBalance() const +{ + return wallet->GetImmatureSpectreBalance(); +} + int WalletModel::getNumTransactions() const { int numTransactions = 0; @@ -76,8 +89,8 @@ void WalletModel::updateStatus() { EncryptionStatus newEncryptionStatus = getEncryptionStatus(); - if(cachedEncryptionStatus != newEncryptionStatus) - emit encryptionStatusChanged(newEncryptionStatus); + if (cachedEncryptionStatus != newEncryptionStatus) + Q_EMIT encryptionStatusChanged(newEncryptionStatus); } void WalletModel::pollBalanceChanged() @@ -97,10 +110,9 @@ void WalletModel::pollBalanceChanged() fForceCheckBalanceChanged = false; int newNumTransactions = getNumTransactions(); - if(cachedNumTransactions != newNumTransactions) - { + if (cachedNumTransactions != newNumTransactions) { cachedNumTransactions = newNumTransactions; - emit numTransactionsChanged(newNumTransactions); + Q_EMIT numTransactionsChanged(newNumTransactions); } // Balance and number of transactions might have changed @@ -113,29 +125,42 @@ void WalletModel::pollBalanceChanged() } } -void WalletModel::checkBalanceChanged() + +void WalletModel::checkBalanceChanged(bool force) { qint64 newBalance = getBalance(); - qint64 newShadowBal = getShadowBalance(); + qint64 newSpectreBal = getSpectreBalance(); qint64 newStake = getStake(); + qint64 newSpectreStake = getSpectreStake(); qint64 newUnconfirmedBalance = getUnconfirmedBalance(); + qint64 newUnconfirmedSpectreBalance = getUnconfirmedSpectreBalance(); qint64 newImmatureBalance = getImmatureBalance(); + qint64 newImmatureSpectreBalance = getImmatureSpectreBalance(); if (cachedBalance != newBalance - || cachedShadowBal != newShadowBal - || cachedStake != newStake - || cachedUnconfirmedBalance != newUnconfirmedBalance - || cachedImmatureBalance != newImmatureBalance) + || cachedSpectreBal != newSpectreBal + || cachedStake != newStake + || cachedSpectreStake != newSpectreStake + || cachedUnconfirmedBalance != newUnconfirmedBalance + || cachedUnconfirmedSpectreBalance != newUnconfirmedSpectreBalance + || cachedImmatureBalance != newImmatureBalance + || cachedImmatureSpectreBalance != newImmatureSpectreBalance + || force == true) { cachedBalance = newBalance; - cachedShadowBal = newShadowBal; + cachedSpectreBal = newSpectreBal; cachedStake = newStake; + cachedSpectreStake = newSpectreStake; cachedUnconfirmedBalance = newUnconfirmedBalance; + cachedUnconfirmedSpectreBalance = newUnconfirmedSpectreBalance; cachedImmatureBalance = newImmatureBalance; - emit balanceChanged(newBalance, newShadowBal, newStake, newUnconfirmedBalance, newImmatureBalance); + cachedImmatureSpectreBalance = newImmatureSpectreBalance; + Q_EMIT balanceChanged(newBalance, newSpectreBal, newStake, newSpectreStake, newUnconfirmedBalance, newUnconfirmedSpectreBalance, newImmatureBalance, cachedImmatureSpectreBalance); } } + + void WalletModel::updateTransaction(const QString &hash, int status) { // Balance and number of transactions might have changed @@ -180,6 +205,9 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList setAddress.size()) - foreach(QString rcpAddr, setAddress) - if(!IsStealthAddress(rcpAddr.toStdString())) + if (recipients.size() > setAddress.size()) { + foreach(QString rcpAddr, setAddress) { + if (!IsStealthAddress(rcpAddr.toStdString())) return DuplicateAddress; + } + } - int64_t nBalance = 0; + int64_t nBalance = 0, nFeeRequired = 0; std::vector vCoins; wallet->AvailableCoins(vCoins, true, coinControl); - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) nBalance += out.tx->vout[out.i].nValue; if(total > nBalance) return AmountExceedsBalance; - if((total + nTransactionFee) > nBalance) - return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); - std::map mapStealthNarr; { @@ -362,7 +389,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListCreateTransaction(vecSend, wtx, nFeeRequired, nChangePos, coinControl); @@ -393,7 +419,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListCommitTransaction(wtx)) + std::map mapPubStealth; + if (!wallet->CommitTransaction(wtx, &mapPubStealth)) return TransactionCommitFailed; hex = QString::fromStdString(wtx.GetHash().GetHex()); @@ -432,7 +459,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListcs_wallet }; - return SendCoinsReturn(OK, 0, hex); + return SendCoinsReturn(OK, nFeeRequired, hex); } WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QList &recipients, const CCoinControl *coinControl) @@ -454,7 +481,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QListGetBalance(); - if ((nTotalOut + nTransactionFee) > nBalance) - return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); + if (nTotalOut > nBalance) + return SendCoinsReturn(AmountExceedsBalance); } else { - nBalance = wallet->GetShadowBalance(); - if ((nTotalOut + MIN_TX_FEE_ANON) > nBalance) - return SendCoinsReturn(SCR_AmountWithFeeExceedsShadowBalance, MIN_TX_FEE_ANON); + nBalance = wallet->GetSpectreBalance(); + if (nTotalOut > nBalance) + return SendCoinsReturn(SCR_AmountExceedsBalance); }; { @@ -517,7 +544,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QList mapStealthNarr; + std::map mapScriptNarr; + std::map mapPubStealth; std::vector > vecSend; std::vector > vecChange; @@ -527,17 +555,27 @@ WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QListIsMine(sxAddrTo)) { + return SendCoinsReturn(RecipientAddressNotOwnedSPECTREtoXSPEC); + } + } + std::string sError; - if (!wallet->CreateStealthOutput(&sxAddrTo, nValue, sNarr, vecSend, mapStealthNarr, sError)) + + if (!wallet->CreateStealthOutput(&sxAddrTo, nValue, sNarr, vecSend, scriptNarration, sError)) { LogPrintf("SendCoinsAnon() CreateStealthOutput failed %s.\n", sError.c_str()); return SendCoinsReturn(SCR_ErrorWithMsg, 0, QString::fromStdString(sError)); @@ -545,25 +583,22 @@ WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QListCreateAnonOutputs(&sxAddrTo, nValue, sNarr, vecSend, scriptNarration)) + // -- out spectre + if (inputTypes == 0) { + // -- Check that we own the recipient address (XSPEC to SPECTRE only allowed for transformation) + if (!wallet->IsMine(sxAddrTo)) { + return SendCoinsReturn(RecipientAddressNotOwnedXSPECtoSPECTRE); + } + } + + if (!wallet->CreateAnonOutputs(&sxAddrTo, nValue, sNarr, vecSend, scriptNarration, &mapPubStealth)) { LogPrintf("SendCoinsAnon() CreateAnonOutputs failed.\n"); return SCR_Error; }; - - if (scriptNarration.size() > 0) - { - for (uint32_t k = 0; k < vecSend.size(); ++k) - { - if (vecSend[k].first != scriptNarration) - continue; - mapStealthNarr[k] = sNarr; - break; - }; - }; }; + if (scriptNarration.size() > 0) + mapScriptNarr[scriptNarration] = sNarr; }; @@ -573,7 +608,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoinsAnon(const QList::iterator it; - for (it = mapStealthNarr.begin(); it != mapStealthNarr.end(); ++it) - { - int pos = it->first; - if (nChangePos > -1 && it->first >= nChangePos) - pos++; - - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", pos) < 1) - { - LogPrintf("SendCoinsAnon(): Error creating narration key."); - continue; - }; - wtxNew.mapValue[key] = it->second; - }; - - } else + } + else { - // -- in shadow + // -- in SPECTRE std::string sError; - if (!wallet->AddAnonInputs(RING_SIG_2, nTotalOut, nRingSize, vecSend, vecChange, wtxNew, nFeeRequired, false, sError)) + if (!wallet->AddAnonInputs(nRingSize == 1 ? RING_SIG_1 : RING_SIG_2, nTotalOut, nRingSize, vecSend, vecChange, wtxNew, nFeeRequired, false, sError)) { - if ((nTotalOut + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future - return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); + if (nFeeRequired != MAX_MONEY && (nTotalOut + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future + return SendCoinsReturn(SCR_AmountWithFeeExceedsSpectreBalance, nFeeRequired); LogPrintf("SendCoinsAnon() AddAnonInputs failed %s.\n", sError.c_str()); - if (!Params().IsProtocolV3(nBestHeight)) - sError += "\nTry again after block 783000."; - return SendCoinsReturn(SCR_ErrorWithMsg, 0, QString::fromStdString(sError)); }; - - std::map::iterator it; - for (it = mapStealthNarr.begin(); it != mapStealthNarr.end(); ++it) - { - int pos = it->first; - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", pos) < 1) - { - LogPrintf("SendCoinsAnon(): Error creating narration key."); - continue; - }; - wtxNew.mapValue[key] = it->second; - }; - }; + for (const auto & [scriptNarration, sNarr] : mapScriptNarr) + { + std::string sError; + if (!wallet->SaveNarrationOutput(wtxNew, scriptNarration, sNarr, sError)) + { + LogPrintf("SendCoinsAnon(): %s\n", sError.c_str()); + return SendCoinsReturn(SCR_Error, 0, QString::fromStdString(sError)); + } + } if (!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) return Aborted; //return SendCoinsReturn(SCR_ErrorWithMsg, 0, QString::fromStdString(std::string("Testing error"))); - if (!wallet->CommitTransaction(wtxNew)) + if (!wallet->CommitTransaction(wtxNew, &mapPubStealth)) { LogPrintf("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.\n"); - wallet->UndoAnonTransaction(wtxNew); + wallet->UndoAnonTransaction(wtxNew, &mapPubStealth); return TransactionCommitFailed; }; @@ -802,26 +813,24 @@ static void NotifyTransactionChanged(WalletModel *walletModel, CWallet *wallet, void WalletModel::subscribeToCoreSignals() { - // Connect signals to wallet - wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); - wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6)); - wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); + wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, boost::placeholders::_1)); + wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3, boost::placeholders::_4, boost::placeholders::_5, boost::placeholders::_6)); + wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); - connect(this, SIGNAL(encryptionStatusChanged(int)), addressTableModel, SLOT(setEncryptionStatus(int))); + connect(this, &WalletModel::encryptionStatusChanged, addressTableModel, &AddressTableModel::setEncryptionStatus); } void WalletModel::unsubscribeFromCoreSignals() { - // Disconnect signals from wallet - wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1)); - wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6)); - wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3)); + wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, boost::placeholders::_1)); + wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3, boost::placeholders::_4, boost::placeholders::_5, boost::placeholders::_6)); + wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, boost::placeholders::_1, boost::placeholders::_2, boost::placeholders::_3)); - disconnect(this, SIGNAL(encryptionStatusChanged(int)), addressTableModel, SLOT(setEncryptionStatus(int))); + disconnect(this, &WalletModel::encryptionStatusChanged, addressTableModel, &AddressTableModel::setEncryptionStatus); } // WalletModel::UnlockContext implementation -WalletModel::UnlockContext WalletModel::requestUnlock() +WalletModel::UnlockContext WalletModel::requestUnlock(WalletModel::UnlockMode mode) { bool was_locked = getEncryptionStatus() == Locked; @@ -831,10 +840,8 @@ WalletModel::UnlockContext WalletModel::requestUnlock() was_locked = getEncryptionStatus() == Locked; } - if(was_locked) - { - // Request UI to unlock wallet - emit requireUnlock(); + if (was_locked) { + Q_EMIT requireUnlock(mode); } // If wallet is still locked, unlock was failed or cancelled, mark context as invalid bool valid = getEncryptionStatus() != Locked; @@ -842,6 +849,20 @@ WalletModel::UnlockContext WalletModel::requestUnlock() return UnlockContext(this, valid, was_locked && !fWalletUnlockStakingOnly); } +void WalletModel::requestUnlockRescan() +{ + if (!fUnlockRescanRequested && getEncryptionStatus() == Locked) { + fUnlockRescanRequested = true; + Q_EMIT requireUnlock(rescan); + if (getEncryptionStatus() != Locked) { + fForceCheckBalanceChanged = true; + if (!fWalletUnlockStakingOnly) + setWalletLocked(true); + } + fUnlockRescanRequested = false; + } +} + WalletModel::UnlockContext::UnlockContext(WalletModel *wallet, bool valid, bool relock): wallet(wallet), valid(valid), @@ -873,7 +894,7 @@ bool WalletModel::getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) { LOCK2(cs_main, wallet->cs_wallet); - BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) + for (const COutPoint& outpoint : vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); @@ -883,8 +904,8 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect } } -// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) -void WalletModel::listCoins(std::map >& mapCoins) const +// AvailableCoins + LockedCoins grouped by wallet address or stealth address (put change in one group with wallet address) +void WalletModel::listCoins(std::map> >& mapCoins) const { std::vector vCoins; wallet->AvailableCoins(vCoins); @@ -893,7 +914,7 @@ void WalletModel::listCoins(std::map >& mapCoins) std::vector vLockedCoins; // add locked coins - BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins) + for (const COutPoint& outpoint : vLockedCoins) { if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); @@ -902,22 +923,46 @@ void WalletModel::listCoins(std::map >& mapCoins) vCoins.push_back(out); } - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) { COutput cout = out; - + bool isChangeOutput = false; while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) { if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); + isChangeOutput = true; } CTxDestination address; if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; - mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); + + // Check if a stealth mapping address exist for output address + if (wallet->mapAddressBook.count(address)) + { + std::string stealthAddress = wallet->mapAddressBook.at(address); + if (IsStealthAddressMappingLabel(stealthAddress)) + { + mapCoins[stealthAddress.c_str()].push_back({out, isChangeOutput}); + continue; + } + } + + mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back({out, isChangeOutput}); } } +/* Look up stealth address for address in wallet + */ +bool WalletModel::getStealthAddress(const QString &address, CStealthAddress& stealthAddressOut) const +{ + LOCK(wallet->cs_wallet); + std::string sAddr = address.toStdString(); + if (wallet->GetStealthAddress(sAddr, stealthAddressOut)) + return true; + return false; +} + bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const { return false; @@ -937,3 +982,13 @@ void WalletModel::listLockedCoins(std::vector& vOutpts) { return; } + +void WalletModel::emitBalanceChanged(qint64 balance, qint64 spectreBal, qint64 stake, qint64 spectreStake, qint64 unconfirmed, qint64 spectreUnconfirmed, qint64 immature, qint64 spectreImmature) +{ + Q_EMIT balanceChanged(balance, spectreBal, stake, spectreStake, unconfirmed, spectreUnconfirmed, immature, spectreImmature); +} + +void WalletModel::emitNumTransactionsChanged(int count) { Q_EMIT numTransactionsChanged(count); } +void WalletModel::emitEncryptionStatusChanged(int status) { Q_EMIT encryptionStatusChanged(status); } +void WalletModel::emitRequireUnlock(UnlockMode mode) { Q_EMIT requireUnlock(mode); } +void WalletModel::emitError(const QString &title, const QString &message, bool modal) { Q_EMIT error(title, message, modal); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 1fb79c7408..65701951de 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -1,11 +1,20 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef WALLETMODEL_H #define WALLETMODEL_H #include + #include #include -#include "allocators.h" /* for SecureString */ +#include "allocators.h" +#include "stealth.h" class OptionsModel; class AddressTableModel; @@ -24,10 +33,10 @@ QT_END_NAMESPACE enum eTxnTypeInd { - TXT_SDC_TO_SDC = 0, - TXT_SDC_TO_ANON, + TXT_SPEC_TO_SPEC = 0, + TXT_SPEC_TO_ANON, TXT_ANON_TO_ANON, - TXT_ANON_TO_SDC, + TXT_ANON_TO_SPEC, }; class SendCoinsRecipient @@ -36,37 +45,41 @@ class SendCoinsRecipient QString address; QString label; QString narration; - int typeInd; - qint64 amount; - int txnTypeInd; - int nRingSize; + int typeInd{0}; + qint64 amount{0}; + int txnTypeInd{0}; + int nRingSize{0}; }; -/** Interface to Bitcoin wallet from Qt view code. */ class WalletModel : public QObject { Q_OBJECT public: - explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0); + explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = nullptr); ~WalletModel(); - enum StatusCode // Returned by sendCoins + enum StatusCode { OK, InvalidAmount, InvalidAddress, + StealthAddressOnlyAllowedForSPECTRE, + RecipientAddressNotOwnedXSPECtoSPECTRE, + RecipientAddressNotOwnedSPECTREtoXSPEC, AmountExceedsBalance, AmountWithFeeExceedsBalance, DuplicateAddress, - TransactionCreationFailed, // Error returned when wallet is still locked + TransactionCreationFailed, TransactionCommitFailed, NarrationTooLong, RingSizeError, InputTypeError, SCR_NeedFullMode, SCR_StealthAddressFail, - SCR_AmountWithFeeExceedsShadowBalance, + SCR_StealthAddressFailAnonToSpec, + SCR_AmountExceedsBalance, + SCR_AmountWithFeeExceedsSpectreBalance, SCR_Error, SCR_ErrorWithMsg, Aborted @@ -74,9 +87,9 @@ class WalletModel : public QObject enum EncryptionStatus { - Unencrypted, // !wallet->IsCrypted() - Locked, // wallet->IsCrypted() && wallet->IsLocked() - Unlocked // wallet->IsCrypted() && !wallet->IsLocked() + Unencrypted, + Locked, + Unlocked }; OptionsModel *getOptionsModel(); @@ -84,44 +97,35 @@ class WalletModel : public QObject TransactionTableModel *getTransactionTableModel(); qint64 getBalance() const; - qint64 getShadowBalance() const; + qint64 getSpectreBalance() const; qint64 getStake() const; + qint64 getSpectreStake() const; qint64 getUnconfirmedBalance() const; + qint64 getUnconfirmedSpectreBalance() const; qint64 getImmatureBalance() const; + qint64 getImmatureSpectreBalance() const; int getNumTransactions() const; EncryptionStatus getEncryptionStatus() const; - // Check address for validity bool validateAddress(const QString &address); - // Return status record for SendCoins, contains error id + information struct SendCoinsReturn { - SendCoinsReturn(StatusCode status=Aborted, - qint64 fee=0, - QString hex=QString()): - status(status), fee(fee), hex(hex) {} + SendCoinsReturn(StatusCode status = Aborted, qint64 fee = 0, QString hex = QString()) + : status(status), fee(fee), hex(hex) {} StatusCode status; - - - qint64 fee; // is used in case status is "AmountWithFeeExceedsBalance" - QString hex; // is filled with the transaction hash if status is "OK", error message otherwise + qint64 fee; + QString hex; }; - // Send coins to a list of recipients - SendCoinsReturn sendCoins(const QList &recipients, const CCoinControl *coinControl=NULL); - SendCoinsReturn sendCoinsAnon(const QList &recipients, const CCoinControl *coinControl=NULL); - - - // Wallet encryption + SendCoinsReturn sendCoins(const QList &recipients, const CCoinControl *coinControl = nullptr); + SendCoinsReturn sendCoinsAnon(const QList &recipients, const CCoinControl *coinControl = nullptr); + bool setWalletEncrypted(bool encrypted, const SecureString &passphrase); - // Passphrase only needed when unlocking - bool setWalletLocked(bool locked, const SecureString &passPhrase=SecureString()); + bool setWalletLocked(bool locked, const SecureString &passPhrase = SecureString()); bool changePassphrase(const SecureString &oldPass, const SecureString &newPass); - // Wallet backup bool backupWallet(const QString &filename); - // RAI object for unlocking wallet, returned by requestUnlock() class UnlockContext { public: @@ -130,83 +134,72 @@ class WalletModel : public QObject bool isValid() const { return valid; } - // Copy operator and constructor transfer the context UnlockContext(const UnlockContext& obj) { CopyFrom(obj); } UnlockContext& operator=(const UnlockContext& rhs) { CopyFrom(rhs); return *this; } + private: WalletModel *wallet; bool valid; - mutable bool relock; // mutable, as it can be set to false by copying + mutable bool relock; void CopyFrom(const UnlockContext& rhs); }; - UnlockContext requestUnlock(); + enum UnlockMode { standard, rescan, login }; + UnlockContext requestUnlock(UnlockMode unlockMode = standard); + int fUnlockRescanRequested{false}; bool getPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const; void getOutputs(const std::vector& vOutpoints, std::vector& vOutputs); - void listCoins(std::map >& mapCoins) const; + void listCoins(std::map>>& mapCoins) const; + bool getStealthAddress(const QString &address, CStealthAddress& stealthAddressOut) const; bool isLockedCoin(uint256 hash, unsigned int n) const; void lockCoin(COutPoint& output); void unlockCoin(COutPoint& output); void listLockedCoins(std::vector& vOutpts); - + + void emitBalanceChanged(qint64 balance, qint64 spectreBal, qint64 stake, qint64 spectreStake, qint64 unconfirmed, qint64 spectreUnconfirmed, qint64 immature, qint64 spectreImmature); + void emitNumTransactionsChanged(int count); + void emitEncryptionStatusChanged(int status); + void emitRequireUnlock(UnlockMode mode); + void emitError(const QString &title, const QString &message, bool modal); + void checkBalanceChanged(bool force = false); + private: CWallet *wallet; - - // Wallet has an options model for wallet-specific options - // (transaction fee, for example) OptionsModel *optionsModel; - - AddressTableModel *addressTableModel; - TransactionTableModel *transactionTableModel; - - // Cache some values to be able to detect changes - qint64 cachedBalance; - qint64 cachedShadowBal; - qint64 cachedStake; - qint64 cachedUnconfirmedBalance; - qint64 cachedImmatureBalance; - qint64 cachedNumTransactions; - EncryptionStatus cachedEncryptionStatus; - int cachedNumBlocks; - bool fForceCheckBalanceChanged; - - QTimer *pollTimer; + AddressTableModel *addressTableModel{nullptr}; + TransactionTableModel *transactionTableModel{nullptr}; + + qint64 cachedBalance{0}; + qint64 cachedSpectreBal{0}; + qint64 cachedStake{0}; + qint64 cachedSpectreStake{0}; + qint64 cachedUnconfirmedBalance{0}; + qint64 cachedUnconfirmedSpectreBalance{0}; + qint64 cachedImmatureBalance{0}; + qint64 cachedImmatureSpectreBalance{0}; + qint64 cachedNumTransactions{0}; + EncryptionStatus cachedEncryptionStatus{Unencrypted}; + int cachedNumBlocks{0}; + bool fForceCheckBalanceChanged{false}; void subscribeToCoreSignals(); void unsubscribeFromCoreSignals(); - void checkBalanceChanged(); - -public slots: - /* Wallet status might have changed */ +public Q_SLOTS: void updateStatus(); - /* New transaction, or transaction changed status */ void updateTransaction(const QString &hash, int status); - /* New, updated or removed address book entry */ void updateAddressBook(const QString &address, const QString &label, bool isMine, int status, bool fManual); - /* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */ void pollBalanceChanged(); + void requestUnlockRescan(); -signals: - // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 shadowBal, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance); - - // Number of transactions in wallet changed +Q_SIGNALS: + void balanceChanged(qint64 balance, qint64 spectreBal, qint64 stake, qint64 spectreStake, qint64 unconfirmed, qint64 spectreUnconfirmed, qint64 immature, qint64 spectreImmature); void numTransactionsChanged(int count); - - // Encryption status of wallet changed void encryptionStatusChanged(int status); - - // Signal emitted when wallet needs to be unlocked - // It is valid behaviour for listeners to keep the wallet locked after this signal; - // this means that the unlocking failed or was cancelled. - void requireUnlock(); - - // Asynchronous error notification + void requireUnlock(WalletModel::UnlockMode mode); void error(const QString &title, const QString &message, bool modal); }; - #endif // WALLETMODEL_H diff --git a/src/qt/websocketclientwrapper.cpp b/src/qt/websocketclientwrapper.cpp new file mode 100755 index 0000000000..cdfbabfcee --- /dev/null +++ b/src/qt/websocketclientwrapper.cpp @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, +// +// SPDX-License-Identifier: BSD-4-Clause + +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd 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 COPYRIGHT HOLDERS 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 COPYRIGHT +** OWNER 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "websocketclientwrapper.h" +#include "websockettransport.h" + +#include +#include +#include +#include +#include +#include + +/*! + \brief Wraps connected QWebSockets clients in WebSocketTransport objects. + + This code is all that is required to connect incoming WebSockets to the WebChannel. Any kind + of remote JavaScript client that supports WebSockets can thus receive messages and access the + published objects. +*/ + +/*! + Construct the client wrapper with the given parent. + + All clients connecting to the QWebSocketServer will be automatically wrapped + in WebSocketTransport objects. +*/ +WebSocketClientWrapper::WebSocketClientWrapper(QWebSocketServer *server, QString accessToken, QObject *parent) + : QObject(parent) + , m_server(server), accessToken(accessToken) +{ + connect(server, &QWebSocketServer::newConnection, + this, &WebSocketClientWrapper::handleNewConnection); +} + +/*! + Wrap an incoming WebSocket connection in a WebSocketTransport object. +*/ +void WebSocketClientWrapper::handleNewConnection() +{ + QWebSocket* pendingConnection = m_server->nextPendingConnection(); + QUrlQuery urlQuery(pendingConnection->request().url()); + QString token = urlQuery.queryItemValue("token"); + if (!urlQuery.hasQueryItem("token")) + qDebug() << "new webocket connection refused: token query param is missing"; + else if (token != accessToken) + qDebug() << "new webocket connection refused: invalid token: " << token; + else + Q_EMIT clientConnected(new WebSocketTransport(pendingConnection)); +} diff --git a/src/qt/websocketclientwrapper.h b/src/qt/websocketclientwrapper.h new file mode 100755 index 0000000000..dc9f1c17c7 --- /dev/null +++ b/src/qt/websocketclientwrapper.h @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, +// +// SPDX-License-Identifier: BSD-4-Clause + +#ifndef WEBSOCKETCLIENTWRAPPER_H +#define WEBSOCKETCLIENTWRAPPER_H + +#include + +class WebSocketTransport; + +QT_BEGIN_NAMESPACE +class QWebSocketServer; +QT_END_NAMESPACE + +class WebSocketClientWrapper : public QObject +{ + Q_OBJECT + +public: + WebSocketClientWrapper(QWebSocketServer *server, QString accessToken, QObject *parent = nullptr); + +Q_SIGNALS: + void clientConnected(WebSocketTransport *client); + +private Q_SLOTS: + void handleNewConnection(); + +private: + QWebSocketServer *m_server{nullptr}; + QString accessToken; +}; + +#endif // WEBSOCKETCLIENTWRAPPER_H diff --git a/src/qt/websockettransport.cpp b/src/qt/websockettransport.cpp new file mode 100755 index 0000000000..9b0709dcef --- /dev/null +++ b/src/qt/websockettransport.cpp @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, +// +// SPDX-License-Identifier: BSD-4-Clause + +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * 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. +** * Neither the name of The Qt Company Ltd 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 COPYRIGHT HOLDERS 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 COPYRIGHT +** OWNER 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "websockettransport.h" + +#include +#include +#include +#include + +/*! + \brief QWebChannelAbstractSocket implementation that uses a QWebSocket internally. + + The transport delegates all messages received over the QWebSocket over its + textMessageReceived signal. Analogously, all calls to sendTextMessage will + be send over the QWebSocket to the remote client. +*/ + +/*! + Construct the transport object and wrap the given socket. + + The socket is also set as the parent of the transport object. +*/ +WebSocketTransport::WebSocketTransport(QWebSocket *socket) +: QWebChannelAbstractTransport(socket) +, m_socket(socket) +{ + connect(socket, &QWebSocket::textMessageReceived, + this, &WebSocketTransport::textMessageReceived); + connect(socket, &QWebSocket::disconnected, + this, &WebSocketTransport::deleteLater); +} + +/*! + Destroys the WebSocketTransport. +*/ +WebSocketTransport::~WebSocketTransport() +{ + m_socket->deleteLater(); +} + +/*! + Serialize the JSON message and send it as a text message via the WebSocket to the client. +*/ +void WebSocketTransport::sendMessage(const QJsonObject &message) +{ + QJsonDocument doc(message); + //QString jsonMessage = QString::fromUtf8(doc.toJson(QJsonDocument::Compact)); + //qDebug() << "sendMessage:" << jsonMessage; + m_socket->sendTextMessage(QString::fromUtf8(doc.toJson(QJsonDocument::Compact))); +} + +/*! + Deserialize the stringified JSON messageData and emit messageReceived. +*/ +void WebSocketTransport::textMessageReceived(const QString &messageData) +{ + QJsonParseError error; + QJsonDocument message = QJsonDocument::fromJson(messageData.toUtf8(), &error); + if (error.error) { + qWarning() << "Failed to parse text message as JSON object:" << messageData + << "Error is:" << error.errorString(); + return; + } else if (!message.isObject()) { + qWarning() << "Received JSON message that is not an object: " << messageData; + return; + } + //qDebug() << "textMessageReceived:" << messageData; + Q_EMIT messageReceived(message.object(), this); +} diff --git a/src/qt/websockettransport.h b/src/qt/websockettransport.h new file mode 100755 index 0000000000..436987661a --- /dev/null +++ b/src/qt/websockettransport.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, +// +// SPDX-License-Identifier: BSD-4-Clause + +#ifndef WEBSOCKETTRANSPORT_H +#define WEBSOCKETTRANSPORT_H + +#include + +QT_BEGIN_NAMESPACE +class QWebSocket; +QT_END_NAMESPACE + +class WebSocketTransport : public QWebChannelAbstractTransport +{ + Q_OBJECT + +public: + explicit WebSocketTransport(QWebSocket *socket); + virtual ~WebSocketTransport(); + + void sendMessage(const QJsonObject &message) override; + +private Q_SLOTS: + void textMessageReceived(const QString &message); + +private: + QWebSocket *m_socket{nullptr}; +}; + +#endif // WEBSOCKETTRANSPORT_H diff --git a/src/qt/winshutdownmonitor.cpp b/src/qt/winshutdownmonitor.cpp new file mode 100644 index 0000000000..c89ccc891b --- /dev/null +++ b/src/qt/winshutdownmonitor.cpp @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#include + +#if defined(Q_OS_WIN) +#include +#include + +#include + +#include + +#include + +// If we don't want a message to be processed by Qt, return true and set result to +// the value that the window procedure should return. Otherwise return false. +bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) +{ + Q_UNUSED(eventType); + + MSG *pMsg = static_cast(pMessage); + + // Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions) + if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) { + // Warn only once as this is performance-critical + static bool warned = false; + if (!warned) { + LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__); + warned = true; + } + } + + switch(pMsg->message) + { + case WM_QUERYENDSESSION: + { + // Initiate a client shutdown after receiving a WM_QUERYENDSESSION and block + // Windows session end until we have finished client shutdown. + qDebug() << "WM_QUERYENDSESSION -> StartShutdown()."; + StartShutdown(); + *pnResult = FALSE; + return true; + } + + case WM_ENDSESSION: + { + *pnResult = FALSE; + return true; + } + } + + return false; +} + +void WinShutdownMonitor::registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId) +{ + typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); + PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)GetProcAddress(GetModuleHandleA("User32.dll"), "ShutdownBlockReasonCreate"); + if (shutdownBRCreate == nullptr) { + qWarning() << "registerShutdownBlockReason: GetProcAddress for ShutdownBlockReasonCreate failed"; + return; + } + + if (shutdownBRCreate(mainWinId, strReason.toStdWString().c_str())) + qWarning() << "registerShutdownBlockReason: Successfully registered: " + strReason; + else + qWarning() << "registerShutdownBlockReason: Failed to register: " + strReason; +} +#endif diff --git a/src/qt/winshutdownmonitor.h b/src/qt/winshutdownmonitor.h new file mode 100644 index 0000000000..a1aeede590 --- /dev/null +++ b/src/qt/winshutdownmonitor.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef BITCOIN_QT_WINSHUTDOWNMONITOR_H +#define BITCOIN_QT_WINSHUTDOWNMONITOR_H + +#ifdef WIN32 +#include +#include + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include + +#include + +class WinShutdownMonitor : public QAbstractNativeEventFilter +{ +public: + bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) override; + static void registerShutdownBlockReason(const QString& strReason, const HWND& mainWinId); +}; +#endif + +#endif // BITCOIN_QT_WINSHUTDOWNMONITOR_H diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000000..e9e89927f0 --- /dev/null +++ b/src/resource.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by src.rc +// +#define IDI_ICON1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/ringsig.cpp b/src/ringsig.cpp index 5d1be3f753..e745d9017a 100644 --- a/src/ringsig.cpp +++ b/src/ringsig.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "ringsig.h" #include "base58.h" @@ -16,9 +19,9 @@ #include -static EC_GROUP *ecGrp = NULL; -static BN_CTX *bnCtx = NULL; -static BIGNUM *bnOrder = NULL; +static EC_GROUP *ecGrp = nullptr; +static BN_CTX *bnCtx = nullptr; +static BIGNUM *bnOrder = nullptr; int initialiseRingSigs() @@ -55,20 +58,25 @@ int finaliseRingSigs() BN_CTX_free(bnCtx); EC_GROUP_clear_free(ecGrp); - ecGrp = NULL; - bnCtx = NULL; - bnOrder = NULL; + ecGrp = nullptr; + bnCtx = nullptr; + bnOrder = nullptr; return 0; } -int splitAmount(int64_t nValue, std::vector& vOut) +int splitAmount(int64_t nValue, std::vector& vOut, int64_t maxAnonOutput) { - // - split amounts into 1, 3, 4, 5 + // First make sure no output bigger than maxAnonOutput is created + for (int numOfMaxAnonOutputs = nValue / maxAnonOutput; numOfMaxAnonOutputs > 0; numOfMaxAnonOutputs--) { + vOut.push_back(1 * maxAnonOutput); + } + nValue = nValue % maxAnonOutput; - int64_t nTest = 1; - int i; + // - split amounts into 1, 3, 4, 5 + int64_t nTest = 1; + int i; while (nValue >= nTest) { @@ -107,7 +115,7 @@ int splitAmount(int64_t nValue, std::vector& vOut) } -int getOldKeyImage(CPubKey &publicKey, ec_point &keyImage) +int getOldKeyImage(const CPubKey &publicKey, ec_point &keyImage) { // - PublicKey * Hash(PublicKey) if (publicKey.size() != EC_COMPRESSED_SIZE) @@ -119,7 +127,7 @@ int getOldKeyImage(CPubKey &publicKey, ec_point &keyImage) BN_CTX_start(bnCtx); BIGNUM *bnTmp = BN_CTX_get(bnCtx); - EC_POINT *ptPk = NULL; + EC_POINT *ptPk = nullptr; // Hash to BIGNUM if (!BN_bin2bn(pkHash.begin(), EC_SECRET_SIZE, bnTmp) @@ -136,7 +144,7 @@ int getOldKeyImage(CPubKey &publicKey, ec_point &keyImage) goto End; // PublicKey * Hash(PublicKey) - if (!EC_POINT_mul(ecGrp, ptPk, NULL, ptPk, bnTmp, bnCtx) + if (!EC_POINT_mul(ecGrp, ptPk, nullptr, ptPk, bnTmp, bnCtx) && (rv = errorN(1, "%s: EC_POINT_mul failed.", __func__))) goto End; @@ -181,14 +189,14 @@ static int hashToEC(const uint8_t *p, uint32_t len, BIGNUM *bnTmp, EC_POINT *ptR BN_add(bnTmp, bnTmp, bnOne); } else - if (!EC_POINT_mul(ecGrp, ptRet, bnTmp, NULL, NULL, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptRet, bnTmp, nullptr, nullptr, bnCtx)) return errorN(1, "%s: EC_POINT_mul failed.", __func__); return 0; } -int generateKeyImage(ec_point &publicKey, ec_secret secret, ec_point &keyImage) +int generateKeyImage(const ec_point &publicKey, ec_secret secret, ec_point &keyImage) { // - keyImage = secret * hash(publicKey) * G @@ -199,7 +207,7 @@ int generateKeyImage(ec_point &publicKey, ec_secret secret, ec_point &keyImage) int rv = 0; BIGNUM *bnTmp = BN_CTX_get(bnCtx); BIGNUM *bnSec = BN_CTX_get(bnCtx); - EC_POINT *hG = NULL; + EC_POINT *hG = nullptr; if (!(hG = EC_POINT_new(ecGrp)) && (rv = errorN(1, "%s: EC_POINT_new failed.", __func__))) @@ -213,7 +221,7 @@ int generateKeyImage(ec_point &publicKey, ec_secret secret, ec_point &keyImage) && (rv = errorN(1, "%s: BN_bin2bn failed.", __func__))) goto End; - if (!EC_POINT_mul(ecGrp, hG, NULL, hG, bnSec, bnCtx) + if (!EC_POINT_mul(ecGrp, hG, nullptr, hG, bnSec, bnCtx) && (rv = errorN(1, "%s: kimg EC_POINT_mul failed.", __func__))) goto End; @@ -240,7 +248,7 @@ int generateKeyImage(ec_point &publicKey, ec_secret secret, ec_point &keyImage) } -int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr) +int generateRingSignature(const data_chunk &keyImage, const uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr) { if (fDebugRingSig) LogPrintf("%s: Ring size %d.\n", __func__, nRingSize); @@ -256,13 +264,13 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnH = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); - EC_POINT *ptT1 = NULL; - EC_POINT *ptT2 = NULL; - EC_POINT *ptT3 = NULL; - EC_POINT *ptPk = NULL; - EC_POINT *ptKi = NULL; - EC_POINT *ptL = NULL; - EC_POINT *ptR = NULL; + EC_POINT *ptT1 = nullptr; + EC_POINT *ptT2 = nullptr; + EC_POINT *ptT3 = nullptr; + EC_POINT *ptPk = nullptr; + EC_POINT *ptKi = nullptr; + EC_POINT *ptL = nullptr; + EC_POINT *ptR = nullptr; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; @@ -289,11 +297,7 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, } // zero sum - if (!bnSum || !(BN_zero(bnSum))) - { - LogPrintf("%s: BN_zero failed.\n", __func__); - rv = 1; goto End; - } + BN_zero(bnSum); if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) @@ -320,7 +324,7 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, // L = k * G // R = k * HashToEC(PKi) - if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptL, bnKS, nullptr, nullptr, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -332,7 +336,7 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, rv = 1; goto End; } - if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptR, nullptr, ptT1, bnKS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -365,14 +369,14 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, } // ptT1 = k1 * Pi - if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, nullptr, ptPk, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT2 = k2 * G - if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT2, bnK2, nullptr, nullptr, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -393,14 +397,14 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, } // ptT1 = k1 * I - if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, nullptr, ptKi, bnK1, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT2 = k2 * ptT3 - if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT2, nullptr, ptT3, bnK2, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -506,7 +510,7 @@ int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, return rv; } -int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr) +int verifyRingSignature(const data_chunk &keyImage, const uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr) { int rv = 0; @@ -517,13 +521,13 @@ int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, c BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnR = BN_CTX_get(bnCtx); BIGNUM *bnSum = BN_CTX_get(bnCtx); - EC_POINT *ptT1 = NULL; - EC_POINT *ptT2 = NULL; - EC_POINT *ptT3 = NULL; - EC_POINT *ptPk = NULL; - EC_POINT *ptKi = NULL; - EC_POINT *ptL = NULL; - EC_POINT *ptR = NULL; + EC_POINT *ptT1 = nullptr; + EC_POINT *ptT2 = nullptr; + EC_POINT *ptT3 = nullptr; + EC_POINT *ptPk = nullptr; + EC_POINT *ptKi = nullptr; + EC_POINT *ptL = nullptr; + EC_POINT *ptR = nullptr; uint8_t tempData[66]; // hold raw point data to hash uint256 commitHash; @@ -532,11 +536,7 @@ int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, c ssCommitHash << txnHash; // zero sum - if (!bnSum || !(BN_zero(bnSum))) - { - LogPrintf("%s: BN_zero failed.\n", __func__); - rv = 1; goto End; - } + BN_zero(bnSum); if ( !(ptT1 = EC_POINT_new(ecGrp)) || !(ptT2 = EC_POINT_new(ecGrp)) @@ -576,14 +576,14 @@ int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, c } // ptT1 = ci * Pi - if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnC, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, nullptr, ptPk, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT2 = ri * G - if (!EC_POINT_mul(ecGrp, ptT2, bnR, NULL, NULL, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT2, bnR, nullptr, nullptr, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -604,14 +604,14 @@ int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, c } // ptT1 = k1 * I - if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, nullptr, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT2 = k2 * ptT3 - if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnR, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT2, nullptr, ptT3, bnR, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -686,7 +686,7 @@ int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, c } -int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS) +int generateRingSignatureAB(const data_chunk &keyImage, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS) { // https://bitcointalk.org/index.php?topic=972541.msg10619684 @@ -747,12 +747,12 @@ int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSiz BIGNUM *bnC = BN_CTX_get(bnCtx); BIGNUM *bnCj = BN_CTX_get(bnCtx); BIGNUM *bnA = BN_CTX_get(bnCtx); - EC_POINT *ptKi = NULL; - EC_POINT *ptPk = NULL; - EC_POINT *ptT1 = NULL; - EC_POINT *ptT2 = NULL; - EC_POINT *ptT3 = NULL; - EC_POINT *ptT4 = NULL; + EC_POINT *ptKi = nullptr; + EC_POINT *ptPk = nullptr; + EC_POINT *ptT1 = nullptr; + EC_POINT *ptT2 = nullptr; + EC_POINT *ptT3 = nullptr; + EC_POINT *ptT4 = nullptr; if (!(ptKi = EC_POINT_new(ecGrp)) ||!(ptPk = EC_POINT_new(ecGrp)) @@ -778,7 +778,7 @@ int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSiz } // ptT1 = alpha * G - if (!EC_POINT_mul(ecGrp, ptT1, bnA, NULL, NULL, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, bnA, nullptr, nullptr, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -796,7 +796,7 @@ int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSiz // ptT2 = alpha * H(P_j) // ptT2 = alpha * ptT3 - if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnA, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT2, nullptr, ptT3, bnA, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -886,14 +886,14 @@ int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSiz } // ptT3 = s_{j+1}*H(P_{j+1}) - if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT3, nullptr, ptT2, bnS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT4 = c_{j+1}*I_j - if (!EC_POINT_mul(ecGrp, ptT4, NULL, ptKi, bnC, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT4, nullptr, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -961,7 +961,7 @@ int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSiz } -int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS) +int verifyRingSignatureAB(const data_chunk &keyImage, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS) { // https://bitcointalk.org/index.php?topic=972541.msg10619684 @@ -995,16 +995,18 @@ int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, BIGNUM *bnC1 = BN_CTX_get(bnCtx); BIGNUM *bnT = BN_CTX_get(bnCtx); BIGNUM *bnS = BN_CTX_get(bnCtx); - EC_POINT *ptKi = NULL; - EC_POINT *ptT1 = NULL; - EC_POINT *ptT2 = NULL; - EC_POINT *ptT3 = NULL; - EC_POINT *ptPk = NULL; + EC_POINT *ptKi = nullptr; + EC_POINT *ptT1 = nullptr; + EC_POINT *ptT2 = nullptr; + EC_POINT *ptT3 = nullptr; + EC_POINT *ptT4 = nullptr; + EC_POINT *ptPk = nullptr; if (!(ptKi = EC_POINT_new(ecGrp)) ||!(ptT1 = EC_POINT_new(ecGrp)) ||!(ptT2 = EC_POINT_new(ecGrp)) ||!(ptT3 = EC_POINT_new(ecGrp)) + ||!(ptT4 = EC_POINT_new(ecGrp)) ||!(ptPk = EC_POINT_new(ecGrp))) { LogPrintf("%s: EC_POINT_new failed.\n", __func__); @@ -1016,6 +1018,14 @@ int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, &&(rv = errorN(1, "%s: extract ptKi failed.", __func__))) goto End; + // test ECC validity with: keyimage * order == infinity/identity + if (!EC_POINT_mul(ecGrp, ptT4, nullptr, ptKi, bnOrder, bnCtx) + &&(rv = errorN(1, "%s: EC_POINT_mul failed.\n", __func__))) + goto End; + if (!EC_POINT_is_at_infinity(ecGrp, ptT4) + &&(rv = errorN(1, "%s: keyImage not valid (ptKi * bnOrder != infinity).\n", __func__))) + goto End; + if (!bnC1 || !BN_bin2bn(&sigC[0], EC_SECRET_SIZE, bnC1)) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); @@ -1066,14 +1076,14 @@ int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, } // ptT3 = s_i*ptT2 - if (!EC_POINT_mul(ecGrp, ptT3, NULL, ptT2, bnS, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT3, nullptr, ptT2, bnS, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; } // ptT1 = c_i*I_j - if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx)) + if (!EC_POINT_mul(ecGrp, ptT1, nullptr, ptKi, bnC, bnCtx)) { LogPrintf("%s: EC_POINT_mul failed.\n", __func__); rv = 1; goto End; @@ -1127,6 +1137,7 @@ int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, EC_POINT_free(ptT1); EC_POINT_free(ptT2); EC_POINT_free(ptT3); + EC_POINT_free(ptT4); EC_POINT_free(ptPk); return rv; diff --git a/src/ringsig.h b/src/ringsig.h index 070b8ef7c0..e4401408ab 100644 --- a/src/ringsig.h +++ b/src/ringsig.h @@ -1,9 +1,12 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT -#ifndef SDC_RINGSIG_H -#define SDC_RINGSIG_H +#ifndef SPEC_RINGSIG_H +#define SPEC_RINGSIG_H #include "stealth.h" #include "state.h" @@ -20,8 +23,7 @@ enum ringsigType const uint32_t MIN_ANON_OUT_SIZE = 1 + 1 + 1 + 33 + 1 + 33; // OP_RETURN ANON_TOKEN lenPk pkTo lenR R [lenEnarr enarr] const uint32_t MIN_ANON_IN_SIZE = 2 + (33 + 32 + 32); // 2byte marker (cpubkey + sigc + sigr) const uint32_t MAX_ANON_NARRATION_SIZE = 48; -const uint32_t MIN_RING_SIZE = 3; -const uint32_t MAX_RING_SIZE_OLD = 200; +const uint32_t MIN_RING_SIZE = 10; const uint32_t MAX_RING_SIZE = 32; // already overkill const int MIN_ANON_SPEND_DEPTH = 10; @@ -32,18 +34,18 @@ const int ANON_TXN_VERSION = 1000; int initialiseRingSigs(); int finaliseRingSigs(); -int splitAmount(int64_t nValue, std::vector &vOut); +int splitAmount(int64_t nValue, std::vector &vOut, int64_t maxAnonOutput = nMaxAnonOutput); -int getOldKeyImage(CPubKey &pubkey, ec_point &keyImage); +int getOldKeyImage(const CPubKey &pubkey, ec_point &keyImage); -int generateKeyImage(ec_point &publicKey, ec_secret secret, ec_point &keyImage); +int generateKeyImage(const ec_point &publicKey, ec_secret secret, ec_point &keyImage); -int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr); -int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr); +int generateRingSignature(const data_chunk &keyImage, const uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr); +int verifyRingSignature(const data_chunk &keyImage, const uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr); -int generateRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS); -int verifyRingSignatureAB(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS); +int generateRingSignatureAB(const data_chunk &keyImage, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, data_chunk &sigC, uint8_t *pSigS); +int verifyRingSignatureAB(const data_chunk &keyImage, int nRingSize, const uint8_t *pPubkeys, const data_chunk &sigC, const uint8_t *pSigS); -#endif // SDC_RINGSIG_H +#endif // SPEC_RINGSIG_H diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 0df11e976f..d45e200abf 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -1,870 +1,56 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2018-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT -#include "main.h" -#include "rpcserver.h" -#include "init.h" -#include "txdb.h" -#include "kernel.h" -#include "checkpoints.h" -#include +#ifndef ALIAS_INTERFACES_HANDLER_H +#define ALIAS_INTERFACES_HANDLER_H +#include +#include -using namespace json_spirit; -using namespace std; +namespace interfaces { -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); +//! Generic interface for managing an event handler or callback function +//! registered with another interface. Has a single disconnect method to cancel +//! the registration and prevent any future notifications. +class Handler { +public: + virtual ~Handler() = default; -double BitsToDouble(unsigned int nBits) -{ - // Floating point number that is a multiple of the minimum difficulty, - // minimum difficulty = 1.0. - int nShift = (nBits >> 24) & 0xff; + //! Disconnect the handler + virtual void disconnect() = 0; +}; - double dDiff = (double)0x0000ffff / (double)(nBits & 0x00ffffff); +//! Return handler wrapping a cleanup function +std::unique_ptr MakeCleanupHandler(std::function cleanup); - while (nShift < 29) - { - dDiff *= 256.0; - nShift++; - } - while (nShift > 29) - { - dDiff /= 256.0; - nShift--; - } - - return dDiff; -} - -double GetDifficulty(const CBlockIndex* blockindex) -{ - if (blockindex == NULL) - { - if (pindexBest == NULL) - return 1.0; - else - blockindex = GetLastBlockIndex(pindexBest, false); - }; - - return BitsToDouble(blockindex->nBits); -} - -double GetHeaderDifficulty(const CBlockThinIndex* blockindex) -{ - if (blockindex == NULL) - { - if (pindexBest == NULL) - return 1.0; - else - blockindex = GetLastBlockThinIndex(pindexBestHeader, false); - }; - - return BitsToDouble(blockindex->nBits); -} - - - -double GetPoWMHashPS() -{ - if (pindexBest->nHeight >= Params().LastPOWBlock()) - return 0; +//! Simple handler implementation that calls cleanup function on disconnect +class CleanupHandler : public Handler { +public: + explicit CleanupHandler(std::function cleanup) : m_cleanup(std::move(cleanup)) {} - int nPoWInterval = 72; - int64_t nTargetSpacingWorkMin = 30, nTargetSpacingWork = 30; - - CBlockIndex* pindex = pindexGenesisBlock; - CBlockIndex* pindexPrevWork = pindexGenesisBlock; - - while (pindex) - { - if (pindex->IsProofOfWork()) - { - int64_t nActualSpacingWork = pindex->GetBlockTime() - pindexPrevWork->GetBlockTime(); - nTargetSpacingWork = ((nPoWInterval - 1) * nTargetSpacingWork + nActualSpacingWork + nActualSpacingWork) / (nPoWInterval + 1); - nTargetSpacingWork = max(nTargetSpacingWork, nTargetSpacingWorkMin); - pindexPrevWork = pindex; + ~CleanupHandler() override { + if (m_cleanup) { + m_cleanup(); } - - pindex = pindex->pnext; - } - - return GetDifficulty() * 4294.967296 / nTargetSpacingWork; -} - -double GetPoSKernelPS() -{ - int nPoSInterval = 72; - double dStakeKernelsTriedAvg = 0; - int nStakesHandled = 0, nStakesTime = 0; - - if (nNodeMode == NT_THIN) - { - CBlockThinIndex* pindex = pindexBestHeader;; - CBlockThinIndex* pindexPrevStake = NULL; - - while (pindex && nStakesHandled < nPoSInterval) - { - if (pindex->IsProofOfStake()) - { - if (pindexPrevStake) - { - dStakeKernelsTriedAvg += GetHeaderDifficulty(pindex) * 4294967296.0; - nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0; - nStakesHandled++; - }; - pindexPrevStake = pindex; - }; - - pindex = pindex->pprev; - }; - } else - { - CBlockIndex* pindex = pindexBest;; - CBlockIndex* pindexPrevStake = NULL; - - while (pindex && nStakesHandled < nPoSInterval) - { - if (pindex->IsProofOfStake()) - { - if (pindexPrevStake) - { - dStakeKernelsTriedAvg += GetDifficulty(pindex) * 4294967296.0; - nStakesTime += pindexPrevStake ? (pindexPrevStake->nTime - pindex->nTime) : 0; - nStakesHandled++; - } - pindexPrevStake = pindex; - } - - pindex = pindex->pprev; - } } - double result = 0; - - if (nStakesTime) - result = dStakeKernelsTriedAvg / nStakesTime; - - if (Params().IsProtocolV2(nBestHeight)) - result *= STAKE_TIMESTAMP_MASK + 1; - - return result; -} - -Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool fPrintTransactionDetail) -{ - Object result; - result.push_back(Pair("hash", block.GetHash().GetHex())); - CMerkleTx txGen(block.vtx[0]); - txGen.SetMerkleBranch(&block); - result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain())); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint))); - result.push_back(Pair("time", (int64_t)block.GetBlockTime())); - result.push_back(Pair("nonce", (uint64_t)block.nNonce)); - result.push_back(Pair("bits", HexBits(block.nBits))); - result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0'))); - result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0'))); - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - if (blockindex->pnext) - result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); - - result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": ""))); - result.push_back(Pair("proofhash", blockindex->hashProof.GetHex())); - result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit())); - result.push_back(Pair("modifier", strprintf("%016x", blockindex->nStakeModifier))); - result.push_back(Pair("modifierv2", blockindex->bnStakeModifierV2.GetHex())); - Array txinfo; - BOOST_FOREACH (const CTransaction& tx, block.vtx) - { - if (fPrintTransactionDetail) - { - Object entry; - - entry.push_back(Pair("txid", tx.GetHash().GetHex())); - TxToJSON(tx, 0, entry); - - txinfo.push_back(entry); + void disconnect() override { + if (m_cleanup) { + m_cleanup(); + m_cleanup = nullptr; } - else - txinfo.push_back(tx.GetHash().GetHex()); } - result.push_back(Pair("tx", txinfo)); - - if (block.IsProofOfStake()) - result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end()))); +private: + std::function m_cleanup; +}; - return result; +inline std::unique_ptr MakeCleanupHandler(std::function cleanup) { + return std::make_unique(std::move(cleanup)); } -Object blockHeaderToJSON(const CBlockThin& block, const CBlockThinIndex* blockindex) -{ - Object result; - result.push_back(Pair("hash", block.GetHash().GetHex())); - //CMerkleTx txGen(block.vtx[0]); - //txGen.SetMerkleBranch(&block); - //result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain())); - result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", blockindex->nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - //result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint))); - result.push_back(Pair("time", (int64_t)block.GetBlockTime())); - result.push_back(Pair("nonce", (uint64_t)block.nNonce)); - result.push_back(Pair("bits", HexBits(block.nBits))); - result.push_back(Pair("difficulty", GetHeaderDifficulty(blockindex))); - result.push_back(Pair("blocktrust", leftTrim(blockindex->GetBlockTrust().GetHex(), '0'))); - result.push_back(Pair("chaintrust", leftTrim(blockindex->nChainTrust.GetHex(), '0'))); - - if (blockindex->pprev) - result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); - if (blockindex->pnext) - result.push_back(Pair("nextblockhash", blockindex->pnext->GetBlockHash().GetHex())); - - result.push_back(Pair("flags", strprintf("%s%s", blockindex->IsProofOfStake()? "proof-of-stake" : "proof-of-work", blockindex->GeneratedStakeModifier()? " stake-modifier": ""))); - result.push_back(Pair("proofhash", blockindex->hashProof.GetHex())); - result.push_back(Pair("entropybit", (int)blockindex->GetStakeEntropyBit())); - result.push_back(Pair("modifier", strprintf("%016x", blockindex->nStakeModifier))); - //result.push_back(Pair("modifierv2", blockindex->bnStakeModifierV2.GetHex())); - //if (block.IsProofOfStake()) - // result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end()))); - - return result; -} - - -Object diskBlockThinIndexToJSON(CDiskBlockThinIndex& diskBlock) -{ - CBlock block = diskBlock.GetBlock(); - - Object result; - result.push_back(Pair("hash", block.GetHash().GetHex())); - //CMerkleTx txGen(block.vtx[0]); - //txGen.SetMerkleBranch(&block); - //result.push_back(Pair("confirmations", (int)txGen.GetDepthInMainChain())); - //result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); - result.push_back(Pair("height", diskBlock.nHeight)); - result.push_back(Pair("version", block.nVersion)); - result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex())); - //result.push_back(Pair("mint", ValueFromAmount(blockindex->nMint))); - result.push_back(Pair("time", (int64_t)block.GetBlockTime())); - result.push_back(Pair("nonce", (uint64_t)block.nNonce)); - result.push_back(Pair("bits", HexBits(block.nBits))); - result.push_back(Pair("difficulty", BitsToDouble(diskBlock.nBits))); - result.push_back(Pair("blocktrust", leftTrim(diskBlock.GetBlockTrust().GetHex(), '0'))); - result.push_back(Pair("chaintrust", leftTrim(diskBlock.nChainTrust.GetHex(), '0'))); - - result.push_back(Pair("previousblockhash", diskBlock.hashPrev.GetHex())); - result.push_back(Pair("nextblockhash", diskBlock.hashNext.GetHex())); - - - result.push_back(Pair("flags", strprintf("%s%s", diskBlock.IsProofOfStake()? "proof-of-stake" : "proof-of-work", diskBlock.GeneratedStakeModifier()? " stake-modifier": ""))); - result.push_back(Pair("proofhash", diskBlock.hashProof.GetHex())); - result.push_back(Pair("entropybit", (int)diskBlock.GetStakeEntropyBit())); - result.push_back(Pair("modifier", strprintf("%016x", diskBlock.nStakeModifier))); - //result.push_back(Pair("modifierv2", diskBlock.bnStakeModifierV2.GetHex())); - //result.push_back(Pair("modifierchecksum", strprintf("%08x", diskBlock.nStakeModifierChecksum))); - - //if (block.IsProofOfStake()) - // result.push_back(Pair("signature", HexStr(block.vchBlockSig.begin(), block.vchBlockSig.end()))); - - return result; -} - -Value getbestblockhash(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getbestblockhash\n" - "Returns the hash of the best block in the longest block chain."); - - return hashBestChain.GetHex(); -} +} // namespace interfaces -Value getblockcount(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getblockcount\n" - "Returns the number of blocks in the longest block chain."); - - return nBestHeight; -} - - -Value getdifficulty(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getdifficulty\n" - "Returns the difficulty as a multiple of the minimum difficulty."); - - Object obj; - obj.push_back(Pair("proof-of-work", GetDifficulty())); - obj.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(pindexBest, true)))); - obj.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); - return obj; -} - - -Value settxfee(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE) - throw runtime_error( - "settxfee \n" - " is a real and is rounded to the nearest 0.01"); - - nTransactionFee = AmountFromValue(params[0]); - nTransactionFee = (nTransactionFee / CENT) * CENT; // round to cent - - return true; -} - -Value getrawmempool(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getrawmempool\n" - "Returns all transaction ids in memory pool."); - - vector vtxid; - mempool.queryHashes(vtxid); - - Array a; - BOOST_FOREACH(const uint256& hash, vtxid) - a.push_back(hash.ToString()); - - return a; -} - -Value getblockhash(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "getblockhash \n" - "Returns hash of block in best-block-chain at ."); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > nBestHeight) - throw runtime_error("Block number out of range."); - - CBlockIndex* pblockindex = FindBlockByHeight(nHeight); - return pblockindex->phashBlock->GetHex(); -} - -Value getblock(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblock [txinfo]\n" - "txinfo optional to print more detailed tx info\n" - "Returns details of a block with given block-hash."); - - std::string strHash = params[0].get_str(); - uint256 hash(strHash); - - if (nNodeMode == NT_THIN) - { - CDiskBlockThinIndex diskindex; - CTxDB txdb("r"); - if (txdb.ReadBlockThinIndex(hash, diskindex)) - return diskBlockThinIndexToJSON(diskindex); - - throw runtime_error("Read header from db failed.\n"); - }; - - if (mapBlockIndex.count(hash) == 0) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hash]; - block.ReadFromDisk(pblockindex, true); - - return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); -} - -Value getblockbynumber(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getblockbynumber [txinfo]\n" - "txinfo optional to print more detailed tx info\n" - "Returns details of a block with given block-number."); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > nBestHeight) - throw runtime_error("Block number out of range."); - - if (nNodeMode == NT_THIN) - { - if (!fThinFullIndex - && pindexRear - && nHeight < pindexRear->nHeight) - { - CDiskBlockThinIndex diskindex; - uint256 hashPrev = pindexRear->GetBlockHash(); - - // -- find closest checkpoint - Checkpoints::MapCheckpoints& checkpoints = (fTestNet ? Checkpoints::mapCheckpointsTestnet : Checkpoints::mapCheckpoints); - Checkpoints::MapCheckpoints::reverse_iterator rit; - - for (rit = checkpoints.rbegin(); rit != checkpoints.rend(); ++rit) - { - if (rit->first < nHeight) - break; - hashPrev = rit->second; - }; - - CTxDB txdb("r"); - while (hashPrev != 0) - { - if (!txdb.ReadBlockThinIndex(hashPrev, diskindex)) - throw runtime_error("Read header from db failed.\n"); - - if (diskindex.nHeight == nHeightFilteredNeeded) - return diskBlockThinIndexToJSON(diskindex); - - hashPrev = diskindex.hashPrev; - }; - - throw runtime_error("block not found."); - }; - - - CBlockThin block; - std::map::iterator mi = mapBlockThinIndex.find(hashBestChain); - if (mi != mapBlockThinIndex.end()) - { - CBlockThinIndex* pblockindex = mi->second; - while (pblockindex->pprev && pblockindex->nHeight > nHeight) - pblockindex = pblockindex->pprev; - - if (nHeight != pblockindex->nHeight) - { - throw runtime_error("block not in chain index."); - } - return blockHeaderToJSON(block, pblockindex); - } else - { - throw runtime_error("hashBestChain not in chain index."); - } - - - } - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; - while (pblockindex->nHeight > nHeight) - pblockindex = pblockindex->pprev; - - uint256 hash = *pblockindex->phashBlock; - - pblockindex = mapBlockIndex[hash]; - block.ReadFromDisk(pblockindex, true); - - return blockToJSON(block, pblockindex, params.size() > 1 ? params[1].get_bool() : false); -} - -Value setbestblockbyheight(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "setbestblockbyheight \n" - "Sets the tip of the chain th block at ."); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > nBestHeight) - throw runtime_error("Block height out of range."); - - if (nNodeMode == NT_THIN) - { - throw runtime_error("Must be in full mode."); - }; - - CBlock block; - CBlockIndex* pblockindex = mapBlockIndex[hashBestChain]; - while (pblockindex->nHeight > nHeight) - pblockindex = pblockindex->pprev; - - uint256 hash = *pblockindex->phashBlock; - - pblockindex = mapBlockIndex[hash]; - block.ReadFromDisk(pblockindex, true); - - - Object result; - - CTxDB txdb; - { - LOCK(cs_main); - - if (!block.SetBestChain(txdb, pblockindex)) - result.push_back(Pair("result", "failure")); - else - result.push_back(Pair("result", "success")); - - }; - - return result; -} - -Value rewindchain(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "rewindchain \n" - "Remove blocks from the chain."); - - int nNumber = params[0].get_int(); - if (nNumber < 0 || nNumber > nBestHeight) - throw runtime_error("Block number out of range."); - - if (nNodeMode == NT_THIN) - { - throw runtime_error("Must be in full mode."); - }; - - Object result; - int nRemoved = 0; - - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - - uint32_t nFileRet = 0; - - uint8_t buffer[512]; - - LogPrintf("rewindchain %d\n", nNumber); - - void* nFind; - - for (int i = 0; i < nNumber; ++i) - { - memset(buffer, 0, sizeof(buffer)); - - FILE* fp = AppendBlockFile(false, nFileRet, "r+b"); - if (!fp) - { - LogPrintf("AppendBlockFile failed.\n"); - break; - }; - - errno = 0; - if (fseek(fp, 0, SEEK_END) != 0) - { - LogPrintf("fseek failed: %s\n", strerror(errno)); - break; - }; - - long int fpos = ftell(fp); - - if (fpos == -1) - { - LogPrintf("ftell failed: %s\n", strerror(errno)); - break; - }; - - long int foundPos = -1; - long int readSize = sizeof(buffer) / 2; - while (fpos > 0) - { - if (fpos < (long int)sizeof(buffer) / 2) - readSize = fpos; - - memcpy(buffer+readSize, buffer, readSize); // move last read data (incase token crosses a boundary) - fpos -= readSize; - - if (fseek(fp, fpos, SEEK_SET) != 0) - { - LogPrintf("fseek failed: %s\n", strerror(errno)); - break; - }; - - errno = 0; - if (fread(buffer, sizeof(uint8_t), readSize, fp) != (size_t)readSize) - { - if (errno != 0) - LogPrintf("fread failed: %s\n", strerror(errno)); - else - LogPrintf("End of file.\n"); - break; - }; - - uint32_t findPos = sizeof(buffer); - while (findPos > MESSAGE_START_SIZE) - { - if ((nFind = sdc::memrchr(buffer, Params().MessageStart()[0], findPos-MESSAGE_START_SIZE))) - { - if (memcmp(nFind, Params().MessageStart(), MESSAGE_START_SIZE) == 0) - { - foundPos = ((uint8_t*)nFind - buffer) + MESSAGE_START_SIZE; - break; - } else - { - findPos = ((uint8_t*)nFind - buffer); - // -- step over matched char that wasn't pchMessageStart - if (findPos > 0) // prevent findPos < 0 (unsigned) - findPos--; - }; - } else - { - break; // pchMessageStart[0] not found in buffer - }; - }; - - if (foundPos > -1) - break; - }; - - LogPrintf("fpos %d, foundPos %d.\n", fpos, foundPos); - - if (foundPos < 0) - { - LogPrintf("block start not found.\n"); - fclose(fp); - break; - }; - - CAutoFile blkdat(fp, SER_DISK, CLIENT_VERSION); - - if (fseek(blkdat, fpos+foundPos, SEEK_SET) != 0) - { - LogPrintf("fseek blkdat failed: %s\n", strerror(errno)); - break; - }; - - unsigned int nSize; - blkdat >> nSize; - LogPrintf("nSize %u .\n", nSize); - - if (nSize < 1 || nSize > MAX_BLOCK_SIZE) - { - LogPrintf("block size error %u\n", nSize); - - }; - - CBlock block; - blkdat >> block; - uint256 hashblock = block.GetHash(); - LogPrintf("hashblock %s .\n", hashblock.ToString().c_str()); - - std::map::iterator mi = mapBlockIndex.find(hashblock); - if (mi != mapBlockIndex.end() && (*mi).second) - { - LogPrintf("block is in main chain.\n"); - - if (!mi->second->pprev) - { - LogPrintf("! mi->second.pprev\n"); - } else - { - { - CBlock blockPrev; // strange way SetBestChain works, TODO: does it need the full block? - if (!blockPrev.ReadFromDisk(mi->second->pprev)) - { - LogPrintf("blockPrev.ReadFromDisk failed %s.\n", mi->second->pprev->GetBlockHash().ToString().c_str()); - //break; - }; - - CTxDB txdb; - if (!blockPrev.SetBestChain(txdb, mi->second->pprev)) - { - LogPrintf("SetBestChain failed.\n"); - }; - } - mi->second->pprev->pnext = NULL; - }; - - delete mi->second; - mapBlockIndex.erase(mi); - }; - - std::map::iterator miOph = mapOrphanBlocks.find(hashblock); - if (miOph != mapOrphanBlocks.end()) - { - LogPrintf("block is an orphan.\n"); - mapOrphanBlocks.erase(miOph); - }; - - CTxDB txdb; - for (vector::iterator it = block.vtx.begin(); it != block.vtx.end(); ++it) - { - LogPrintf("EraseTxIndex().\n"); - txdb.EraseTxIndex(*it); - }; - - LogPrintf("EraseBlockIndex().\n"); - txdb.EraseBlockIndex(hashblock); - - errno = 0; - if (ftruncate(fileno(fp), fpos+foundPos-MESSAGE_START_SIZE) != 0) - { - LogPrintf("ftruncate failed: %s\n", strerror(errno)); - }; - - LogPrintf("hashBestChain %s, nBestHeight %d\n", hashBestChain.ToString().c_str(), nBestHeight); - - //fclose(fp); // ~CAutoFile() will close the file - nRemoved++; - }; - } - - - result.push_back(Pair("no. blocks removed", itostr(nRemoved))); - - result.push_back(Pair("hashBestChain", hashBestChain.ToString())); - result.push_back(Pair("nBestHeight", itostr(nBestHeight))); - - // -- need restart, setStakeSeen etc - if (nRemoved > 0) - result.push_back(Pair("Please restart shadowcoin", "")); - - if (nRemoved == nNumber) - result.push_back(Pair("result", "success")); - else - result.push_back(Pair("result", "failure")); - return result; -} - - -Value nextorphan(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw runtime_error( - "nextorphan [connecthash]\n" - "displays orphan blocks that connect to current best block.\n" - "if [connecthash] is set try to connect that block (must be nextorphan).\n"); - - if (nNodeMode == NT_THIN) - { - throw runtime_error("Must be in full mode."); - }; - - if (!pindexBest) - throw runtime_error("No best index."); - - throw runtime_error("Not working."); // too few blocks in mapOrphan!? - - Object result; - - std::map mapNextOrphanBlocks; - - LOCK(cs_main); - - //mapOrphanBlocks.clear(); - uint256 besthash = *pindexBest->phashBlock; - std::map::iterator it; - for (it = mapOrphanBlocks.begin(); it != mapOrphanBlocks.end(); ++it) - { - if (it->second->hashPrev == besthash) - { - mapNextOrphanBlocks[it->first] = it->second; - }; - }; - - if (params.size() > 0) - { - - } else - { - std::map::iterator it; - for (it = mapNextOrphanBlocks.begin(); it != mapNextOrphanBlocks.end(); ++it) - { - result.push_back(Pair("block", it->first.ToString())); - }; - }; - - result.push_back(Pair("result", "done")); - return result; -} - -// ppcoin: get information of sync-checkpoint -Value getcheckpoint(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getcheckpoint\n" - "Show info of synchronized checkpoint.\n"); - - Object result; - const CBlockIndex* pindexCheckpoint = Checkpoints::AutoSelectSyncCheckpoint(); - - result.push_back(Pair("synccheckpoint", pindexCheckpoint->GetBlockHash().ToString().c_str())); - result.push_back(Pair("height", pindexCheckpoint->nHeight)); - result.push_back(Pair("timestamp", DateTimeStrFormat(pindexCheckpoint->GetBlockTime()).c_str())); - - result.push_back(Pair("policy", "rolling")); - - return result; -} - - - -Value thinscanmerkleblocks(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "thinscanmerkleblocks \n" - "Request and rescan merkle blocks from peers starting from ."); - - int nHeight = params[0].get_int(); - if (nHeight < 0 || nHeight > nBestHeight) - throw runtime_error("Block height out of range."); - - if (nNodeMode != NT_THIN) - throw runtime_error("Must be in thin mode."); - - if (nNodeState == NS_GET_FILTERED_BLOCKS) - throw runtime_error("Wait for current merkle block scan to complete."); - - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - pwalletMain->nLastFilteredHeight = nHeight; - nHeightFilteredNeeded = nHeight; - CWalletDB walletdb(pwalletMain->strWalletFile); - walletdb.WriteLastFilteredHeight(nHeight); - - ChangeNodeState(NS_GET_FILTERED_BLOCKS, false); - } - - Object result; - result.push_back(Pair("result", "Success.")); - result.push_back(Pair("startheight", nHeight)); - return result; -} - -Value thinforcestate(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "thinforcestate \n" - "force into state .\n" - "2 get headers, 3 get filtered blocks, 4 ready"); - - if (nNodeMode != NT_THIN) - throw runtime_error("Must be in thin mode."); - - int nState = params[0].get_int(); - if (nState <= NS_STARTUP || nState >= NS_UNKNOWN) - throw runtime_error("unknown state."); - - - - Object result; - if (ChangeNodeState(nState)) - result.push_back(Pair("result", "Success.")); - else - result.push_back(Pair("result", "Failed.")); - - return result; -} +#endif // ALIAS_INTERFACES_HANDLER_H diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 410426db3b..a8e92896c6 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -1,14 +1,17 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include #include "rpcclient.h" #include "rpcprotocol.h" #include "util.h" -#include "ui_interface.h" +#include "interface.h" #include "chainparams.h" // for Params().RPCPort() #include @@ -16,11 +19,10 @@ #include #include #include -#include -#include -#include +#include #include #include +#include "util/fs.h" #include #include #include "json/json_spirit_writer_template.h" @@ -41,7 +43,12 @@ Object CallRPC(const string& strMethod, const Array& params) // Connect to localhost bool fUseSSL = GetBoolArg("-rpcssl", false); asio::io_service io_service; - ssl::context context(io_service, ssl::context::sslv23); + ssl::context context( +#if BOOST_VERSION <= 104800 + io_service, +#endif + ssl::context::sslv23 + ); context.set_options(ssl::context::no_sslv2); asio::ssl::stream sslStream(io_service, context); SSLIOStreamDevice d(sslStream, fUseSSL); @@ -133,7 +140,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listsinceblock", 1 }, { "clearwallettransactions", 0}, { "scanforalltxns", 0 }, - { "scanforstealthtxns", 0 }, { "sendalert", 2 }, { "sendalert", 3 }, { "sendalert", 4 }, @@ -156,14 +162,13 @@ static const CRPCConvertParam vRPCConvertParams[] = { "signrawtransaction", 1}, { "signrawtransaction", 2}, { "keypoolrefill", 0 }, - { "sendtostealthaddress", 1 }, - { "sendsdctoanon", 1 }, - { "sendanontoanon", 1 }, - { "sendanontoanon", 2 }, - { "sendanontosdc", 1 }, - { "sendanontosdc", 2 }, - { "estimateanonfee", 0 }, - { "estimateanonfee", 1 }, + { "sendpublictoprivate", 1 }, + { "sendprivate", 1 }, + { "sendprivate", 2 }, + { "sendprivatetopublic", 1 }, + { "sendprivatetopublic", 2 }, + { "estimateprivatefee", 0 }, + { "estimateprivatefee", 1 }, { "thinscanmerkleblocks", 0 }, { "thinforcestate", 0 }, { "importprivkey", 2 }, @@ -171,6 +176,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "checkkernel", 0 }, { "checkkernel", 1 }, { "submitblock", 1 }, + { "gettxout", 1 }, + { "gettxout", 2 }, }; class CRPCConvertTable @@ -199,14 +206,13 @@ CRPCConvertTable::CRPCConvertTable() static CRPCConvertTable rpcCvtTable; -// Convert strings to command-specific RPC representation + // Convert strings to command-specific RPC representation Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams) { Array params; for (unsigned int idx = 0; idx < strParams.size(); idx++) { const std::string& strVal = strParams[idx]; - // insert string value directly if (!rpcCvtTable.convert(strMethod, idx)) { params.push_back(strVal); @@ -280,7 +286,7 @@ int CommandLineRPC(int argc, char *argv[]) nRet = 87; } catch (...) { - PrintException(NULL, "CommandLineRPC()"); + PrintException(nullptr, "CommandLineRPC()"); } if (strPrint != "") diff --git a/src/rpcclient.h b/src/rpcclient.h index f3ea56c25b..66cd2d602b 100644 --- a/src/rpcclient.h +++ b/src/rpcclient.h @@ -1,17 +1,24 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef _BITCOINRPC_CLIENT_H_ -#define _BITCOINRPC_CLIENT_H_ 1 +#ifndef BITCOIN_KERNEL_CONTEXT_H +#define BITCOIN_KERNEL_CONTEXT_H -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" +namespace kernel { +//! Context struct holding the kernel library's logically global state, and +//! passed to external libbitcoin_kernel functions which need access to this +//! state. The kernel library API is a work in progress, so state organization +//! and member list will evolve over time. +//! +//! State stored directly in this struct should be simple. More complex state +//! should be stored to std::unique_ptr members pointing to opaque types. +struct Context { + Context(); +}; +} // namespace kernel -int CommandLineRPC(int argc, char *argv[]); +#endif // BITCOIN_KERNEL_CONTEXT_H -json_spirit::Array RPCConvertValues(const std::string &strMethod, const std::vector &strParams); - -#endif diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 0a8243047a..85e7c429a7 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -1,13 +1,16 @@ -// Copyright (c) 2009-2012 Bitcoin Developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include #include #include "init.h" // for pwalletMain #include "rpcserver.h" -#include "ui_interface.h" +#include "interface.h" #include "base58.h" #include @@ -63,7 +66,7 @@ std::string static EncodeDumpTime(int64_t nTime) std::string static EncodeDumpString(const std::string &str) { std::stringstream ret; - BOOST_FOREACH(unsigned char c, str) + for (unsigned char c : str) { if (c <= 32 || c >= 128 || c == '%') { @@ -101,9 +104,9 @@ class CTxDump bool fSpent; CWalletTx* ptx; int nOut; - CTxDump(CWalletTx* ptx = NULL, int nOut = -1) + CTxDump(CWalletTx* ptx = nullptr, int nOut = -1) { - pindex = NULL; + pindex = nullptr; nValue = 0; fSpent = false; this->ptx = ptx; @@ -115,7 +118,7 @@ Value importprivkey(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 4) throw runtime_error( - "importprivkey [label] [rescan=true] [timestamp=1]\n" + "importprivkey [label] [rescan=true] [timestamp=1]\n" "Adds a private key (as returned by dumpprivkey) to your wallet."); string strSecret = params[0].get_str(); @@ -166,8 +169,6 @@ Value importprivkey(const Array& params, bool fHelp) } } - SecureMsgAddWalletAddresses(); - return Value::null; } @@ -259,8 +260,8 @@ Value dumpprivkey(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( - "dumpprivkey \n" - "Reveals the private key corresponding to ."); + "dumpprivkey \n" + "Reveals the private key corresponding to ."); EnsureWalletIsUnlocked(); @@ -282,7 +283,7 @@ Value dumpprivkey(const Array& params, bool fHelp) } else { if (!address.SetString(strAddress)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); if (!address.GetKeyID(keyID)) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); }; @@ -324,7 +325,7 @@ Value dumpwallet(const Array& params, bool fHelp) std::sort(vKeyBirth.begin(), vKeyBirth.end()); // produce output - file << strprintf("# Wallet dump created by ShadowCoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); + file << strprintf("# Wallet dump created by Alias %s (%s)\n", CLIENT_BUILD, CLIENT_DATE); file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime())); file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString()); file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime)); diff --git a/src/rpcextkey.cpp b/src/rpcextkey.cpp index 0fc4156c39..ea679ffc3d 100644 --- a/src/rpcextkey.cpp +++ b/src/rpcextkey.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2015 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "init.h" #include "main.h" @@ -9,6 +12,7 @@ #include "key.h" #include "extkey.h" #include "chainparams.h" +#include "chainparams_migration.h" #include "hash.h" #include "base58.h" @@ -35,76 +39,76 @@ int ExtractBip32InfoV(std::vector &vchKey, Object &keyInfo, std:: CExtKey58 ek58; CExtKeyPair vk; vk.DecodeV(&vchKey[4]); - + CChainParams::Base58Type typePk = CChainParams::EXT_PUBLIC_KEY; - if (memcmp(&vchKey[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0) - keyInfo.push_back(Pair("type", "Shadowcoin extended secret key")); + if (memcmp(&vchKey[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0) + keyInfo.push_back(Pair("type", "Alias extended secret key")); else - if (memcmp(&vchKey[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) + if (memcmp(&vchKey[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) { keyInfo.push_back(Pair("type", "Bitcoin extended secret key")); typePk = CChainParams::EXT_PUBLIC_KEY_BTC; } else keyInfo.push_back(Pair("type", "Unknown extended secret key")); - + keyInfo.push_back(Pair("version", strprintf("%02X", reversePlace(&vchKey[0])))); keyInfo.push_back(Pair("depth", strprintf("%u", vchKey[4]))); keyInfo.push_back(Pair("parent_fingerprint", strprintf("%08X", reversePlace(&vchKey[5])))); keyInfo.push_back(Pair("child_index", strprintf("%u", reversePlace(&vchKey[9])))); keyInfo.push_back(Pair("chain_code", strprintf("%s", HexStr(&vchKey[13], &vchKey[13+32])))); keyInfo.push_back(Pair("key", strprintf("%s", HexStr(&vchKey[46], &vchKey[46+32])))); - + // don't display raw secret ?? // TODO: add option - + CKey key; key.Set(&vchKey[46], true); keyInfo.push_back(Pair("privkey", strprintf("%s", CBitcoinSecret(key).ToString()))); CKeyID id = key.GetPubKey().GetID(); CBitcoinAddress addr; addr.Set(id, CChainParams::EXT_KEY_HASH); - + keyInfo.push_back(Pair("id", addr.ToString().c_str())); addr.Set(id); keyInfo.push_back(Pair("address", addr.ToString().c_str())); keyInfo.push_back(Pair("checksum", strprintf("%02X", reversePlace(&vchKey[78])))); - + ek58.SetKey(vk, typePk); keyInfo.push_back(Pair("ext_public_key", ek58.ToString())); - + return 0; }; int ExtractBip32InfoP(std::vector &vchKey, Object &keyInfo, std::string &sError) { CExtPubKey pk; - - if (memcmp(&vchKey[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0) - keyInfo.push_back(Pair("type", "Shadowcoin extended public key")); + + if (memcmp(&vchKey[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0) + keyInfo.push_back(Pair("type", "Alias extended public key")); else - if (memcmp(&vchKey[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) + if (memcmp(&vchKey[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) keyInfo.push_back(Pair("type", "Bitcoin extended public key")); else keyInfo.push_back(Pair("type", "Unknown extended public key")); - + keyInfo.push_back(Pair("version", strprintf("%02X", reversePlace(&vchKey[0])))); keyInfo.push_back(Pair("depth", strprintf("%u", vchKey[4]))); keyInfo.push_back(Pair("parent_fingerprint", strprintf("%08X", reversePlace(&vchKey[5])))); keyInfo.push_back(Pair("child_index", strprintf("%u", reversePlace(&vchKey[9])))); keyInfo.push_back(Pair("chain_code", strprintf("%s", HexStr(&vchKey[13], &vchKey[13+32])))); keyInfo.push_back(Pair("key", strprintf("%s", HexStr(&vchKey[45], &vchKey[45+33])))); - + CPubKey key; key.Set(&vchKey[45], &vchKey[78]); CKeyID id = key.GetID(); CBitcoinAddress addr; addr.Set(id, CChainParams::EXT_KEY_HASH); - + keyInfo.push_back(Pair("id", addr.ToString().c_str())); addr.Set(id); keyInfo.push_back(Pair("address", addr.ToString().c_str())); keyInfo.push_back(Pair("checksum", strprintf("%02X", reversePlace(&vchKey[78])))); - + return 0; }; @@ -112,13 +116,13 @@ int ExtKeyPathV(std::string &sPath, std::vector &vchKey, Object &keyInf { if (sPath.compare("info") == 0) return ExtractBip32InfoV(vchKey, keyInfo, sError); - + CExtKey vk; vk.Decode(&vchKey[4]); - + CExtKey vkOut; CExtKey vkWork = vk; - + std::vector vPath; int rv; if ((rv = ExtractExtKeyPath(sPath, vPath)) != 0) @@ -126,25 +130,25 @@ int ExtKeyPathV(std::string &sPath, std::vector &vchKey, Object &keyInf sError = ExtKeyGetString(rv); return 1; }; - - for (std::vector::iterator it = vPath.begin(); it != vPath.end(); ++it) + + for (uint32_t pathItem : vPath) { - if (*it == 0) + if (pathItem == 0) { vkOut = vkWork; } else - if (!vkWork.Derive(vkOut, *it)) + if (!vkWork.Derive(vkOut, pathItem)) { sError = "CExtKey Derive failed."; return 1; }; vkWork = vkOut; }; - + CBitcoinExtKey ekOut; ekOut.SetKey(vkOut); keyInfo.push_back(Pair("result", ekOut.ToString())); - + return 0; }; @@ -152,13 +156,13 @@ int ExtKeyPathP(std::string &sPath, std::vector &vchKey, Object &keyInf { if (sPath.compare("info") == 0) return ExtractBip32InfoP(vchKey, keyInfo, sError); - + CExtPubKey pk; pk.Decode(&vchKey[4]); - + CExtPubKey pkOut; CExtPubKey pkWork = pk; - + std::vector vPath; int rv; if ((rv = ExtractExtKeyPath(sPath, vPath)) != 0) @@ -166,44 +170,44 @@ int ExtKeyPathP(std::string &sPath, std::vector &vchKey, Object &keyInf sError = ExtKeyGetString(rv); return 1; }; - - for (std::vector::iterator it = vPath.begin(); it != vPath.end(); ++it) + + for (uint32_t pathItem : vPath) { - if (*it == 0) + if (pathItem == 0) { pkOut = pkWork; } else - if ((*it >> 31) == 1) + if ((pathItem >> 31) == 1) { sError = "Can't derive hardened keys from public ext key."; return 1; } else - if (!pkWork.Derive(pkOut, *it)) + if (!pkWork.Derive(pkOut, pathItem)) { sError = "CExtKey Derive failed."; return 1; }; pkWork = pkOut; }; - + CBitcoinExtPubKey ekOut; ekOut.SetKey(pkOut); keyInfo.push_back(Pair("result", ekOut.ToString())); - + return 0; }; int AccountInfo(CExtKeyAccount *pa, int nShowKeys, Object &obj, std::string &sError) { CExtKey58 eKey58; - + obj.push_back(Pair("type", "Account")); obj.push_back(Pair("active", pa->nFlags & EAF_ACTIVE ? "true" : "false")); obj.push_back(Pair("label", pa->sLabel)); - + if (pwalletMain->idDefaultAccount == pa->GetID()) obj.push_back(Pair("default_account", "true")); - + mapEKValue_t::iterator mi = pa->mapValue.find(EKVT_CREATED_AT); if (mi != pa->mapValue.end()) { @@ -211,21 +215,21 @@ int AccountInfo(CExtKeyAccount *pa, int nShowKeys, Object &obj, std::string &sEr GetCompressedInt64(mi->second, (uint64_t&)nCreatedAt); obj.push_back(Pair("created_at", nCreatedAt)); }; - + obj.push_back(Pair("id", pa->GetIDString58())); obj.push_back(Pair("has_secret", pa->nFlags & EAF_HAVE_SECRET ? "true" : "false")); - + CStoredExtKey *sekAccount = pa->ChainAccount(); if (!sekAccount) { obj.push_back(Pair("error", "chain account not set.")); return 0; }; - + CBitcoinAddress addr; addr.Set(pa->idMaster, CChainParams::EXT_KEY_HASH); obj.push_back(Pair("root_key_id", addr.ToString())); - + mi = sekAccount->mapValue.find(EKVT_PATH); if (mi != sekAccount->mapValue.end()) { @@ -241,13 +245,13 @@ int AccountInfo(CExtKeyAccount *pa, int nShowKeys, Object &obj, std::string &sEr eKey58.SetKeyV(sekAccount->kp); obj.push_back(Pair("evkey", eKey58.ToString())); }; - + if (nShowKeys > 0) { eKey58.SetKeyP(sekAccount->kp); obj.push_back(Pair("epkey", eKey58.ToString())); }; - + if (pa->nActiveExternal < pa->vExtKeys.size()) { CStoredExtKey *sekE = pa->vExtKeys[pa->nActiveExternal]; @@ -259,7 +263,7 @@ int AccountInfo(CExtKeyAccount *pa, int nShowKeys, Object &obj, std::string &sEr obj.push_back(Pair("num_derives_external", strprintf("%u", sekE->nGenerated))); obj.push_back(Pair("num_derives_external_h", strprintf("%u", sekE->nHGenerated))); }; - + if (pa->nActiveInternal < pa->vExtKeys.size()) { CStoredExtKey *sekI = pa->vExtKeys[pa->nActiveInternal]; @@ -271,14 +275,14 @@ int AccountInfo(CExtKeyAccount *pa, int nShowKeys, Object &obj, std::string &sEr obj.push_back(Pair("num_derives_internal", strprintf("%u", sekI->nGenerated))); obj.push_back(Pair("num_derives_internal_h", strprintf("%u", sekI->nHGenerated))); }; - + if (pa->nActiveStealth < pa->vExtKeys.size()) { CStoredExtKey *sekS = pa->vExtKeys[pa->nActiveStealth]; obj.push_back(Pair("num_derives_stealth", strprintf("%u", sekS->nGenerated))); obj.push_back(Pair("num_derives_stealth_h", strprintf("%u", sekS->nHGenerated))); }; - + return 0; }; @@ -291,23 +295,23 @@ int AccountInfo(CKeyID &keyId, int nShowKeys, Object &obj, std::string &sError) sError = "Unknown account."; return 1; }; - + CExtKeyAccount *pa = mi->second; - + return AccountInfo(pa, nShowKeys, obj, sError); }; int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, Object &obj, std::string &sError) { CExtKey58 eKey58; - + bool fBip44Root = false; obj.push_back(Pair("type", "Loose")); obj.push_back(Pair("active", sek.nFlags & EAF_ACTIVE ? "true" : "false")); obj.push_back(Pair("receive_on", sek.nFlags & EAF_RECEIVE_ON ? "true" : "false")); obj.push_back(Pair("encrypted", sek.nFlags & EAF_IS_CRYPTED ? "true" : "false")); obj.push_back(Pair("label", sek.sLabel)); - + if (reversePlace(&sek.kp.vchFingerprint[0]) == 0) { obj.push_back(Pair("path", "Root")); @@ -321,14 +325,14 @@ int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, obj.push_back(Pair("path", sPath)); }; }; - + mapEKValue_t::iterator mi = sek.mapValue.find(EKVT_KEY_TYPE); if (mi != sek.mapValue.end()) { uint8_t type = EKT_MAX_TYPES; if (mi->second.size() == 1) type = mi->second[0]; - + std::string sType; switch (type) { @@ -341,16 +345,16 @@ int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, }; obj.push_back(Pair("key_type", sType)); }; - + if (idMaster == idKey) obj.push_back(Pair("current_master", "true")); - + CBitcoinAddress addr; mi = sek.mapValue.find(EKVT_ROOT_ID); if (mi != sek.mapValue.end()) { CKeyID idRoot; - + if (GetCKeyID(mi->second, idRoot)) { addr.Set(idRoot, CChainParams::EXT_KEY_HASH); @@ -360,7 +364,7 @@ int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, obj.push_back(Pair("root_key_id", "malformed")); }; }; - + mi = sek.mapValue.find(EKVT_CREATED_AT); if (mi != sek.mapValue.end()) { @@ -368,11 +372,11 @@ int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, GetCompressedInt64(mi->second, (uint64_t&)nCreatedAt); obj.push_back(Pair("created_at", nCreatedAt)); }; - - + + addr.Set(idKey, CChainParams::EXT_KEY_HASH); obj.push_back(Pair("id", addr.ToString())); - + if (nShowKeys > 1 && pwalletMain->ExtKeyUnlock(&sek) == 0) { @@ -382,21 +386,21 @@ int KeyInfo(CKeyID &idMaster, CKeyID &idKey, CStoredExtKey &sek, int nShowKeys, eKey58.SetKeyV(sek.kp); obj.push_back(Pair("evkey", eKey58.ToString())); }; - + if (nShowKeys > 0) { if (fBip44Root) eKey58.SetKey(sek.kp, CChainParams::EXT_PUBLIC_KEY_BTC); else eKey58.SetKeyP(sek.kp); - + obj.push_back(Pair("epkey", eKey58.ToString())); }; - + obj.push_back(Pair("num_derives", strprintf("%u", sek.nGenerated))); obj.push_back(Pair("num_derives_hardened", strprintf("%u", sek.nHGenerated))); - - + + return 0; }; @@ -408,8 +412,8 @@ class ListExtCallback : public LoopExtKeyCallback nItems = 0; rvArray = arr; nShowKeys = _nShowKeys; - - + + if (pwalletMain && pwalletMain->pEkMaster) idMaster = pwalletMain->pEkMaster->GetID(); }; @@ -423,11 +427,11 @@ class ListExtCallback : public LoopExtKeyCallback obj.push_back(Pair("id", sek.GetIDString58())); obj.push_back(Pair("error", sError)); }; - + rvArray->push_back(obj); - + return 0; }; - + int ProcessAccount(CKeyID &id, CExtKeyAccount &sea) { nItems++; @@ -437,10 +441,11 @@ class ListExtCallback : public LoopExtKeyCallback obj.push_back(Pair("id", sea.GetIDString58())); obj.push_back(Pair("error", sError)); }; - + rvArray->push_back(obj); + return 0; }; - + std::string sError; int nItems; int nShowKeys; @@ -451,24 +456,24 @@ class ListExtCallback : public LoopExtKeyCallback int ListLooseExtKeys(int nShowKeys, Array &ret, size_t &nKeys) { ListExtCallback cbc(&ret, nShowKeys); - + if (0 != LoopExtKeysInDB(true, false, cbc)) return errorN(1, "LoopExtKeys failed."); - + nKeys = cbc.nItems; - + return 0; }; int ListAccountExtKeys(int nShowKeys, Array &ret, size_t &nKeys) { ListExtCallback cbc(&ret, nShowKeys); - + if (0 != LoopExtAccountsInDB(true, cbc)) return errorN(1, "LoopExtKeys failed."); - + nKeys = cbc.nItems; - + return 0; }; @@ -478,7 +483,7 @@ int ManageExtKey(CStoredExtKey &sek, std::string &sOptName, std::string &sOptVal { if (sOptValue.length() == 0) sek.sLabel = sOptValue; - + result.push_back(Pair("set_label", sek.sLabel)); } else if (sOptName == "active") @@ -490,7 +495,7 @@ int ManageExtKey(CStoredExtKey &sek, std::string &sOptName, std::string &sOptVal else sek.nFlags &= ~EAF_ACTIVE; }; - + result.push_back(Pair("set_active", sek.nFlags & EAF_ACTIVE ? "true" : "false")); } else if (sOptName == "receive_on") @@ -502,7 +507,7 @@ int ManageExtKey(CStoredExtKey &sek, std::string &sOptName, std::string &sOptVal else sek.nFlags &= ~EAF_RECEIVE_ON; }; - + result.push_back(Pair("receive_on", sek.nFlags & EAF_RECEIVE_ON ? "true" : "false")); } else { @@ -511,7 +516,7 @@ int ManageExtKey(CStoredExtKey &sek, std::string &sOptName, std::string &sOptVal result.push_back(Pair("active", sek.nFlags & EAF_ACTIVE ? "true" : "false")); result.push_back(Pair("receive_on", sek.nFlags & EAF_RECEIVE_ON ? "true" : "false")); }; - + return 0; }; @@ -521,7 +526,7 @@ int ManageExtAccount(CExtKeyAccount &sea, std::string &sOptName, std::string &sO { if (sOptValue.length() > 0) sea.sLabel = sOptValue; - + result.push_back(Pair("set_label", sea.sLabel)); } else if (sOptName == "active") @@ -533,7 +538,7 @@ int ManageExtAccount(CExtKeyAccount &sea, std::string &sOptName, std::string &sO else sea.nFlags &= ~EAF_ACTIVE; }; - + result.push_back(Pair("set_active", sea.nFlags & EAF_ACTIVE ? "true" : "false")); } else { @@ -541,7 +546,7 @@ int ManageExtAccount(CExtKeyAccount &sea, std::string &sOptName, std::string &sO result.push_back(Pair("label", sea.sLabel)); result.push_back(Pair("active", sea.nFlags & EAF_ACTIVE ? "true" : "false")); }; - + return 0; }; @@ -549,7 +554,7 @@ int ManageExtAccount(CExtKeyAccount &sea, std::string &sOptName, std::string &sO Value extkey(const Array ¶ms, bool fHelp) { static const char *help = "" - "extkey [info|list|account|gen|import|importAccount|setMaster|setDefaultAccount|deriveAccount|options]\n" + "extkey [info|list|account|gen|import|importAccount|setMaster|setDefaultAccount|deriveAccount|options]\n" "extkey [\"info\"] [key] [path]\n" "extkey list [show_secrets] - default\n" " List loose and account ext keys.\n" @@ -576,40 +581,40 @@ Value extkey(const Array ¶ms, bool fHelp) " Manage keys and accounts\n" "\n" ""; - - + + // default mode is list unless 1st parameter is a key - then mode is set to info - + // path: // master keys are hashed with an integer (child_index) to form child keys // each child key can spawn more keys - // payments etc are not send to keys derived from the master keys + // payments etc are not send to keys derived from the master keys // m - master key // m/0 - key0 (1st) key derived from m // m/1/2 key2 (3rd) key derived from key1 derived from m - + // hardened keys are keys with (child_index) > 2^31 // it's not possible to compute the next extended public key in the sequence from a hardened public key (still possible with a hardened private key) - + // this maintains privacy, you can give hardened public keys to customers // and they will not be able to compute/guess the key you give out to other customers // but will still be able to send payments to you on the 2^32 keys derived from the public key you provided - - + + // accounts to receive must be non-hardened // - locked wallets must be able to derive new keys as they receive - - + + if (fHelp || params.size() > 5) // defaults to info, will always take at least 1 parameter throw std::runtime_error(help); - + std::string mode = "list"; - + if (pwalletMain->IsLocked()) throw std::runtime_error("Wallet is locked."); - + std::string sInKey = ""; - + uint32_t nParamOffset = 0; if (params.size() > 0) { @@ -617,11 +622,11 @@ Value extkey(const Array ¶ms, bool fHelp) std::string st = " " + s + " "; // Note the spaces std::transform(st.begin(), st.end(), st.begin(), ::tolower); static const char *pmodes = " info list gen account import importaccount setmaster setdefaultaccount deriveaccount options "; - if (strstr(pmodes, st.c_str()) != NULL) + if (strstr(pmodes, st.c_str()) != nullptr) { st.erase(std::remove(st.begin(), st.end(), ' '), st.end()); mode = st; - + nParamOffset = 1; } else { @@ -629,19 +634,19 @@ Value extkey(const Array ¶ms, bool fHelp) mode = "info"; }; }; - + CBitcoinExtKey bvk; CBitcoinExtPubKey bpk; - + std::vector vchVersionIn; vchVersionIn.resize(4); - + Object result; - + if (mode == "info") { std::string sMode = "info"; // info lists details of bip32 key, m displays internal key - + if (sInKey.length() == 0) { if (params.size() > nParamOffset + 1) @@ -650,35 +655,35 @@ Value extkey(const Array ¶ms, bool fHelp) nParamOffset++; }; }; - + if (params.size() > nParamOffset + 1) sMode = params[nParamOffset+1].get_str(); - + Object keyInfo; std::vector vchOut; - + if (!DecodeBase58(sInKey.c_str(), vchOut)) throw std::runtime_error("DecodeBase58 failed."); - + if (!VerifyChecksum(vchOut)) throw std::runtime_error("VerifyChecksum failed."); - + size_t keyLen = vchOut.size(); std::string sError; - + if (keyLen != BIP32_KEY_LEN) throw std::runtime_error(strprintf("Unknown ext key length '%d'", keyLen)); - + const CChainParams &otherNet = TestNet() ? MainNetParams() : TestNetParams(); - - if (memcmp(&vchOut[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0 - || memcmp(&vchOut[0], &Params().Base58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) + + if (memcmp(&vchOut[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY)[0], 4) == 0 + || memcmp(&vchOut[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_SECRET_KEY_BTC)[0], 4) == 0) { if (ExtKeyPathV(sMode, vchOut, keyInfo, sError) != 0) throw std::runtime_error(strprintf("ExtKeyPathV failed %s.", sError.c_str())); } else - if (memcmp(&vchOut[0], &Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY)[0], 4) == 0 - || memcmp(&vchOut[0], &Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY_BTC)[0], 4) == 0) + if (memcmp(&vchOut[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_PUBLIC_KEY)[0], 4) == 0 + || memcmp(&vchOut[0], &ChainParamsMigration::GetBase58Prefix(CChainParams::EXT_PUBLIC_KEY_BTC)[0], 4) == 0) { if (ExtKeyPathP(sMode, vchOut, keyInfo, sError) != 0) throw std::runtime_error(strprintf("ExtKeyPathP failed %s.", sError.c_str())); @@ -693,38 +698,38 @@ Value extkey(const Array ¶ms, bool fHelp) { throw std::runtime_error(strprintf("Unknown prefix '%s'", sInKey.substr(0, 4))); }; - + result.push_back(Pair("key_info", keyInfo)); } else if (mode == "list") { Array ret; - + int nListFull = 0; // 0 id only, 1 id+pubkey, 2 id+pubkey+secret if (params.size() > nParamOffset) { std::string st = params[nParamOffset].get_str(); if (IsStringBoolPositive(st)) nListFull = 2; - + nParamOffset++; }; - + size_t nKeys = 0; - + { LOCK(pwalletMain->cs_wallet); ListLooseExtKeys(nListFull, ret, nKeys); ListAccountExtKeys(nListFull, ret, nKeys); } // cs_wallet - + if (nKeys) return ret; - + result.push_back(Pair("result", "No keys to list.")); - + //result.push_back(Pair("ext_keys", ret)); - + } else if (mode == "account") { @@ -734,22 +739,22 @@ Value extkey(const Array ¶ms, bool fHelp) nParamOffset++; } else throw std::runtime_error("Must specify ext key or id."); - + int nListFull = 0; // 0 id only, 1 id+pubkey, 2 id+pubkey+secret if (params.size() > nParamOffset) { std::string st = params[nParamOffset].get_str(); if (IsStringBoolPositive(st)) nListFull = 2; - + nParamOffset++; }; - + CKeyID keyId; CExtKey58 eKey58; CExtKeyPair ekp; CBitcoinAddress addr; - + if (addr.SetString(sInKey) && addr.IsValid(CChainParams::EXT_ACC_HASH) && addr.GetKeyID(keyId, CChainParams::EXT_ACC_HASH)) @@ -764,55 +769,55 @@ Value extkey(const Array ¶ms, bool fHelp) { throw std::runtime_error("Invalid key."); }; - - + + std::string sError; if (0 != AccountInfo(keyId, nListFull, result, sError)) throw std::runtime_error("AccountInfo failed: " + sError); - + } else if (mode == "gen") { // - make a new master key // from random or passphrase + int + seed string - + CExtKey newKey; - + CBitcoinExtKey b58Key; - + if (params.size() > 1) { std::string sPassphrase = params[1].get_str(); int32_t nHashes = 100; - std::string sSeed = "Shadow seed"; - + std::string sSeed = "Alias seed"; + // - generate from passphrase // allow generator string and nhashes to be specified // To allow importing of bip32 strings from other systems // Match bip32.org: bip32 gen "pass" 50000 "Bitcoin seed" - + if (params.size() > 2) { std::stringstream sstr(params[2].get_str()); - + sstr >> nHashes; if (!sstr) throw std::runtime_error("Invalid num hashes"); - + if (nHashes < 1) throw std::runtime_error("Num hashes must be more 1 or higher."); }; - + if (params.size() > 3) { sSeed = params[3].get_str(); }; - + if (params.size() > 4) throw std::runtime_error(help); - + pwalletMain->ExtKeyNew32(newKey, sPassphrase.c_str(), nHashes, sSeed.c_str()); - + result.push_back(Pair("warning", "If the same passphrase is used by another your privacy and coins will be compromised.\n" "It is recommended not to use this feature - if you must, pick very unique values for passphrase, num hashes and generator parameters.")); @@ -820,10 +825,10 @@ Value extkey(const Array ¶ms, bool fHelp) { pwalletMain->ExtKeyNew32(newKey); }; - + b58Key.SetKey(newKey); - - + + result.push_back(Pair("result", b58Key.ToString())); } else if (mode == "import") @@ -836,14 +841,14 @@ Value extkey(const Array ¶ms, bool fHelp) nParamOffset++; }; }; - + CStoredExtKey sek; if (params.size() > nParamOffset) { sek.sLabel = params[nParamOffset].get_str(); nParamOffset++; }; - + bool fBip44 = false; if (params.size() > nParamOffset) { @@ -852,7 +857,7 @@ Value extkey(const Array ¶ms, bool fHelp) fBip44 = true; nParamOffset++; }; - + bool fSaveBip44 = false; if (params.size() > nParamOffset) { @@ -861,10 +866,10 @@ Value extkey(const Array ¶ms, bool fHelp) fSaveBip44 = true; nParamOffset++; }; - + std::vector v; sek.mapValue[EKVT_CREATED_AT] = SetCompressedInt64(v, GetTime()); - + CExtKey58 eKey58; if (eKey58.Set58(sInKey.c_str()) == 0) { @@ -876,21 +881,21 @@ Value extkey(const Array ¶ms, bool fHelp) { if (!eKey58.IsValid(CChainParams::EXT_SECRET_KEY) && !eKey58.IsValid(CChainParams::EXT_PUBLIC_KEY_BTC)) - throw std::runtime_error("Import failed - Key must begin with Shadowcoin prefix."); + throw std::runtime_error("Import failed - Key must begin with Alias prefix."); }; - + sek.kp = eKey58.GetKey(); } else { throw std::runtime_error("Import failed - Invalid key."); }; - + { LOCK(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + int rv; if (0 != (rv = pwalletMain->ExtKeyImportLoose(&wdb, sek, fBip44, fSaveBip44))) { @@ -904,7 +909,7 @@ Value extkey(const Array ¶ms, bool fHelp) result.push_back(Pair("key_label", sek.sLabel)); result.push_back(Pair("note", "Please backup your wallet.")); // TODO: check for child of existing key? }; - + } // cs_wallet } else if (mode == "importaccount") @@ -917,12 +922,12 @@ Value extkey(const Array ¶ms, bool fHelp) nParamOffset++; }; }; - + int64_t nTimeStartScan = 1; // scan from start, 0 means no scan { std::string sVar = params[nParamOffset].get_str(); nParamOffset++; - + if (sVar == "N") { nTimeStartScan = 0; @@ -931,34 +936,34 @@ Value extkey(const Array ¶ms, bool fHelp) { // - setting timestamp directly errno = 0; - nTimeStartScan = strtoimax(sVar.c_str(), NULL, 10); + nTimeStartScan = strtoimax(sVar.c_str(), nullptr, 10); if (errno != 0) throw std::runtime_error("Import Account failed - Parse time error."); } else { int year, month, day; - + if (sscanf(sVar.c_str(), "%d-%d-%d", &year, &month, &day) != 3) throw std::runtime_error("Import Account failed - Parse time error."); - + struct tm tmdate; tmdate.tm_year = year - 1900; tmdate.tm_mon = month - 1; tmdate.tm_mday = day; time_t t = mktime(&tmdate); - + nTimeStartScan = t; }; }; - - + + std::string sLabel; if (params.size() > nParamOffset) { sLabel = params[nParamOffset].get_str(); nParamOffset++; }; - + CStoredExtKey sek; CExtKey58 eKey58; if (eKey58.Set58(sInKey.c_str()) == 0) @@ -968,13 +973,13 @@ Value extkey(const Array ¶ms, bool fHelp) { throw std::runtime_error("Import Account failed - Invalid key."); }; - + { LOCK(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + int rv = pwalletMain->ExtKeyImportAccount(&wdb, sek, nTimeStartScan, sLabel); if (rv == 1) { @@ -990,19 +995,19 @@ Value extkey(const Array ¶ms, bool fHelp) if (!wdb.TxnCommit()) throw std::runtime_error("TxnCommit failed."); result.push_back(Pair("result", "Success.")); - + if (rv == 3) result.push_back(Pair("result", "secret added to existing account.")); - + result.push_back(Pair("account_label", sLabel)); result.push_back(Pair("scanned_from", nTimeStartScan)); result.push_back(Pair("note", "Please backup your wallet.")); // TODO: check for child of existing key? }; - + } // cs_wallet - - - + + + } else if (mode == "setmaster") { @@ -1015,12 +1020,12 @@ Value extkey(const Array ¶ms, bool fHelp) } else throw std::runtime_error("Must specify ext key or id."); }; - + CKeyID idNewMaster; CExtKey58 eKey58; CExtKeyPair ekp; CBitcoinAddress addr; - + if (addr.SetString(sInKey) && addr.IsValid(CChainParams::EXT_KEY_HASH) && addr.GetKeyID(idNewMaster, CChainParams::EXT_KEY_HASH)) @@ -1035,13 +1040,13 @@ Value extkey(const Array ¶ms, bool fHelp) { throw std::runtime_error("Invalid key."); }; - + { LOCK(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + int rv; if (0 != (rv = pwalletMain->ExtKeySetMaster(&wdb, idNewMaster))) { @@ -1052,7 +1057,7 @@ Value extkey(const Array ¶ms, bool fHelp) throw std::runtime_error("TxnCommit failed."); result.push_back(Pair("result", "Success.")); } // cs_wallet - + } else if (mode == "setdefaultaccount") { @@ -1065,29 +1070,29 @@ Value extkey(const Array ¶ms, bool fHelp) } else throw std::runtime_error("Must specify ext key or id."); }; - + CKeyID idNewDefault; CBitcoinAddress addr; - + CExtKeyAccount *sea = new CExtKeyAccount(); - + if (addr.SetString(sInKey) && addr.IsValid(CChainParams::EXT_ACC_HASH) && addr.GetKeyID(idNewDefault, CChainParams::EXT_ACC_HASH)) { // idNewDefault is set }; - - + + { LOCK(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + if (!wdb.ReadExtAccount(idNewDefault, *sea)) throw std::runtime_error("Account not in wallet."); - + if (!wdb.WriteNamedExtKeyId("defaultAccount", idNewDefault)) { wdb.TxnAbort(); @@ -1095,9 +1100,9 @@ Value extkey(const Array ¶ms, bool fHelp) }; if (!wdb.TxnCommit()) throw std::runtime_error("TxnCommit failed."); - + pwalletMain->idDefaultAccount = idNewDefault; - + // TODO: necessary? ExtKeyAccountMap::iterator mi = pwalletMain->mapExtAccounts.find(idNewDefault); if (mi == pwalletMain->mapExtAccounts.end()) @@ -1107,10 +1112,10 @@ Value extkey(const Array ¶ms, bool fHelp) { delete sea; }; - + result.push_back(Pair("result", "Success.")); } // cs_wallet - + } else if (mode == "deriveaccount") { @@ -1120,21 +1125,21 @@ Value extkey(const Array ¶ms, bool fHelp) sLabel = params[nParamOffset].get_str(); nParamOffset++; }; - + if (params.size() > nParamOffset) { sPath = params[nParamOffset].get_str(); nParamOffset++; }; - + CExtKeyAccount *sea = new CExtKeyAccount(); - + { LOCK(pwalletMain->cs_wallet); CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + if (pwalletMain->ExtKeyDeriveNewAccount(&wdb, sea, sLabel, sPath) != 0) { wdb.TxnAbort(); @@ -1143,7 +1148,7 @@ Value extkey(const Array ¶ms, bool fHelp) { if (!wdb.TxnCommit()) throw std::runtime_error("TxnCommit failed."); - + result.push_back(Pair("result", "Success.")); result.push_back(Pair("account", sea->GetIDString58())); CStoredExtKey *sekAccount = sea->ChainAccount(); @@ -1153,7 +1158,7 @@ Value extkey(const Array ¶ms, bool fHelp) eKey58.SetKeyP(sekAccount->kp); result.push_back(Pair("public key", eKey58.ToString())); }; - + if (sLabel != "") result.push_back(Pair("label", sLabel)); }; @@ -1181,13 +1186,13 @@ Value extkey(const Array ¶ms, bool fHelp) sOptValue = params[nParamOffset].get_str(); nParamOffset++; }; - + CBitcoinAddress addr; - + CKeyID id; if (!addr.SetString(sInKey)) throw std::runtime_error("Invalid key or account id."); - + bool fAccount = false; bool fKey = false; if (addr.IsValid(CChainParams::EXT_KEY_HASH) @@ -1203,10 +1208,10 @@ Value extkey(const Array ¶ms, bool fHelp) fAccount = true; } else throw std::runtime_error("Invalid key or account id."); - - + + // TODO: work directly with key? - + CStoredExtKey sek; CExtKeyAccount sea; { @@ -1214,7 +1219,7 @@ Value extkey(const Array ¶ms, bool fHelp) CWalletDB wdb(pwalletMain->strWalletFile, "r+"); if (!wdb.TxnBegin()) throw std::runtime_error("TxnBegin failed."); - + if (fKey) { if (wdb.ReadExtKey(id, sek)) @@ -1224,7 +1229,7 @@ Value extkey(const Array ¶ms, bool fHelp) wdb.TxnAbort(); throw std::runtime_error("Error: " + sError); }; - + if (sOptValue.length() > 0 && !wdb.WriteExtKey(id, sek)) { @@ -1237,7 +1242,7 @@ Value extkey(const Array ¶ms, bool fHelp) throw std::runtime_error("Account not in wallet."); }; }; - + if (fAccount) { if (wdb.ReadExtAccount(id, sea)) @@ -1247,7 +1252,7 @@ Value extkey(const Array ¶ms, bool fHelp) wdb.TxnAbort(); throw std::runtime_error("Error: " + sError); }; - + if (sOptValue.length() > 0 && !wdb.WriteExtAccount(id, sea)) { @@ -1260,7 +1265,7 @@ Value extkey(const Array ¶ms, bool fHelp) throw std::runtime_error("Account not in wallet."); }; }; - + if (sOptValue.length() == 0) { wdb.TxnAbort(); @@ -1271,12 +1276,12 @@ Value extkey(const Array ¶ms, bool fHelp) result.push_back(Pair("result", "Success.")); }; } // cs_wallet - + } else { throw std::runtime_error(help); }; - + return result; }; diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 15f765831f..5b83332400 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "rpcserver.h" #include "main.h" @@ -10,6 +13,7 @@ #include "init.h" #include "miner.h" #include "kernel.h" +#include "chainparams_migration.h" #include @@ -19,7 +23,7 @@ using namespace boost::assign; // Key used by getwork/getblocktemplate miners. // Allocated in InitRPCMining, free'd in ShutdownRPCMining -static CReserveKey* pMiningKey = NULL; +static CReserveKey* pMiningKey = nullptr; void InitRPCMining() { @@ -35,7 +39,7 @@ void ShutdownRPCMining() if (!pMiningKey) return; - delete pMiningKey; pMiningKey = NULL; + delete pMiningKey; pMiningKey = nullptr; } Value getsubsidy(const Array& params, bool fHelp) @@ -51,7 +55,7 @@ Value getsubsidy(const Array& params, bool fHelp) else nShowHeight = nBestHeight+1; // block currently being solved - return (uint64_t)Params().GetProofOfWorkReward(nShowHeight, 0); + return (uint64_t)ChainParamsMigration::GetProofOfWorkReward(nShowHeight, 0); } @@ -74,12 +78,12 @@ Value getstakesubsidy(const Array& params, bool fHelp) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); } - uint64_t nCoinAge; + uint64_t nCoinAge = 0; CTxDB txdb("r"); - if (!tx.GetCoinAge(txdb, pindexBest, nCoinAge)) + if (!Params().IsProtocolV3(pindexBest->nHeight) && !tx.GetCoinAge(txdb, pindexBest, nCoinAge)) throw JSONRPCError(RPC_MISC_ERROR, "GetCoinAge failed"); - return (uint64_t)Params().GetProofOfStakeReward(pindexBest, nCoinAge, 0); + return (uint64_t)ChainParamsMigration::GetProofOfStakeReward(pindexBest->pprev, nCoinAge, 0); } Value getmininginfo(const Array& params, bool fHelp) @@ -89,7 +93,7 @@ Value getmininginfo(const Array& params, bool fHelp) "getmininginfo\n" "Returns an object containing mining-related information."); - uint64_t nWeight = pwalletMain->GetStakeWeight(); + uint64_t nWeight = pwalletMain->GetStakeWeight() + pwalletMain->GetSpectreStakeWeight(); Object obj, diff, weight; obj.push_back(Pair("blocks", (int)nBestHeight)); @@ -103,15 +107,16 @@ Value getmininginfo(const Array& params, bool fHelp) } else { diff.push_back(Pair("proof-of-work", GetHeaderDifficulty())); - diff.push_back(Pair("proof-of-stake", GetHeaderDifficulty(GetLastBlockThinIndex(pindexBestHeader, true)))); + diff.push_back(Pair("proof-of-stake", GetHeaderDifficulty(GetLastBlockThinIndex(pindexBestHeader, true)))); }; diff.push_back(Pair("search-interval", (int)nLastCoinStakeSearchInterval)); obj.push_back(Pair("difficulty", diff)); - obj.push_back(Pair("blockvalue", (uint64_t)Params().GetProofOfWorkReward(nBestHeight+1, 0))); + obj.push_back(Pair("blockvalue", (uint64_t)ChainParamsMigration::GetProofOfWorkReward(nBestHeight+1, 0))); obj.push_back(Pair("netmhashps", GetPoWMHashPS())); obj.push_back(Pair("netstakeweight", GetPoSKernelPS())); + obj.push_back(Pair("netstakeweightrecent", GetPoSKernelPSRecent())); obj.push_back(Pair("errors", GetWarnings("statusbar"))); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); weight.push_back(Pair("minimum", (uint64_t)nWeight)); @@ -131,11 +136,11 @@ Value getstakinginfo(const Array& params, bool fHelp) "getstakinginfo\n" "Returns an object containing staking-related information."); - uint64_t nWeight = pwalletMain->GetStakeWeight(); + uint64_t nWeight = pwalletMain->GetStakeWeight() + pwalletMain->GetSpectreStakeWeight(); uint64_t nNetworkWeight = GetPoSKernelPS(); bool staking = nLastCoinStakeSearchInterval && nWeight; - uint64_t nExpectedTime = staking ? (GetTargetSpacing(nBestHeight) * nNetworkWeight / nWeight) : 0; + uint64_t nExpectedTime = staking ? (GetTargetSpacing(nBestHeight, GetAdjustedTime()) * nNetworkWeight / nWeight) : 0; Object obj; @@ -152,6 +157,7 @@ Value getstakinginfo(const Array& params, bool fHelp) obj.push_back(Pair("weight", (uint64_t)nWeight)); obj.push_back(Pair("netstakeweight", (uint64_t)nNetworkWeight)); + obj.push_back(Pair("netstakeweightrecent", (uint64_t)GetPoSKernelPSRecent())); obj.push_back(Pair("expectedtime", nExpectedTime)); @@ -172,10 +178,10 @@ Value checkkernel(const Array& params, bool fHelp) bool fCreateBlockTemplate = params.size() > 1 ? params[1].get_bool() : false; if (vNodes.empty()) - throw JSONRPCError(-9, "ShadowCoin is not connected!"); + throw JSONRPCError(-9, "Alias is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "ShadowCoin is downloading blocks..."); + throw JSONRPCError(-10, "Alias is downloading blocks..."); COutPoint kernel; CBlockIndex* pindexPrev = pindexBest; @@ -183,7 +189,7 @@ Value checkkernel(const Array& params, bool fHelp) int64_t nTime = GetAdjustedTime(); nTime &= ~STAKE_TIMESTAMP_MASK; - BOOST_FOREACH(Value& input, inputs) + for (Value& input : inputs) { const Object& o = input.get_obj(); @@ -225,7 +231,7 @@ Value checkkernel(const Array& params, bool fHelp) return result; int64_t nFees; - auto_ptr pblock(CreateNewBlock(pwalletMain, true, &nFees)); + unique_ptr pblock(CreateNewBlock(pwalletMain, true, &nFees)); pblock->nTime = pblock->vtx[0].nTime = nTime; @@ -253,12 +259,12 @@ Value getworkex(const Array& params, bool fHelp) ); if (vNodes.empty()) - throw JSONRPCError(-9, "ShadowCoin is not connected!"); + throw JSONRPCError(-9, "Alias is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(-10, "ShadowCoin is downloading blocks..."); + throw JSONRPCError(-10, "Alias is downloading blocks..."); - if (pindexBest->nHeight >= Params().LastPOWBlock()) + if (pindexBest->nHeight >= ChainParamsMigration::GetLastPOWBlock()) throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); typedef map > mapNewBlock_t; @@ -279,7 +285,7 @@ Value getworkex(const Array& params, bool fHelp) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); - BOOST_FOREACH(CBlock* pblock, vNewBlock) + for (CBlock* pblock : vNewBlock) delete pblock; vNewBlock.clear(); } @@ -326,7 +332,7 @@ Value getworkex(const Array& params, bool fHelp) Array merkle_arr; - BOOST_FOREACH(uint256 merkleh, merkle) { + for (const uint256& merkleh : merkle) { merkle_arr.push_back(HexStr(BEGIN(merkleh), END(merkleh))); } @@ -389,12 +395,12 @@ Value getwork(const Array& params, bool fHelp) throw JSONRPCError(RPC_MISC_ERROR, "Not running as a full node!"); if (vNodes.empty()) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "ShadowCoin is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Alias is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "ShadowCoin is downloading blocks..."); + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Alias is downloading blocks..."); - if (pindexBest->nHeight >= Params().LastPOWBlock()) + if (pindexBest->nHeight >= ChainParamsMigration::GetLastPOWBlock()) throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); typedef map > mapNewBlock_t; @@ -416,13 +422,13 @@ Value getwork(const Array& params, bool fHelp) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); - BOOST_FOREACH(CBlock* pblock, vNewBlock) + for (CBlock* pblock : vNewBlock) delete pblock; vNewBlock.clear(); } // Clear pindexPrev so future getworks make a new block, despite any failures from here on - pindexPrev = NULL; + pindexPrev = nullptr; // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); @@ -533,12 +539,12 @@ Value getblocktemplate(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); if (vNodes.empty()) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "ShadowCoin is not connected!"); + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Alias is not connected!"); if (IsInitialBlockDownload()) - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "ShadowCoin is downloading blocks..."); + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Alias is downloading blocks..."); - if (pindexBest->nHeight >= Params().LastPOWBlock()) + if (pindexBest->nHeight >= ChainParamsMigration::GetLastPOWBlock()) throw JSONRPCError(RPC_MISC_ERROR, "No more PoW blocks"); static CReserveKey reservekey(pwalletMain); @@ -552,7 +558,7 @@ Value getblocktemplate(const Array& params, bool fHelp) (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on - pindexPrev = NULL; + pindexPrev = nullptr; // Store the pindexBest used before CreateNewBlock, to avoid races nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); @@ -563,7 +569,7 @@ Value getblocktemplate(const Array& params, bool fHelp) if(pblock) { delete pblock; - pblock = NULL; + pblock = nullptr; } pblock = CreateNewBlock(pwalletMain); @@ -582,8 +588,7 @@ Value getblocktemplate(const Array& params, bool fHelp) map setTxIndex; int i = 0; CTxDB txdb("r"); - BOOST_FOREACH (CTransaction& tx, pblock->vtx) - { + for (CTransaction& tx : pblock->vtx) { uint256 txHash = tx.GetHash(); setTxIndex[txHash] = i++; @@ -606,7 +611,7 @@ Value getblocktemplate(const Array& params, bool fHelp) entry.push_back(Pair("fee", (int64_t)(tx.GetValueIn(mapInputs) - tx.GetValueOut()))); Array deps; - BOOST_FOREACH (MapPrevTx::value_type& inp, mapInputs) + for (auto& inp : mapInputs) { if (setTxIndex.count(inp.first)) deps.push_back(setTxIndex[inp.first]); @@ -706,7 +711,7 @@ Value submitblock(const Array& params, bool fHelp) } } uint256 hashblock = block.GetHash(); - bool fAccepted = ProcessBlock(NULL, &block, hashblock); + bool fAccepted = ProcessBlock(nullptr, &block, hashblock); if (!fAccepted) return "rejected"; diff --git a/src/rpcmnemonic.cpp b/src/rpcmnemonic.cpp index d742000178..0a9c7e7ebf 100644 --- a/src/rpcmnemonic.cpp +++ b/src/rpcmnemonic.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2015 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "init.h" #include "main.h" @@ -9,6 +12,7 @@ #include "key.h" #include "extkey.h" #include "chainparams.h" +#include "chainparams_migration.h" #include "hash.h" #include "base58.h" @@ -22,7 +26,7 @@ using namespace json_spirit; Value mnemonic(const Array ¶ms, bool fHelp) { static const char *help = "" - "mnemonic \n" + "mnemonic \n" "mnemonic new [password] [language] [nBytesEntropy] [bip44]\n" " Generate a new extended key and mnemonic\n" " password, can be blank "", default blank\n" @@ -36,33 +40,30 @@ Value mnemonic(const Array ¶ms, bool fHelp) " Final no of words in mnemonic must be divisible by three.\n" "\n" ""; - + if (fHelp || params.size() > 5) // defaults to info, will always take at least 1 parameter throw std::runtime_error(help); - + std::string mode = ""; - - uint32_t nParamOffset = 0; + if (params.size() > 0) { std::string s = params[0].get_str(); std::string st = " " + s + " "; // Note the spaces std::transform(st.begin(), st.end(), st.begin(), ::tolower); static const char *pmodes = " new decode addchecksum "; - if (strstr(pmodes, st.c_str()) != NULL) + if (strstr(pmodes, st.c_str()) != nullptr) { st.erase(std::remove(st.begin(), st.end(), ' '), st.end()); mode = st; - - nParamOffset = 1; } else { throw std::runtime_error("Unknown mode."); }; }; - + Object result; - + if (mode == "new") { int nLanguage = WLL_ENGLISH; @@ -70,78 +71,78 @@ Value mnemonic(const Array ¶ms, bool fHelp) bool fBip44 = false; std::string sPassword = ""; std::string sError; - + if (params.size() > 1) { sPassword = params[1].get_str(); }; - + if (params.size() > 2) { static const char *planguages = "\nenglish\nfrench\njapanese\nspanish\nchinese_s\nchinese_t\n"; std::string s = params[2].get_str(); std::transform(s.begin(), s.end(), s.begin(), ::tolower); - + if (GetWordOffset(s.c_str(), planguages, strlen(planguages), nLanguage) != 0) throw std::runtime_error("Unknown language."); - + if (nLanguage < 1 || nLanguage >= WLL_MAX) throw std::runtime_error("Unknown language."); }; - + if (params.size() > 3) { std::stringstream sstr(params[3].get_str()); - + sstr >> nBytesEntropy; if (!sstr) throw std::runtime_error("Invalid num bytes entropy"); - + if (nBytesEntropy < 16 || nBytesEntropy > 64) throw std::runtime_error("Num bytes entropy out of range [16,64]."); }; - + if (params.size() > 4) { std::string s = params[4].get_str(); if (IsStringBoolPositive(s)) fBip44 = true; }; - + std::vector vEntropy; std::vector vSeed; vEntropy.resize(nBytesEntropy); - + std::string sMnemonic; CExtKey ekMaster; - + RandAddSeedPerfmon(); for (uint32_t i = 0; i < MAX_DERIVE_TRIES; ++i) { if (1 != RAND_bytes(&vEntropy[0], nBytesEntropy)) throw std::runtime_error("RAND_bytes failed."); - + if (0 != MnemonicEncode(nLanguage, vEntropy, sMnemonic, sError)) throw std::runtime_error(strprintf("MnemonicEncode failed %s.", sError.c_str()).c_str()); - + if (0 != MnemonicToSeed(sMnemonic, sPassword, vSeed)) throw std::runtime_error("MnemonicToSeed failed."); - + ekMaster.SetMaster(&vSeed[0], vSeed.size()); - + if (!ekMaster.IsValid()) continue; break; }; - + CExtKey58 eKey58; result.push_back(Pair("mnemonic", sMnemonic)); - + if (fBip44) { eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY_BTC); result.push_back(Pair("master", eKey58.ToString())); - + // m / purpose' / coin_type' / account' / change / address_index // path "44' Params().RPCPort() } else @@ -149,7 +150,7 @@ Value mnemonic(const Array ¶ms, bool fHelp) eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY); result.push_back(Pair("master", eKey58.ToString())); }; - + // - in c++11 strings are definitely contiguous, and before they're very unlikely not to be OPENSSL_cleanse(&sMnemonic[0], sMnemonic.size()); OPENSSL_cleanse(&sPassword[0], sPassword.size()); @@ -160,7 +161,7 @@ Value mnemonic(const Array ¶ms, bool fHelp) std::string sPassword; std::string sMnemonic; std::string sError; - + if (params.size() > 1) { sPassword = params[1].get_str(); @@ -168,7 +169,7 @@ Value mnemonic(const Array ¶ms, bool fHelp) { throw std::runtime_error("Must specify password."); }; - + if (params.size() > 2) { sMnemonic = params[2].get_str(); @@ -176,41 +177,41 @@ Value mnemonic(const Array ¶ms, bool fHelp) { throw std::runtime_error("Must specify mnemonic."); }; - + if (params.size() > 3) { std::string s = params[3].get_str(); if (IsStringBoolPositive(s)) fBip44 = true; }; - + std::vector vEntropy; std::vector vSeed; - + // - decode to determine validity of mnemonic if (0 != MnemonicDecode(-1, sMnemonic, vEntropy, sError)) throw std::runtime_error(strprintf("MnemonicDecode failed %s.", sError.c_str()).c_str()); - + if (0 != MnemonicToSeed(sMnemonic, sPassword, vSeed)) throw std::runtime_error("MnemonicToSeed failed."); - + CExtKey ekMaster; CExtKey58 eKey58; ekMaster.SetMaster(&vSeed[0], vSeed.size()); - + if (!ekMaster.IsValid()) throw std::runtime_error("Invalid key."); - + if (fBip44) { eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY_BTC); result.push_back(Pair("master", eKey58.ToString())); - + // m / purpose' / coin_type' / account' / change / address_index CExtKey ekDerived; ekMaster.Derive(ekDerived, BIP44_PURPOSE); - ekDerived.Derive(ekDerived, Params().BIP44ID()); - + ekDerived.Derive(ekDerived, ChainParamsMigration::GetBIP44ID()); + eKey58.SetKey(ekDerived, CChainParams::EXT_SECRET_KEY); result.push_back(Pair("derived", eKey58.ToString())); } else @@ -218,7 +219,7 @@ Value mnemonic(const Array ¶ms, bool fHelp) eKey58.SetKey(ekMaster, CChainParams::EXT_SECRET_KEY); result.push_back(Pair("master", eKey58.ToString())); }; - + // - in c++11 strings are definitely contiguous, and before they're very unlikely not to be OPENSSL_cleanse(&sMnemonic[0], sMnemonic.size()); OPENSSL_cleanse(&sPassword[0], sPassword.size()); @@ -230,9 +231,9 @@ Value mnemonic(const Array ¶ms, bool fHelp) std::string sError; if (params.size() != 2) throw std::runtime_error("Must provide input mnemonic."); - + sMnemonicIn = params[1].get_str(); - + if (0 != MnemonicAddChecksum(-1, sMnemonicIn, sMnemonicOut, sError)) throw std::runtime_error(strprintf("MnemonicAddChecksum failed %s", sError.c_str()).c_str()); result.push_back(Pair("result", sMnemonicOut)); @@ -240,7 +241,7 @@ Value mnemonic(const Array ¶ms, bool fHelp) { throw std::runtime_error(help); }; - + return result; }; diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index b66aafffbe..dd8ce37fb1 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2009-2012 Bitcoin Developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "net.h" #include "rpcserver.h" @@ -9,7 +12,6 @@ #include "db.h" #include "walletdb.h" -#include #include "json/json_spirit_value.h" using namespace json_spirit; @@ -37,7 +39,7 @@ Value ping(const Array& params, bool fHelp) // Request that each node send a ping during next message processing pass LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pNode, vNodes) { + for (CNode* pNode : vNodes) { pNode->fPingQueued = true; } @@ -50,7 +52,7 @@ static void CopyNodeStats(std::vector& vstats) LOCK(cs_vNodes); vstats.reserve(vNodes.size()); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { CNodeStats stats; pnode->copyStats(stats); vstats.push_back(stats); @@ -69,7 +71,7 @@ Value getpeerinfo(const Array& params, bool fHelp) Array ret; - BOOST_FOREACH(const CNodeStats& stats, vstats) { + for (const CNodeStats& stats : vstats) { Object obj; obj.push_back(Pair("addr", stats.addrName)); @@ -150,42 +152,42 @@ Value getaddednodeinfo(const Array& params, bool fHelp) bool fDns = params[0].get_bool(); - list laddedNodes(0); + list laddedNodes; if (params.size() == 1) { LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + for (const std::string& strAddNode : vAddedNodes) laddedNodes.push_back(strAddNode); } else { string strNode = params[1].get_str(); LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) + for (const std::string& strAddNode : vAddedNodes) if (strAddNode == strNode) { laddedNodes.push_back(strAddNode); break; } - if (laddedNodes.size() == 0) + if (laddedNodes.empty()) throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); } if (!fDns) { Object ret; - BOOST_FOREACH(string& strAddNode, laddedNodes) + for (std::string& strAddNode : laddedNodes) ret.push_back(Pair("addednode", strAddNode)); return ret; } Array ret; - list > > laddedAddreses(0); - BOOST_FOREACH(string& strAddNode, laddedNodes) + list > > laddedAddreses; + for (const std::string& strAddNode : laddedNodes) { - vector vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0)) + vector vservNode; + if(Lookup(strAddNode.c_str(), vservNode, ChainParamsMigration::GetDefaultPort(), fNameLookup, 0)) laddedAddreses.push_back(make_pair(strAddNode, vservNode)); else { @@ -198,26 +200,25 @@ Value getaddednodeinfo(const Array& params, bool fHelp) } LOCK(cs_vNodes); - for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) + for (const auto& item : laddedAddreses) { Object obj; - obj.push_back(Pair("addednode", it->first)); + obj.push_back(Pair("addednode", item.first)); Array addresses; bool fConnected = false; - BOOST_FOREACH(CService& addrNode, it->second) - { + for (const CService& addrNode : item.second) { bool fFound = false; Object node; node.push_back(Pair("address", addrNode.ToString())); - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->addr == addrNode) - { + for (CNode* pnode : vNodes) { + if (pnode->addr == addrNode) { fFound = true; fConnected = true; node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); break; } + } if (!fFound) node.push_back(Pair("connected", "false")); addresses.push_back(node); @@ -267,17 +268,19 @@ Value sendalert(const Array& params, bool fHelp) alert.vchMsg = vector(sMsg.begin(), sMsg.end()); vector vchPrivKey = ParseHex(params[1].get_str()); - key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end()), false); // if key is not correct openssl may crash + if (!key.SetPrivKey(CPrivKey(vchPrivKey.begin(), vchPrivKey.end()), false)) // if key is not correct openssl may crash + throw runtime_error( + "Private key is in wrong format!\n"); if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) throw runtime_error( - "Unable to sign alert, check private key?\n"); - if(!alert.ProcessAlert()) + "Unable to sign alert, check private key?\n"); + if(!alert.ProcessAlert()) throw runtime_error( "Failed to process alert.\n"); // Relay alert { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) alert.RelayTo(pnode); } @@ -352,7 +355,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) " }\n" " ,...\n" " ],\n" - " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in sdc/kb\n" + " \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in spec/kb\n" " \"localaddresses\": [ (array) list of local addresses\n" " {\n" " \"address\": \"xxxx\", (string) network address\n" @@ -378,7 +381,7 @@ Value getnetworkinfo(const Array& params, bool fHelp) //obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()))); Array localAddresses; { - BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) + for (const auto& item : mapLocalHost) { Object rec; rec.push_back(Pair("address", item.first.ToString())); diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp index e5e0c20df8..5ea71bf935 100644 --- a/src/rpcprotocol.cpp +++ b/src/rpcprotocol.cpp @@ -1,251 +1,26 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "rpcprotocol.h" +#include -#include "util.h" +#include // For LogPrintf +#include // May not exist in old codebase, will add if needed +#include // May not exist in old codebase, will add if needed -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "json/json_spirit_writer_template.h" - -using namespace json_spirit; - -// -// HTTP protocol -// -// This ain't Apache. We're just using HTTP header for the length field -// and to be compatible with other JSON-RPC implementations. -// - -std::string HTTPPost(const std::string& strMsg, const std::map& mapRequestHeaders) -{ - std::ostringstream s; - s << "POST / HTTP/1.1\r\n" - << "User-Agent: shadow-json-rpc/" << FormatFullVersion() << "\r\n" - << "Host: 127.0.0.1\r\n" - << "Content-Type: application/json\r\n" - << "Content-Length: " << strMsg.size() << "\r\n" - << "Connection: close\r\n" - << "Accept: application/json\r\n"; - BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, mapRequestHeaders) - s << item.first << ": " << item.second << "\r\n"; - s << "\r\n" << strMsg; - - return s.str(); -} - -static std::string rfc1123Time() -{ - return DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", GetTime()); -} - -std::string HTTPReply(int nStatus, const std::string& strMsg, bool keepalive) -{ - if (nStatus == HTTP_UNAUTHORIZED) - return strprintf("HTTP/1.0 401 Authorization Required\r\n" - "Date: %s\r\n" - "Server: shadow-json-rpc/%s\r\n" - "WWW-Authenticate: Basic realm=\"jsonrpc\"\r\n" - "Content-Type: text/html\r\n" - "Content-Length: 296\r\n" - "\r\n" - "\r\n" - "\r\n" - "\r\n" - "Error\r\n" - "\r\n" - "\r\n" - "

    401 Unauthorized.

    \r\n" - "\r\n", rfc1123Time(), FormatFullVersion()); - const char *cStatus; - if (nStatus == HTTP_OK) cStatus = "OK"; - else if (nStatus == HTTP_BAD_REQUEST) cStatus = "Bad Request"; - else if (nStatus == HTTP_FORBIDDEN) cStatus = "Forbidden"; - else if (nStatus == HTTP_NOT_FOUND) cStatus = "Not Found"; - else if (nStatus == HTTP_INTERNAL_SERVER_ERROR) cStatus = "Internal Server Error"; - else cStatus = ""; - return strprintf( - "HTTP/1.1 %d %s\r\n" - "Date: %s\r\n" - "Connection: %s\r\n" - "Content-Length: %u\r\n" - "Content-Type: application/json\r\n" - "Server: shadow-json-rpc/%s\r\n" - "\r\n" - "%s", - nStatus, - cStatus, - rfc1123Time(), - keepalive ? "keep-alive" : "close", - strMsg.size(), - FormatFullVersion(), - strMsg); -} - -bool ReadHTTPRequestLine(std::basic_istream& stream, int &proto, - std::string& http_method, std::string& http_uri) -{ - std::string str; - getline(stream, str); - - // HTTP request line is space-delimited - std::vector vWords; - boost::split(vWords, str, boost::is_any_of(" ")); - if (vWords.size() < 2) - return false; - - // HTTP methods permitted: GET, POST - http_method = vWords[0]; - if (http_method != "GET" && http_method != "POST") - return false; - - // HTTP URI must be an absolute path, relative to current host - http_uri = vWords[1]; - if (http_uri.size() == 0 || http_uri[0] != '/') - return false; - - // parse proto, if present - std::string strProto = ""; - if (vWords.size() > 2) - strProto = vWords[2]; - - proto = 0; - const char *ver = strstr(strProto.c_str(), "HTTP/1."); - if (ver != NULL) - proto = atoi(ver+7); - - return true; -} - -int ReadHTTPStatus(std::basic_istream& stream, int &proto) -{ - std::string str; - getline(stream, str); - std::vector vWords; - boost::split(vWords, str, boost::is_any_of(" ")); - if (vWords.size() < 2) - return HTTP_INTERNAL_SERVER_ERROR; - proto = 0; - const char *ver = strstr(str.c_str(), "HTTP/1."); - if (ver != NULL) - proto = atoi(ver+7); - return atoi(vWords[1].c_str()); -} - -int ReadHTTPHeaders(std::basic_istream& stream, std::map& mapHeadersRet) -{ - int nLen = 0; - while (true) - { - std::string str; - std::getline(stream, str); - if (str.empty() || str == "\r") - break; - std::string::size_type nColon = str.find(":"); - if (nColon != std::string::npos) - { - std::string strHeader = str.substr(0, nColon); - boost::trim(strHeader); - boost::to_lower(strHeader); - std::string strValue = str.substr(nColon+1); - boost::trim(strValue); - mapHeadersRet[strHeader] = strValue; - if (strHeader == "content-length") - nLen = atoi(strValue.c_str()); - } - } - return nLen; -} - - -int ReadHTTPMessage(std::basic_istream& stream, std::map& mapHeadersRet, std::string& strMessageRet, - int nProto) +namespace kernel { +Context::Context() { - mapHeadersRet.clear(); - strMessageRet = ""; - - // Read header - int nLen = ReadHTTPHeaders(stream, mapHeadersRet); - if (nLen < 0 || nLen > (int)MAX_SIZE) - return HTTP_INTERNAL_SERVER_ERROR; - - // Read message - if (nLen > 0) - { - std::vector vch(nLen); - stream.read(&vch[0], nLen); - strMessageRet = std::string(vch.begin(), vch.end()); - } - - std::string sConHdr = mapHeadersRet["connection"]; - - if ((sConHdr != "close") && (sConHdr != "keep-alive")) - { - if (nProto >= 1) - mapHeadersRet["connection"] = "keep-alive"; - else - mapHeadersRet["connection"] = "close"; - } - - return HTTP_OK; + // TODO: Implement SHA256AutoDetect and RandomInit when crypto/random modules are migrated + // For now, this is a placeholder that allows compilation + // std::string sha256_algo = SHA256AutoDetect(); + // LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo); + // RandomInit(); + LogPrintf("Kernel context initialized\n"); } +} // namespace kernel -// -// JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility, -// but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were -// unspecified (HTTP errors and contents of 'error'). -// -// 1.0 spec: http://json-rpc.org/wiki/specification -// 1.2 spec: http://groups.google.com/group/json-rpc/web/json-rpc-over-http -// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx -// - -std::string JSONRPCRequest(const std::string& strMethod, const Array& params, const Value& id) -{ - Object request; - request.push_back(Pair("method", strMethod)); - request.push_back(Pair("params", params)); - request.push_back(Pair("id", id)); - return write_string(Value(request), false) + "\n"; -} - -Object JSONRPCReplyObj(const Value& result, const Value& error, const Value& id) -{ - Object reply; - if (error.type() != null_type) - reply.push_back(Pair("result", Value::null)); - else - reply.push_back(Pair("result", result)); - reply.push_back(Pair("error", error)); - reply.push_back(Pair("id", id)); - return reply; -} - -std::string JSONRPCReply(const Value& result, const Value& error, const Value& id) -{ - Object reply = JSONRPCReplyObj(result, error, id); - return write_string(Value(reply), false) + "\n"; -} - -Object JSONRPCError(int code, const std::string& message) -{ - Object error; - error.push_back(Pair("code", code)); - error.push_back(Pair("message", message)); - return error; -} diff --git a/src/rpcprotocol.h b/src/rpcprotocol.h index a5da6fef7c..f24bd0a248 100644 --- a/src/rpcprotocol.h +++ b/src/rpcprotocol.h @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef _BITCOINRPC_PROTOCOL_H_ #define _BITCOINRPC_PROTOCOL_H_ 1 @@ -12,10 +15,13 @@ #include #include #include + +#ifndef Q_MOC_RUN #include #include #include #include +#endif #include "json/json_spirit_reader_template.h" #include "json/json_spirit_utils.h" @@ -103,7 +109,7 @@ class SSLIOStreamDevice : public boost::iostreams::device @@ -38,7 +41,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeH out.push_back(Pair("type", GetTxnOutputType(type))); Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) + for (const CTxDestination& addr : addresses) a.push_back(CBitcoinAddress(addr).ToString()); out.push_back(Pair("addresses", a)); } @@ -53,8 +56,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) std::vector vchImage; Array vin; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { + for (const CTxIn& txin : tx.vin) { Object in; if (tx.IsCoinBase()) { @@ -94,9 +96,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) entry.push_back(Pair("vin", vin)); Array vout; - for (unsigned int i = 0; i < tx.vout.size(); i++) + unsigned int i = 0; + for (const CTxOut& txout : tx.vout) { - const CTxOut& txout = tx.vout[i]; Object out; out.push_back(Pair("value", ValueFromAmount(txout.nValue))); out.push_back(Pair("n", (int64_t)i)); @@ -104,16 +106,17 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry) ScriptPubKeyToJSON(txout.scriptPubKey, o, true); out.push_back(Pair("scriptPubKey", o)); vout.push_back(out); + i++; }; entry.push_back(Pair("vout", vout)); - if (hashBlock != 0) + if (hashBlock != uint256()) { entry.push_back(Pair("blockhash", hashBlock.GetHex())); map::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) + if (mi != mapBlockIndex.end() && mi->second) { - CBlockIndex* pindex = (*mi).second; + CBlockIndex* pindex = mi->second; if (pindex->IsInMainChain()) { entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight)); @@ -143,7 +146,7 @@ Value getrawtransaction(const Array& params, bool fHelp) fVerbose = (params[1].get_int() != 0); CTransaction tx; - uint256 hashBlock = 0; + uint256 hashBlock = uint256(); if (!GetTransaction(hash, tx, hashBlock)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction"); @@ -185,11 +188,11 @@ Value listunspent(const Array& params, bool fHelp) if (params.size() > 2) { Array inputs = params[2].get_array(); - BOOST_FOREACH(Value& input, inputs) + for (Value& input : inputs) { CBitcoinAddress address(input.get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid ShadowCoin address: ")+input.get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Alias address: ")+input.get_str()); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); setAddress.insert(address); @@ -199,8 +202,7 @@ Value listunspent(const Array& params, bool fHelp) Array results; vector vecOutputs; pwalletMain->AvailableCoins(vecOutputs, false); - BOOST_FOREACH(const COutput& out, vecOutputs) - { + for (const COutput& out : vecOutputs) { if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) continue; @@ -239,7 +241,7 @@ Value createrawtransaction(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) throw runtime_error( - "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...}\n" + "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {public_address:amount,...}\n" "Create a transaction spending given inputs\n" "(array of objects containing transaction id and output number),\n" "sending to given address(es).\n" @@ -254,7 +256,7 @@ Value createrawtransaction(const Array& params, bool fHelp) CTransaction rawTx; - BOOST_FOREACH(Value& input, inputs) + for (Value& input : inputs) { const Object& o = input.get_obj(); @@ -277,11 +279,11 @@ Value createrawtransaction(const Array& params, bool fHelp) }; set setAddress; - BOOST_FOREACH(const Pair& s, sendTo) + for (const Pair& s : sendTo) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid ShadowCoin address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Alias address: ")+s.name_); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_); @@ -394,7 +396,7 @@ Value signrawtransaction(const Array& params, bool fHelp) // Fetch previous transactions (inputs): std::map mapPrevOut; - for (unsigned int i = 0; i < mergedTx.vin.size(); i++) + for (const CTxIn& vin : mergedTx.vin) { CTransaction tempTx; MapPrevTx mapPrevTx; @@ -403,11 +405,11 @@ Value signrawtransaction(const Array& params, bool fHelp) bool fInvalid; // FetchInputs aborts on failure, so we go one at a time. - tempTx.vin.push_back(mergedTx.vin[i]); + tempTx.vin.push_back(vin); tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid); // Copy results into mapPrevOut: - BOOST_FOREACH(const CTxIn& txin, tempTx.vin) + for (const CTxIn& txin : tempTx.vin) { const uint256& prevHash = txin.prevout.hash; if (mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size()>txin.prevout.n) @@ -421,7 +423,7 @@ Value signrawtransaction(const Array& params, bool fHelp) { fGivenKeys = true; Array keys = params[2].get_array(); - BOOST_FOREACH(Value k, keys) + for (const Value& k : keys) { CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(k.get_str()); @@ -439,8 +441,7 @@ Value signrawtransaction(const Array& params, bool fHelp) if (params.size() > 1 && params[1].type() != null_type) { Array prevTxs = params[1].get_array(); - BOOST_FOREACH(Value& p, prevTxs) - { + for (Value& p : prevTxs) { if (p.type() != obj_type) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}"); @@ -522,7 +523,7 @@ Value signrawtransaction(const Array& params, bool fHelp) for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; - if (mapPrevOut.count(txin.prevout) == 0) + if (mapPrevOut.find(txin.prevout) == mapPrevOut.end()) { fComplete = false; continue; @@ -537,7 +538,7 @@ Value signrawtransaction(const Array& params, bool fHelp) } // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) + for (const CTransaction& txv : txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); }; @@ -582,10 +583,10 @@ Value sendrawtransaction(const Array& params, bool fHelp) // See if the transaction is already in a block // or in the memory pool: CTransaction existingTx; - uint256 hashBlock = 0; + uint256 hashBlock = uint256(); if (GetTransaction(hashTx, existingTx, hashBlock)) { - if (hashBlock != 0) + if (hashBlock != uint256()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("transaction already in block ")+hashBlock.GetHex()); // Not in block, but already in the memory pool; will drop // through to re-relay it. @@ -596,7 +597,7 @@ Value sendrawtransaction(const Array& params, bool fHelp) if (!AcceptToMemoryPool(mempool, tx, txdb)) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX rejected"); - SyncWithWallets(tx, NULL, true); + SyncWithWallets(tx, nullptr, true); }; RelayTransaction(tx, hashTx); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 27d0a7b470..291151fc68 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "rpcserver.h" @@ -11,20 +14,19 @@ #include "sync.h" #include "base58.h" #include "db.h" -#include "ui_interface.h" +#include "interface.h" #include "wallet.h" +#include "chainparams_migration.h" #include #include #include #include -#include -#include -#include -#include +#include #include #include #include +#include "util/fs.h" #include using namespace std; @@ -37,17 +39,17 @@ namespace ba = boost::asio; static std::string strRPCUserColonPass; // These are created by StartRPCThreads, destroyed in StopRPCThreads -static asio::io_service* rpc_io_service = NULL; +static asio::io_service* rpc_io_service = nullptr; static map > deadlineTimers; -static ssl::context* rpc_ssl_context = NULL; -static boost::thread_group* rpc_worker_group = NULL; +static ssl::context* rpc_ssl_context = nullptr; +static boost::thread_group* rpc_worker_group = nullptr; void RPCTypeCheck(const Array& params, const list& typesExpected, bool fAllowNull) { unsigned int i = 0; - BOOST_FOREACH(Value_type t, typesExpected) + for (Value_type t : typesExpected) { if (params.size() <= i) break; @@ -67,8 +69,7 @@ void RPCTypeCheck(const Object& o, const map& typesExpected, bool fAllowNull) { - BOOST_FOREACH(const PAIRTYPE(string, Value_type)& t, typesExpected) - { + for (const auto& t : typesExpected) { const Value& v = find_value(o, t.first); if (!fAllowNull && v.type() == null_type) throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first)); @@ -125,13 +126,13 @@ bool GetStringBool(std::string& value, bool &fOut) fOut = true; return true; }; - + if (IsStringBoolNegative(value)) { fOut = false; return true; }; - + return false; }; @@ -182,32 +183,31 @@ string CRPCTable::help(string strCommand) const string strRet; set setDone; - for (map::const_iterator mi = mapCommands.begin(); mi != mapCommands.end(); ++mi) + for (const auto& mi : mapCommands) { - const CRPCCommand *pcmd = mi->second; - string strMethod = mi->first; + const CRPCCommand *pcmd = mi.second; + string strMethod = mi.first; // We already filter duplicates, but these deprecated screw up the sort order if (strMethod.find("label") != string::npos) continue; - - + + if (fAllAnon) { - if (strMethod != "sendsdctoanon" - && strMethod != "sendanontoanon" - && strMethod != "sendanontosdc" - && strMethod != "estimateanonfee" - && strMethod != "anonoutputs" - && strMethod != "anoninfo" - && strMethod != "reloadanondata") + if (strMethod != "sendpublictoprivate" + && strMethod != "sendprivate" + && strMethod != "sendprivatetopublic" + && strMethod != "estimateprivatefee" + && strMethod != "privateoutputs" + && strMethod != "privateinfo") continue; } else if (strCommand != "" && strMethod != strCommand) continue; - + if (pcmd->reqWallet && !pwalletMain) continue; - + try { Array params; @@ -252,10 +252,10 @@ Value stop(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw std::runtime_error( "stop\n" - "Stop ShadowCoin server."); + "Stop Alias server."); // Shutdown will take long enough that the response should get back StartShutdown(); - return "ShadowCoin server stopping"; + return "Alias server stopping"; } @@ -312,11 +312,13 @@ static const CRPCCommand vRPCCommands[] = { "createmultisig", &createmultisig, true, false, true }, { "addredeemscript", &addredeemscript, false, false, false }, { "getrawmempool", &getrawmempool, true, false, false }, + { "gettxout", &gettxout, false, false, false }, { "getblock", &getblock, false, false, false }, { "getblockbynumber", &getblockbynumber, false, false, false }, { "setbestblockbyheight", &setbestblockbyheight, false, false, false }, { "rewindchain", &rewindchain, false, false, false }, { "nextorphan", &nextorphan, false, false, false }, + { "getorphans", &getorphans, false, false, false }, { "getblockhash", &getblockhash, false, false, false }, { "gettransaction", &gettransaction, false, false, false }, { "listtransactions", &listtransactions, false, false, false }, @@ -348,47 +350,28 @@ static const CRPCCommand vRPCCommands[] = { "resendtx", &resendtx, false, true, false }, { "makekeypair", &makekeypair, false, true, false }, { "checkkernel", &checkkernel, true, false, true }, - + { "sendalert", &sendalert, false, false, false }, { "getnetworkinfo", &getnetworkinfo, false, false, false }, - - - { "getnewstealthaddress", &getnewstealthaddress, false, false, false }, - { "liststealthaddresses", &liststealthaddresses, false, false, false }, - { "importstealthaddress", &importstealthaddress, false, false, false }, - { "sendtostealthaddress", &sendtostealthaddress, false, false, false }, + + { "getnewprivateaddress", &getnewprivateaddress, false, false, false }, + { "listprivateaddresses", &listprivateaddresses, false, false, false }, + { "importprivateaddress", &importprivateaddress, false, false, false }, { "clearwallettransactions",&clearwallettransactions,false, false, false }, { "scanforalltxns", &scanforalltxns, false, false, false }, - { "scanforstealthtxns", &scanforstealthtxns, false, false, false }, - - { "sendsdctoanon", &sendsdctoanon, false, false, false }, - { "sendanontoanon", &sendanontoanon, false, false, false }, - { "sendanontosdc", &sendanontosdc, false, false, false }, - { "estimateanonfee", &estimateanonfee, false, false, false }, - { "anonoutputs", &anonoutputs, false, false, false }, - { "anoninfo", &anoninfo, false, false, false }, - { "reloadanondata", &reloadanondata, false, false, false }, + + { "sendpublictoprivate", &sendpublictoprivate, false, false, false }, + { "sendprivate", &sendprivate, false, false, false }, + { "sendprivatetopublic", &sendprivatetopublic, false, false, false }, + { "estimateprivatefee", &estimateprivatefee, false, false, false }, + { "privateoutputs", &privateoutputs, false, false, false }, + { "privateinfo", &privateinfo, false, false, false }, { "txnreport", &txnreport, false, false, false }, - { "smsgenable", &smsgenable, false, false, false }, - { "smsgdisable", &smsgdisable, false, false, false }, - { "smsglocalkeys", &smsglocalkeys, false, false, false }, - { "smsgoptions", &smsgoptions, false, false, false }, - { "smsgscanchain", &smsgscanchain, false, false, false }, - { "smsgscanbuckets", &smsgscanbuckets, false, false, false }, - { "smsgaddkey", &smsgaddkey, false, false, false }, - { "smsggetpubkey", &smsggetpubkey, false, false, false }, - { "smsgsend", &smsgsend, false, false, false }, - { "smsgsendanon", &smsgsendanon, false, false, false }, - { "smsginbox", &smsginbox, false, false, false }, - { "smsgoutbox", &smsgoutbox, false, false, false }, - { "smsgbuckets", &smsgbuckets, false, false, false }, - - { "thinscanmerkleblocks", &thinscanmerkleblocks, false, false, false }, { "thinforcestate", &thinforcestate, false, false, false }, - + { "extkey", &extkey, false, false, true }, { "bip32", &extkey, false, false, true }, { "mnemonic", &mnemonic, false, false, false }, @@ -411,8 +394,8 @@ const CRPCCommand *CRPCTable::operator[](string name) const { map::const_iterator it = mapCommands.find(name); if (it == mapCommands.end()) - return NULL; - return (*it).second; + return nullptr; + return it->second; } @@ -454,7 +437,7 @@ bool ClientAllowed(const boost::asio::ip::address& address) const string strAddress = address.to_string(); const vector& vAllow = mapMultiArgs["-rpcallowip"]; - BOOST_FOREACH(string strAllow, vAllow) + for (const std::string& strAllow : vAllow) if (WildcardMatch(strAddress, strAllow)) return true; return false; @@ -484,17 +467,17 @@ class AcceptedConnectionImpl : public AcceptedConnection { } - virtual std::iostream& stream() + std::iostream& stream() override { return _stream; } - virtual std::string peer_address_to_string() const + std::string peer_address_to_string() const override { return peer.address().to_string(); } - virtual void close() + void close() override { _stream.close(); } @@ -510,8 +493,12 @@ class AcceptedConnectionImpl : public AcceptedConnection void ServiceConnection(AcceptedConnection *conn); // Forward declaration required for RPCListen -template -static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, +template < + typename Protocol +> +static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor< + Protocol +> > acceptor, ssl::context& context, bool fUseSSL, AcceptedConnection* conn, @@ -520,18 +507,28 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor -static void RPCListen(boost::shared_ptr< basic_socket_acceptor > acceptor, +template < + typename Protocol +> +static void RPCListen(boost::shared_ptr< basic_socket_acceptor< + Protocol +> > acceptor, ssl::context& context, const bool fUseSSL) { // Accept connection - AcceptedConnectionImpl* conn = new AcceptedConnectionImpl(acceptor->get_io_service(), context, fUseSSL); + AcceptedConnectionImpl + + * conn = new AcceptedConnectionImpl + + ((boost::asio::io_context&)(acceptor)->get_executor().context(), context, fUseSSL); acceptor->async_accept( conn->sslStream.lowest_layer(), conn->peer, - boost::bind(&RPCAcceptHandler, + boost::bind(&RPCAcceptHandler< + Protocol + >, acceptor, boost::ref(context), fUseSSL, @@ -543,8 +540,12 @@ static void RPCListen(boost::shared_ptr< basic_socket_acceptor -static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor > acceptor, +template < + typename Protocol +> +static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor< + Protocol +> > acceptor, ssl::context& context, const bool fUseSSL, AcceptedConnection* conn, @@ -583,11 +584,11 @@ void StartRPCThreads() { strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]; if (((mapArgs["-rpcpassword"] == "") || - (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword()) + (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && ChainParamsMigration::RequireRPCPassword()) { unsigned char rand_pwd[32]; RAND_bytes(rand_pwd, 32); - std::string strWhatAmI = "To use shadowcoind"; + std::string strWhatAmI = "To use aliaswalletd"; if (mapArgs.count("-server")) strWhatAmI = strprintf(_("To use the %s option"), "\"-server\""); else if (mapArgs.count("-daemon")) @@ -596,13 +597,13 @@ void StartRPCThreads() _("%s, you must set a rpcpassword in the configuration file:\n" "%s\n" "It is recommended you use the following random password:\n" - "rpcuser=shadowcoinrpc\n" + "rpcuser=aliasrpc\n" "rpcpassword=%s\n" "(you do not need to remember this password)\n" "The username and password MUST NOT be the same.\n" "If the file does not exist, create it with owner-readable-only file permissions.\n" "It is also recommended to set alertnotify so you are notified of problems;\n" - "for example: alertnotify=echo %%s | mail -s \"ShadowCoin Alert\" admin@foo.com\n"), + "for example: alertnotify=echo %%s | mail -s \"Alias Alert\" admin@foo.com\n"), strWhatAmI, GetConfigFile().string(), EncodeBase58(&rand_pwd[0],&rand_pwd[0]+32)), @@ -611,9 +612,14 @@ void StartRPCThreads() return; } - assert(rpc_io_service == NULL); + assert(rpc_io_service == nullptr); rpc_io_service = new asio::io_service(); - rpc_ssl_context = new ssl::context(*rpc_io_service, ssl::context::sslv23); + rpc_ssl_context = new ssl::context( +#if BOOST_VERSION <= 104800 + *rpc_io_service, +#endif + ssl::context::sslv23 + ); const bool fUseSSL = GetBoolArg("-rpcssl", false); @@ -621,24 +627,24 @@ void StartRPCThreads() { rpc_ssl_context->set_options(ssl::context::no_sslv2); - filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert")); - if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile; - if (filesystem::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string()); + fs::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert")); + if (!pathCertFile.is_absolute()) pathCertFile = fs::path(GetDataDir()) / pathCertFile; + if (fs::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string()); else LogPrintf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string()); - filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem")); - if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile; - if (filesystem::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem); + fs::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem")); + if (!pathPKFile.is_absolute()) pathPKFile = fs::path(GetDataDir()) / pathPKFile; + if (fs::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem); else LogPrintf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string()); string strCiphers = GetArg("-rpcsslciphers", "TLSv1.2+HIGH:TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH"); - SSL_CTX_set_cipher_list(rpc_ssl_context->impl(), strCiphers.c_str()); + SSL_CTX_set_cipher_list(rpc_ssl_context->native_handle(), strCiphers.c_str()); } // Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets const bool loopback = !mapArgs.count("-rpcallowip"); asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any(); - ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort())); + ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", ChainParamsMigration::GetRPCPort())); boost::system::error_code v6_only_error; boost::shared_ptr acceptor(new ip::tcp::acceptor(*rpc_io_service)); @@ -700,15 +706,19 @@ void StartRPCThreads() void StopRPCThreads() { - if (rpc_io_service == NULL) return; + if (rpc_io_service == nullptr) return; deadlineTimers.clear(); rpc_io_service->stop(); - if (rpc_worker_group != NULL) + if (rpc_worker_group != nullptr) rpc_worker_group->join_all(); - delete rpc_worker_group; rpc_worker_group = NULL; - delete rpc_ssl_context; rpc_ssl_context = NULL; - delete rpc_io_service; rpc_io_service = NULL; + delete rpc_worker_group; rpc_worker_group = nullptr; + delete rpc_ssl_context; rpc_ssl_context = nullptr; + delete rpc_io_service; rpc_io_service = nullptr; +} + +bool IsRPCServerRunning() { + return rpc_io_service != nullptr; } void RPCRunHandler(const boost::system::error_code& err, boost::function func) @@ -719,7 +729,7 @@ void RPCRunHandler(const boost::system::error_code& err, boost::function func, int64_t nSeconds) { - assert(rpc_io_service != NULL); + assert(rpc_io_service != nullptr); if (deadlineTimers.count(name) == 0) { @@ -727,7 +737,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 boost::shared_ptr(new deadline_timer(*rpc_io_service)))); } deadlineTimers[name]->expires_from_now(posix_time::seconds(nSeconds)); - deadlineTimers[name]->async_wait(boost::bind(RPCRunHandler, _1, func)); + deadlineTimers[name]->async_wait(boost::bind(RPCRunHandler, boost::placeholders::_1, func)); } CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address) @@ -748,7 +758,7 @@ CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address) boost::asio::ip::address_v6::bytes_type bytes = address.to_v6().to_bytes(); netaddr.SetRaw(NET_IPV6, &bytes[0]); }; - + return netaddr; } @@ -810,8 +820,8 @@ static Object JSONRPCExecOne(const Value& req) static string JSONRPCExecBatch(const Array& vReq) { Array ret; - for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++) - ret.push_back(JSONRPCExecOne(vReq[reqIdx])); + for (const auto& req : vReq) + ret.push_back(JSONRPCExecOne(req)); return write_string(Value(ret), false) + "\n"; } @@ -838,7 +848,7 @@ void ServiceConnection(AcceptedConnection *conn) } // Check authorization - if (mapHeaders.count("authorization") == 0) + if (mapHeaders.find("authorization") == mapHeaders.end()) { conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush; break; @@ -904,7 +914,7 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s const CRPCCommand *pcmd = tableRPC[strMethod]; if (!pcmd) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found"); - + if (pcmd->reqWallet && !pwalletMain) throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); diff --git a/src/rpcserver.h b/src/rpcserver.h index dfd20f96e5..6e5d273866 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -1,248 +1,228 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef _BITCOINRPC_SERVER_H_ -#define _BITCOINRPC_SERVER_H_ 1 +#ifndef BITCOIN_KERNEL_CHAINPARAMS_H +#define BITCOIN_KERNEL_CHAINPARAMS_H -#include "uint256.h" -#include "rpcprotocol.h" +#include +#include +#include // Alias uses CBlock from core.h +#include +#include +#include +#include -#include +#include +#include #include +#include +#include +#include +#include +#include +#include class CBlockIndex; -class CBlockThinIndex; -class CNetAddr; - -void StartRPCThreads(); -void StopRPCThreads(); - -/* - Type-check arguments; throws JSONRPCError if wrong type given. Does not check that - the right number of arguments are passed, just that any passed are the correct type. - Use like: RPCTypeCheck(params, boost::assign::list_of(str_type)(int_type)(obj_type)); -*/ -void RPCTypeCheck(const json_spirit::Array& params, - const std::list& typesExpected, bool fAllowNull=false); -/* - Check for expected keys/value types in an Object. - Use like: RPCTypeCheck(object, boost::assign::map_list_of("name", str_type)("value", int_type)); -*/ -void RPCTypeCheck(const json_spirit::Object& o, - const std::map& typesExpected, bool fAllowNull=false); - -/* - Run func nSeconds from now. Uses boost deadline timers. - Overrides previous timer (if any). - */ -void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds); +class CAddress; -//! Convert boost::asio address to CNetAddr -CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address); +struct CDNSSeedData { + std::string name, host; + CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {} +}; -typedef json_spirit::Value(*rpcfn_type)(const json_spirit::Array& params, bool fHelp); +typedef std::map MapCheckpoints; -class CRPCCommand -{ -public: - std::string name; - rpcfn_type actor; - bool okSafeMode; - bool threadSafe; - bool reqWallet; +struct CCheckpointData { + MapCheckpoints mapCheckpoints; + + int GetHeight() const { + const auto& final_checkpoint = mapCheckpoints.rbegin(); + return final_checkpoint->first /* height */; + } }; -class JSONRequest -{ -public: - json_spirit::Value id; - std::string strMethod; - json_spirit::Array params; +struct AssumeutxoHash : public BaseHash { + explicit AssumeutxoHash(const uint256& hash) : BaseHash(hash) {} +}; - JSONRequest() { id = json_spirit::Value::null; } - void parse(const json_spirit::Value& valRequest); +struct AssumeutxoData { + int height; + AssumeutxoHash hash_serialized; + unsigned int nChainTx; + uint256 blockhash; }; +struct ChainTxData { + int64_t nTime; + int64_t nTxCount; + double dTxRate; +}; /** - * Bitcoin RPC command dispatcher. + * CChainParams defines various tweakable parameters of a given instance of the + * Alias blockchain system. Modern structure with Alias-specific extensions. */ -class CRPCTable +class CChainParams { -private: - std::map mapCommands; public: - CRPCTable(); - const CRPCCommand* operator[](std::string name) const; - std::string help(std::string name) const; - - /** - * Execute a method. - * @param method Method to execute - * @param params Array of arguments (JSON objects) - * @returns Result of the call. - * @throws an exception (json_spirit::Value) when an error happens. - */ - json_spirit::Value execute(const std::string &method, const json_spirit::Array ¶ms) const; + enum Network { + MAIN, + TESTNET, + REGTEST, + MAX_NETWORK_TYPES + }; + + enum Base58Type { + PUBKEY_ADDRESS, + SCRIPT_ADDRESS, + SECRET_KEY, + STEALTH_ADDRESS, + EXT_PUBLIC_KEY, + EXT_SECRET_KEY, + EXT_KEY_HASH, + EXT_ACC_HASH, + EXT_PUBLIC_KEY_BTC, + EXT_SECRET_KEY_BTC, + MAX_BASE58_TYPES + }; + + const Consensus::Params& GetConsensus() const { return consensus; } + const MessageStartChars& MessageStart() const { return pchMessageStart; } + uint16_t GetDefaultPort() const { return nDefaultPort; } + + const CBlock& GenesisBlock() const { return genesis; } + bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } + bool IsTestChain() const { return m_chain_type != ChainType::MAIN; } + bool IsMockableChain() const { return m_is_mockable_chain; } + uint64_t PruneAfterHeight() const { return nPruneAfterHeight; } + uint64_t AssumedBlockchainSize() const { return m_assumed_blockchain_size; } + uint64_t AssumedChainStateSize() const { return m_assumed_chain_state_size; } + bool MineBlocksOnDemand() const { return consensus.fPowNoRetargeting; } + std::string GetChainTypeString() const { return ChainTypeToString(m_chain_type); } + ChainType GetChainType() const { return m_chain_type; } + const std::vector& DNSSeeds() const { return vSeeds; } + const std::vector& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } + const std::vector& FixedSeeds() const { return vFixedSeeds; } + const CCheckpointData& Checkpoints() const { return checkpointData; } + const ChainTxData& TxData() const { return chainTxData; } + + // Alias-specific methods (preserved from old structure) + const uint256& HashGenesisBlock() const { return hashGenesisBlock; } + const std::vector& AlertKey() const { return vAlertPubKey; } + int RPCPort() const { return nRPCPort; } + int BIP44ID() const { return nBIP44ID; } + int LastPOWBlock() const { return nLastPOWBlock; } + std::string NetworkIDString() const { return strNetworkID; } + const std::string& DataDir() const { return strDataDir; } + + // Alias PoS methods + bool IsProtocolV2(int nHeight) const { return nHeight > nFirstPosv2Block; } + bool IsProtocolV3(int nHeight) const { return nHeight > nFirstPosv3Block; } + + // Alias fork detection + bool IsForkV2(int64_t nTime) const { return nTime > nForkV2Time; } + bool IsForkV3(int64_t nTime) const { return nTime > nForkV3Time; } + bool IsForkV4(int64_t nTime) const { return nTime >= nForkV4Time; } + bool IsForkV4SupplyIncrease(const CBlockIndex* pindexPrev) const; + int GetForkId(int64_t nTime) const { + return (nTime >= nForkV4Time) ? 4 : (nTime > nForkV3Time) ? 3 : (nTime > nForkV2Time) ? 2 : 0; + } + + // Alias stake confirmation methods + int GetStakeMinConfirmations(int64_t nTime) const { + return IsForkV3(nTime) ? nStakeMinConfirmations : nStakeMinConfirmationsLegacy; + } + int GetAnonStakeMinConfirmations() const { return nStakeMinConfirmations; } + + // Alias reward methods + int64_t GetProofOfWorkReward(int nHeight, int64_t nFees) const; + int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, int64_t nFees) const; + int64_t GetProofOfAnonStakeReward(const CBlockIndex* pindexPrev, int64_t nFees) const; + + // Alias development fund addresses + const std::string GetDevContributionAddress() const { return devContributionAddress; } + const std::string GetSupplyIncreaseAddress() const { return supplyIncreaseAddress; } + + // Alias proof limits (using CBigNum for compatibility) + const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const CBigNum& ProofOfStakeLimit(int nHeight) const { + return IsProtocolV2(nHeight) ? bnProofOfStakeLimitV2 : bnProofOfStakeLimit; + } + const CBigNum BnProofOfWorkLimit() const { return bnProofOfWorkLimit; } + const CBigNum BnProofOfStakeLimit() const { return bnProofOfStakeLimit; } + + // Network selection + virtual Network NetworkID() const = 0; + virtual bool RequireRPCPassword() const { return true; } + + static std::unique_ptr RegTest(); + static std::unique_ptr Main(); + static std::unique_ptr TestNet(); + +protected: + CChainParams() {} + + Consensus::Params consensus; + MessageStartChars pchMessageStart; + uint16_t nDefaultPort; + uint64_t nPruneAfterHeight; + uint64_t m_assumed_blockchain_size; + uint64_t m_assumed_chain_state_size; + std::vector vSeeds; + std::vector base58Prefixes[MAX_BASE58_TYPES]; + ChainType m_chain_type; + CBlock genesis; + std::vector vFixedSeeds; // Alias uses CAddress + bool fDefaultConsistencyChecks; + bool m_is_mockable_chain; + CCheckpointData checkpointData; + std::vector m_assumeutxo_data; + ChainTxData chainTxData; + + // Alias-specific members + uint256 hashGenesisBlock; + std::vector vAlertPubKey; + std::string strNetworkID; + int nRPCPort; + int nBIP44ID; + std::string strDataDir; + + // Alias PoS parameters + int nLastPOWBlock; + int nFirstPosv2Block; + int nFirstPosv3Block; + CBigNum bnProofOfWorkLimit; + CBigNum bnProofOfStakeLimit; + CBigNum bnProofOfStakeLimitV2; + int nStakeMinConfirmationsLegacy; + int nStakeMinConfirmations; + + // Alias fork times + int64_t nForkV2Time; + int64_t nForkV3Time; + int64_t nForkV4Time; + + // Alias development addresses + std::string devContributionAddress; + std::string supplyIncreaseAddress; + + // Alias stake rewards (externally set, referenced in reward functions) + // These are set in state.cpp and referenced via extern }; -extern const CRPCTable tableRPC; - -extern void InitRPCMining(); -extern void ShutdownRPCMining(); - -extern int64_t nWalletUnlockTime; -extern int64_t AmountFromValue(const json_spirit::Value& value); -extern json_spirit::Value ValueFromAmount(int64_t amount); - -bool IsStringBoolPositive(std::string& value); -bool IsStringBoolNegative(std::string& value); -bool GetStringBool(std::string& value, bool &fOut); - -extern double GetDifficulty(const CBlockIndex* blockindex = NULL); -extern double GetHeaderDifficulty(const CBlockThinIndex* blockindex = NULL); - -extern double GetPoWMHashPS(); -extern double GetPoSKernelPS(); - -extern std::string HexBits(unsigned int nBits); -extern std::string HelpRequiringPassphrase(); -extern void EnsureWalletIsUnlocked(); - -// -// Utilities: convert hex-encoded Values -// (throws error if not hex). -// -extern uint256 ParseHashV(const json_spirit::Value& v, std::string strName); -extern uint256 ParseHashO(const json_spirit::Object& o, std::string strKey); -extern std::vector ParseHexV(const json_spirit::Value& v, std::string strName); -extern std::vector ParseHexO(const json_spirit::Object& o, std::string strKey); - -extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp -extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp -extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value sendalert(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value getsubsidy(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getstakesubsidy(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getmininginfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getstakinginfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value checkkernel(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getwork(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getworkex(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getblocktemplate(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value submitblock(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value getnewaddress(const json_spirit::Array& params, bool fHelp); // in rpcwallet.cpp -extern json_spirit::Value getnewextaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getaccountaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value setaccount(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getaccount(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getaddressesbyaccount(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendtoaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value signmessage(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value verifymessage(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getreceivedbyaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getreceivedbyaccount(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getbalance(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value movecmd(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendfrom(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendmany(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value addmultisigaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value createmultisig(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value addredeemscript(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listreceivedbyaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listreceivedbyaccount(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listtransactions(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value backupwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value keypoolrefill(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value walletpassphrase(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value walletpassphrasechange(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value walletlock(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value encryptwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value validateaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getinfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value reservebalance(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value checkwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value repairwallet(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value resendtx(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value validatepubkey(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnewpubkey(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp -extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value createrawtransaction(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value decoderawtransaction(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value decodescript(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value signrawtransaction(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendrawtransaction(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value getbestblockhash(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp -extern json_spirit::Value getblockcount(const json_spirit::Array& params, bool fHelp); // in rpcblockchain.cpp -extern json_spirit::Value getdifficulty(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value settxfee(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getrawmempool(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getblockbynumber(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value setbestblockbyheight(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value rewindchain(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value nextorphan(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getcheckpoint(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value getnewstealthaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value liststealthaddresses(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value importstealthaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendtostealthaddress(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value clearwallettransactions(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value scanforalltxns(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value scanforstealthtxns(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value sendsdctoanon(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendanontoanon(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value sendanontosdc(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value estimateanonfee(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value anonoutputs(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value anoninfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value reloadanondata(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value txnreport(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value smsgenable(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgdisable(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsglocalkeys(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgoptions(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgscanchain(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgscanbuckets(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgaddkey(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsggetpubkey(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgsend(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgsendanon(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsginbox(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgoutbox(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value smsgbuckets(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value thinscanmerkleblocks(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value thinforcestate(const json_spirit::Array& params, bool fHelp); - -extern json_spirit::Value extkey(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value mnemonic(const json_spirit::Array& params, bool fHelp); - -#endif +// Global functions for backward compatibility +const CChainParams &Params(); +const CChainParams &TestNetParams(); +const CChainParams &MainNetParams(); +void SelectParams(CChainParams::Network network); +bool SelectParamsFromCommandLine(); + +std::optional GetNetworkForMagic(const MessageStartChars& pchMessageStart); + +#endif // BITCOIN_KERNEL_CHAINPARAMS_H + diff --git a/src/rpcsmessage.cpp b/src/rpcsmessage.cpp deleted file mode 100644 index 0f6a6a81ef..0000000000 --- a/src/rpcsmessage.cpp +++ /dev/null @@ -1,929 +0,0 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "main.h" -#include "rpcserver.h" - -#include -#include -#include - -#include "smessage.h" -#include "init.h" -#include "util.h" - -using namespace json_spirit; - -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); - - - -Value smsgenable(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw std::runtime_error( - "smsgenable \n" - "Enable secure messaging."); - - if (fSecMsgEnabled) - throw std::runtime_error("Secure messaging is already enabled."); - - Object result; - result.push_back(Pair("result", (SecureMsgEnable() ? "Enabled secure messaging." : "Failed to enable secure messaging."))); - - return result; -} - -Value smsgdisable(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw std::runtime_error( - "smsgdisable \n" - "Disable secure messaging."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is already disabled."); - - Object result; - result.push_back(Pair("result", (SecureMsgDisable() ? "Disabled secure messaging." : "Failed to disable secure messaging."))); - - return result; -} - -Value smsgoptions(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 3) - throw std::runtime_error( - "smsgoptions [list |set ]\n" - "smsgoptions list 1\n" - " list possible options with descriptions.\n" - "List and manage options."); - - std::string mode = "list"; - if (params.size() > 0) - mode = params[0].get_str(); - - Object result; - - if (mode == "list") - { - bool fDescriptions = false; - if (params.size() > 1) - { - std::string value = params[1].get_str(); - fDescriptions = IsStringBoolPositive(value); - }; - - result.push_back(Pair("option", std::string("newAddressRecv = ") + (smsgOptions.fNewAddressRecv ? "true" : "false"))); - - if (fDescriptions) - result.push_back(Pair("newAddressRecv", "Enable receiving messages for newly created addresses.")); - result.push_back(Pair("option", std::string("newAddressAnon = ") + (smsgOptions.fNewAddressAnon ? "true" : "false"))); - - if (fDescriptions) - result.push_back(Pair("newAddressAnon", "Enable receiving anonymous messages for newly created addresses.")); - result.push_back(Pair("option", std::string("scanIncoming = ") + (smsgOptions.fScanIncoming ? "true" : "false"))); - - if (fDescriptions) - result.push_back(Pair("scanIncoming", "Scan incoming blocks for public keys.")); - - result.push_back(Pair("result", "Success.")); - } else - if (mode == "set") - { - if (params.size() < 3) - { - result.push_back(Pair("result", "Too few parameters.")); - result.push_back(Pair("expected", "set ")); - return result; - }; - - std::string optname = params[1].get_str(); - std::string value = params[2].get_str(); - - std::transform(optname.begin(), optname.end(), optname.begin(), ::tolower); - - bool fValue; - if (optname == "newaddressrecv") - { - if (GetStringBool(value, fValue)) - { - smsgOptions.fNewAddressRecv = fValue; - } else - { - result.push_back(Pair("result", "Unknown value.")); - return result; - }; - result.push_back(Pair("set option", std::string("newAddressRecv = ") + (smsgOptions.fNewAddressRecv ? "true" : "false"))); - } else - if (optname == "newaddressanon") - { - if (GetStringBool(value, fValue)) - { - smsgOptions.fNewAddressAnon = fValue; - } else - { - result.push_back(Pair("result", "Unknown value.")); - return result; - }; - result.push_back(Pair("set option", std::string("newAddressAnon = ") + (smsgOptions.fNewAddressAnon ? "true" : "false"))); - } else - if (optname == "scanincoming") - { - if (GetStringBool(value, fValue)) - { - smsgOptions.fScanIncoming = fValue; - } else - { - result.push_back(Pair("result", "Unknown value.")); - return result; - }; - result.push_back(Pair("set option", std::string("scanIncoming = ") + (smsgOptions.fScanIncoming ? "true" : "false"))); - } else - { - result.push_back(Pair("result", "Option not found.")); - return result; - }; - } else - { - result.push_back(Pair("result", "Unknown Mode.")); - result.push_back(Pair("expected", "smsgoption [list|set ]")); - }; - return result; -} - -Value smsglocalkeys(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 3) - throw std::runtime_error( - "smsglocalkeys [whitelist|all|wallet|recv <+/->
    |anon <+/->
    ]\n" - "List and manage keys."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - Object result; - - std::string mode = "whitelist"; - if (params.size() > 0) - { - mode = params[0].get_str(); - }; - - if (mode == "whitelist" - || mode == "all") - { - uint32_t nKeys = 0; - int all = mode == "all" ? 1 : 0; - Array keys; - - for (std::vector::iterator it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (!all - && !it->fReceiveEnabled) - continue; - - CBitcoinAddress coinAddress(it->sAddress); - if (!coinAddress.IsValid()) - continue; - - std::string sPublicKey; - - CKeyID keyID; - if (!coinAddress.GetKeyID(keyID)) - continue; - - CPubKey pubKey; - if (!pwalletMain->GetPubKey(keyID, pubKey)) - continue; - if (!pubKey.IsValid() - || !pubKey.IsCompressed()) - { - continue; - }; - - sPublicKey = EncodeBase58(pubKey.begin(), pubKey.end()); - - Object objM; - - std::string sLabel = pwalletMain->mapAddressBook[keyID]; - std::string sInfo; - if (all) - sInfo = std::string("Receive ") + (it->fReceiveEnabled ? "on, " : "off, "); - sInfo += std::string("Anon ") + (it->fReceiveAnon ? "on" : "off"); - //result.push_back(Pair("key", it->sAddress + " - " + sPublicKey + " " + sInfo + " - " + sLabel)); - objM.push_back(Pair("address", it->sAddress)); - objM.push_back(Pair("publickey",sPublicKey)); - objM.push_back(Pair("receive",(it->fReceiveEnabled ? "1" : "0"))); - objM.push_back(Pair("anon",(it->fReceiveAnon ? "1" : "0"))); - objM.push_back(Pair("label",sLabel)); - keys.push_back(objM); - - nKeys++; - }; - result.push_back(Pair("keys", keys)); - result.push_back(Pair("result", strprintf("%u", nKeys))); - } else - if (mode == "recv") - { - if (params.size() < 3) - { - result.push_back(Pair("result", "Too few parameters.")); - result.push_back(Pair("expected", "recv <+/->
    ")); - return result; - }; - - std::string op = params[1].get_str(); - std::string addr = params[2].get_str(); - - std::vector::iterator it; - for (it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (addr != it->sAddress) - continue; - break; - }; - - if (it == smsgAddresses.end()) - { - result.push_back(Pair("result", "Address not found.")); - return result; - }; - - if (op == "+" || op == "on" || op == "add" || op == "a") - { - it->fReceiveEnabled = true; - } else - if (op == "-" || op == "off" || op == "rem" || op == "r") - { - it->fReceiveEnabled = false; - } else - { - result.push_back(Pair("result", "Unknown operation.")); - return result; - }; - - std::string sInfo; - sInfo = std::string("Receive ") + (it->fReceiveEnabled ? "on, " : "off,"); - sInfo += std::string("Anon ") + (it->fReceiveAnon ? "on" : "off"); - result.push_back(Pair("result", "Success.")); - result.push_back(Pair("key", it->sAddress + " " + sInfo)); - return result; - - } else - if (mode == "anon") - { - if (params.size() < 3) - { - result.push_back(Pair("result", "Too few parameters.")); - result.push_back(Pair("expected", "anon <+/->
    ")); - return result; - }; - - std::string op = params[1].get_str(); - std::string addr = params[2].get_str(); - - std::vector::iterator it; - for (it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (addr != it->sAddress) - continue; - break; - }; - - if (it == smsgAddresses.end()) - { - result.push_back(Pair("result", "Address not found.")); - return result; - }; - - if (op == "+" || op == "on" || op == "add" || op == "a") - { - it->fReceiveAnon = true; - } else - if (op == "-" || op == "off" || op == "rem" || op == "r") - { - it->fReceiveAnon = false; - } else - { - result.push_back(Pair("result", "Unknown operation.")); - return result; - }; - - std::string sInfo; - sInfo = std::string("Receive ") + (it->fReceiveEnabled ? "on, " : "off,"); - sInfo += std::string("Anon ") + (it->fReceiveAnon ? "on" : "off"); - result.push_back(Pair("result", "Success.")); - result.push_back(Pair("key", it->sAddress + " " + sInfo)); - return result; - - } else - if (mode == "wallet") - { - uint32_t nKeys = 0; - Array keys; - - BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& entry, pwalletMain->mapAddressBook) - { - if (!IsDestMine(*pwalletMain, entry.first)) - continue; - - CBitcoinAddress coinAddress(entry.first); - if (!coinAddress.IsValid()) - continue; - - std::string address; - std::string sPublicKey; - address = coinAddress.ToString(); - - CKeyID keyID; - if (!coinAddress.GetKeyID(keyID)) - continue; - - CPubKey pubKey; - if (!pwalletMain->GetPubKey(keyID, pubKey)) - continue; - if (!pubKey.IsValid() - || !pubKey.IsCompressed()) - { - continue; - }; - - sPublicKey = EncodeBase58(pubKey.begin(), pubKey.end()); - - Object objM; - - objM.push_back(Pair("key", address)); - objM.push_back(Pair("publickey", sPublicKey)); - objM.push_back(Pair("label", entry.second)); - - keys.push_back(objM); - nKeys++; - }; - result.push_back(Pair("keys", keys)); - result.push_back(Pair("result", strprintf("%u", nKeys))); - } else - { - result.push_back(Pair("result", "Unknown Mode.")); - result.push_back(Pair("expected", "smsglocalkeys [whitelist|all|wallet|recv <+/->
    |anon <+/->
    ]")); - }; - - return result; -}; - -Value smsgscanchain(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw std::runtime_error( - "smsgscanchain \n" - "Look for public keys in the block chain."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - Object result; - if (!SecureMsgScanBlockChain()) - { - result.push_back(Pair("result", "Scan Chain Failed.")); - } else - { - result.push_back(Pair("result", "Scan Chain Completed.")); - }; - return result; -} - -Value smsgscanbuckets(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw std::runtime_error( - "smsgscanbuckets \n" - "Force rescan of all messages in the bucket store."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - if (pwalletMain->IsLocked()) - throw std::runtime_error("Wallet is locked."); - - Object result; - if (!SecureMsgScanBuckets()) - { - result.push_back(Pair("result", "Scan Buckets Failed.")); - } else - { - result.push_back(Pair("result", "Scan Buckets Completed.")); - }; - return result; -} - -Value smsgaddkey(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 2) - throw std::runtime_error( - "smsgaddkey
    \n" - "Add address, pubkey pair to database."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - std::string addr = params[0].get_str(); - std::string pubk = params[1].get_str(); - - Object result; - int rv = SecureMsgAddAddress(addr, pubk); - if (rv != 0) - { - result.push_back(Pair("result", "Public key not added to db.")); - switch (rv) - { - case 2: result.push_back(Pair("reason", "publicKey is invalid.")); break; - case 3: result.push_back(Pair("reason", "publicKey does not match address.")); break; - case 4: result.push_back(Pair("reason", "address is already in db.")); break; - case 5: result.push_back(Pair("reason", "address is invalid.")); break; - default: result.push_back(Pair("reason", "error.")); break; - }; - } else - { - result.push_back(Pair("result", "Added public key to db.")); - }; - - return result; -} - -Value smsggetpubkey(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw std::runtime_error( - "smsggetpubkey
    \n" - "Return the base58 encoded compressed public key for an address.\n" - "Tests localkeys first, then looks in public key db.\n"); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - std::string address = params[0].get_str(); - std::string publicKey; - - Object result; - int rv = SecureMsgGetLocalPublicKey(address, publicKey); - switch (rv) - { - case 0: - result.push_back(Pair("result", "Success.")); - result.push_back(Pair("address", address)); - result.push_back(Pair("publickey", publicKey)); - return result; // success, don't check db - case 2: - case 3: - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Invalid address.")); - return result; - case 4: - break; // check db - //case 1: - default: - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Error.")); - return result; - }; - - CBitcoinAddress coinAddress(address); - - - CKeyID keyID; - if (!coinAddress.GetKeyID(keyID)) - { - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Invalid address.")); - return result; - }; - - CPubKey cpkFromDB; - rv = SecureMsgGetStoredKey(keyID, cpkFromDB); - - switch (rv) - { - case 0: - if (!cpkFromDB.IsValid() - || !cpkFromDB.IsCompressed()) - { - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Invalid address.")); - } else - { - //cpkFromDB.SetCompressedPubKey(); // make sure key is compressed - publicKey = EncodeBase58(cpkFromDB.begin(), cpkFromDB.end()); - - result.push_back(Pair("result", "Success.")); - result.push_back(Pair("address", address)); - result.push_back(Pair("publickey", publicKey)); - }; - break; - case 2: - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Address not found in wallet or db.")); - return result; - //case 1: - default: - result.push_back(Pair("result", "Failed.")); - result.push_back(Pair("message", "Error, GetStoredKey().")); - return result; - }; - - return result; -} - -Value smsgsend(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 3) - throw std::runtime_error( - "smsgsend \n" - "Send an encrypted message from addrFrom to addrTo."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - std::string addrFrom = params[0].get_str(); - std::string addrTo = params[1].get_str(); - std::string msg = params[2].get_str(); - - - Object result; - - std::string sError; - if (SecureMsgSend(addrFrom, addrTo, msg, sError) != 0) - { - result.push_back(Pair("result", "Send failed.")); - result.push_back(Pair("error", sError)); - } else - result.push_back(Pair("result", "Sent.")); - - return result; -} - -Value smsgsendanon(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 2) - throw std::runtime_error( - "smsgsendanon \n" - "Send an anonymous encrypted message to addrTo."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - std::string addrFrom = "anon"; - std::string addrTo = params[0].get_str(); - std::string msg = params[1].get_str(); - - - Object result; - std::string sError; - if (SecureMsgSend(addrFrom, addrTo, msg, sError) != 0) - { - result.push_back(Pair("result", "Send failed.")); - result.push_back(Pair("error", sError)); - } else - result.push_back(Pair("result", "Sent.")); - - return result; -} - -Value smsginbox(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) // defaults to read - throw std::runtime_error( - "smsginbox [all|unread|clear]\n" - "Decrypt and display all received messages.\n" - "Warning: clear will delete all messages."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - if (pwalletMain->IsLocked()) - throw std::runtime_error("Wallet is locked."); - - std::string mode = "unread"; - if (params.size() > 0) - { - mode = params[0].get_str(); - }; - - - Object result; - - std::vector vchKey; - vchKey.resize(16); - memset(&vchKey[0], 0, 16); - - { - LOCK(cs_smsgDB); - - SecMsgDB dbInbox; - - if (!dbInbox.Open("cr+")) - throw std::runtime_error("Could not open DB."); - - uint32_t nMessages = 0; - char cbuf[256]; - - std::string sPrefix("im"); - unsigned char chKey[18]; - - if (mode == "clear") - { - dbInbox.TxnBegin(); - - leveldb::Iterator* it = dbInbox.pdb->NewIterator(leveldb::ReadOptions()); - while (dbInbox.NextSmesgKey(it, sPrefix, chKey)) - { - dbInbox.EraseSmesg(chKey); - nMessages++; - }; - delete it; - dbInbox.TxnCommit(); - - result.push_back(Pair("result", strprintf("Deleted %u messages.", nMessages))); - } else - if (mode == "all" - || mode == "unread") - { - int fCheckReadStatus = mode == "unread" ? 1 : 0; - - SecMsgStored smsgStored; - MessageData msg; - - dbInbox.TxnBegin(); - - leveldb::Iterator* it = dbInbox.pdb->NewIterator(leveldb::ReadOptions()); - Array messageList; - - while (dbInbox.NextSmesg(it, sPrefix, chKey, smsgStored)) - { - if (fCheckReadStatus - && !(smsgStored.status & SMSG_MASK_UNREAD)) - continue; - - uint32_t nPayload = smsgStored.vchMessage.size() - SMSG_HDR_LEN; - if (SecureMsgDecrypt(false, smsgStored.sAddrTo, &smsgStored.vchMessage[0], &smsgStored.vchMessage[SMSG_HDR_LEN], nPayload, msg) == 0) - { - Object objM; - objM.push_back(Pair("success", "1")); - objM.push_back(Pair("received", getTimeString(smsgStored.timeReceived, cbuf, sizeof(cbuf)))); - objM.push_back(Pair("sent", getTimeString(msg.timestamp, cbuf, sizeof(cbuf)))); - objM.push_back(Pair("from", msg.sFromAddress)); - objM.push_back(Pair("to", smsgStored.sAddrTo)); - objM.push_back(Pair("text", std::string((char*)&msg.vchMessage[0]))); // ugh - - messageList.push_back(objM); - } else - { - Object objM; - objM.push_back(Pair("success", "0")); - messageList.push_back(objM); - }; - - if (fCheckReadStatus) - { - smsgStored.status &= ~SMSG_MASK_UNREAD; - dbInbox.WriteSmesg(chKey, smsgStored); - }; - nMessages++; - }; - delete it; - dbInbox.TxnCommit(); - - - result.push_back(Pair("messages", messageList)); - result.push_back(Pair("result", strprintf("%u", nMessages))); - - } else - { - result.push_back(Pair("result", "Unknown Mode.")); - result.push_back(Pair("expected", "[all|unread|clear].")); - }; - } - - return result; -}; - -Value smsgoutbox(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) // defaults to read - throw std::runtime_error( - "smsgoutbox [all|clear]\n" - "Decrypt and display all sent messages.\n" - "Warning: clear will delete all sent messages."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - if (pwalletMain->IsLocked()) - throw std::runtime_error("Wallet is locked."); - - std::string mode = "all"; - if (params.size() > 0) - { - mode = params[0].get_str(); - } - - - Object result; - - std::string sPrefix("sm"); - unsigned char chKey[18]; - memset(&chKey[0], 0, 18); - - { - LOCK(cs_smsgDB); - - SecMsgDB dbOutbox; - - if (!dbOutbox.Open("cr+")) - throw std::runtime_error("Could not open DB."); - - uint32_t nMessages = 0; - char cbuf[256]; - - if (mode == "clear") - { - dbOutbox.TxnBegin(); - - leveldb::Iterator* it = dbOutbox.pdb->NewIterator(leveldb::ReadOptions()); - while (dbOutbox.NextSmesgKey(it, sPrefix, chKey)) - { - dbOutbox.EraseSmesg(chKey); - nMessages++; - }; - delete it; - dbOutbox.TxnCommit(); - - - result.push_back(Pair("result", strprintf("Deleted %u messages.", nMessages))); - } else - if (mode == "all") - { - SecMsgStored smsgStored; - MessageData msg; - leveldb::Iterator* it = dbOutbox.pdb->NewIterator(leveldb::ReadOptions()); - - Array messageList; - - while (dbOutbox.NextSmesg(it, sPrefix, chKey, smsgStored)) - { - uint32_t nPayload = smsgStored.vchMessage.size() - SMSG_HDR_LEN; - - if (SecureMsgDecrypt(false, smsgStored.sAddrOutbox, &smsgStored.vchMessage[0], &smsgStored.vchMessage[SMSG_HDR_LEN], nPayload, msg) == 0) - { - Object objM; - objM.push_back(Pair("success", "1")); - objM.push_back(Pair("sent", getTimeString(msg.timestamp, cbuf, sizeof(cbuf)))); - objM.push_back(Pair("from", msg.sFromAddress)); - objM.push_back(Pair("to", smsgStored.sAddrTo)); - objM.push_back(Pair("text", std::string((char*)&msg.vchMessage[0]))); // ugh - - messageList.push_back(objM); - } else - { - Object objM; - objM.push_back(Pair("success", "0")); - messageList.push_back(objM); - }; - nMessages++; - }; - delete it; - - result.push_back(Pair("messages" ,messageList)); - result.push_back(Pair("result", strprintf("%u", nMessages))); - } else - { - result.push_back(Pair("result", "Unknown Mode.")); - result.push_back(Pair("expected", "[all|clear].")); - }; - } - - return result; -}; - - -Value smsgbuckets(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw std::runtime_error( - "smsgbuckets [stats|dump]\n" - "Display some statistics."); - - if (!fSecMsgEnabled) - throw std::runtime_error("Secure messaging is disabled."); - - std::string mode = "stats"; - if (params.size() > 0) - { - mode = params[0].get_str(); - }; - - Object result; - - char cbuf[256]; - if (mode == "stats") - { - uint32_t nBuckets = 0; - uint32_t nMessages = 0; - uint64_t nBytes = 0; - { - LOCK(cs_smsg); - std::map::iterator it; - it = smsgBuckets.begin(); - - for (it = smsgBuckets.begin(); it != smsgBuckets.end(); ++it) - { - std::set& tokenSet = it->second.setTokens; - - std::string sBucket = boost::lexical_cast(it->first); - std::string sFile = sBucket + "_01.dat"; - - std::string sHash = boost::lexical_cast(it->second.hash); - - nBuckets++; - nMessages += tokenSet.size(); - - Object objM; - objM.push_back(Pair("bucket", sBucket)); - objM.push_back(Pair("time", getTimeString(it->first, cbuf, sizeof(cbuf)))); - objM.push_back(Pair("no. messages", strprintf("%u", tokenSet.size()))); - objM.push_back(Pair("hash", sHash)); - objM.push_back(Pair("last changed", getTimeString(it->second.timeChanged, cbuf, sizeof(cbuf)))); - - boost::filesystem::path fullPath = GetDataDir() / "smsgStore" / sFile; - - - if (!boost::filesystem::exists(fullPath)) - { - // -- If there is a file for an empty bucket something is wrong. - if (tokenSet.size() == 0) - objM.push_back(Pair("file size", "Empty bucket.")); - else - objM.push_back(Pair("file size, error", "File not found.")); - } else - { - try { - - uint64_t nFBytes = 0; - nFBytes = boost::filesystem::file_size(fullPath); - nBytes += nFBytes; - objM.push_back(Pair("file size", bytesReadable(nFBytes))); - } catch (const boost::filesystem::filesystem_error& ex) - { - objM.push_back(Pair("file size, error", ex.what())); - }; - }; - - result.push_back(Pair("bucket", objM)); - }; - }; // LOCK(cs_smsg); - - - std::string snBuckets = boost::lexical_cast(nBuckets); - std::string snMessages = boost::lexical_cast(nMessages); - - Object objM; - objM.push_back(Pair("buckets", snBuckets)); - objM.push_back(Pair("messages", snMessages)); - objM.push_back(Pair("size", bytesReadable(nBytes))); - result.push_back(Pair("total", objM)); - - } else - if (mode == "dump") - { - { - LOCK(cs_smsg); - std::map::iterator it; - it = smsgBuckets.begin(); - - for (it = smsgBuckets.begin(); it != smsgBuckets.end(); ++it) - { - std::string sFile = boost::lexical_cast(it->first) + "_01.dat"; - - try { - boost::filesystem::path fullPath = GetDataDir() / "smsgStore" / sFile; - boost::filesystem::remove(fullPath); - } catch (const boost::filesystem::filesystem_error& ex) - { - //objM.push_back(Pair("file size, error", ex.what())); - LogPrintf("Error removing bucket file %s.\n", ex.what()); - }; - }; - smsgBuckets.clear(); - }; // LOCK(cs_smsg); - - result.push_back(Pair("result", "Removed all buckets.")); - - } else - { - result.push_back(Pair("result", "Unknown Mode.")); - result.push_back(Pair("expected", "[stats|dump].")); - }; - - - return result; -}; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index cb3d47c876..b52afc73f0 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "wallet.h" #include "walletdb.h" @@ -11,7 +14,6 @@ #include "txdb.h" #include "stealth.h" #include "ringsig.h" -#include "smessage.h" #include using namespace json_spirit; @@ -48,7 +50,7 @@ void EnsureWalletIsUnlocked() throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Wallet is unlocked for staking only."); } -void WalletTxToJSON(const CWalletTx& wtx, Object& entry) +void WalletTxToJSON(const CWalletTx& wtx, Object& entry, bool listNarrations=true) { entry.push_back(Pair("version", wtx.nVersion)); int confirms = wtx.GetDepthInMainChain(); @@ -79,8 +81,9 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) entry.push_back(Pair("time", (int64_t)wtx.GetTxTime())); entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); - BOOST_FOREACH(const PAIRTYPE(std::string,std::string)& item, wtx.mapValue) - entry.push_back(Pair(item.first, item.second)); + for (const auto& item : wtx.mapValue) + if (listNarrations || item.first.substr(0,2) != "n_") + entry.push_back(Pair(item.first, item.second)); } std::string AccountFromValue(const Value& value) @@ -121,10 +124,8 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("debugpos", fDebugPoS)); obj.push_back(Pair("debugringsig", fDebugRingSig)); - obj.push_back(Pair("datadir", GetDataDir().string())); - obj.push_back(Pair("walletfile", pwalletMain->strWalletFile)); obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); obj.push_back(Pair("walletcrypted", pwalletMain->IsCrypted())); @@ -144,13 +145,26 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("mode", std::string(GetNodeModeName(nNodeMode)))); obj.push_back(Pair("state", nNodeMode == NT_THIN ? std::string(GetNodeStateName(nNodeState)) : "Full Node")); - obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); - obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); - obj.push_back(Pair("shadowbalance", ValueFromAmount(pwalletMain->GetShadowBalance()))); - obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); - obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); - obj.push_back(Pair("reserve", ValueFromAmount(nReserveBalance))); + obj.push_back(Pair("protocolversion", (int)PROTOCOL_VERSION)); + obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); + int64_t balancePublic = pwalletMain->GetBalance(), balancePrivate = pwalletMain->GetSpectreBalance(); + obj.push_back(Pair("balance", ValueFromAmount(balancePublic + balancePrivate))); + obj.push_back(Pair("balance_public", ValueFromAmount(balancePublic))); + obj.push_back(Pair("balance_private", ValueFromAmount(balancePrivate))); + obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); + int64_t stakePublic = pwalletMain->GetStake(), stakePrivate = pwalletMain->GetSpectreStake(); + obj.push_back(Pair("stake", ValueFromAmount(stakePublic + stakePrivate))); + obj.push_back(Pair("stake_public", ValueFromAmount(stakePublic))); + obj.push_back(Pair("stake_private", ValueFromAmount(stakePrivate))); + int64_t unconfirmedBalPublic = pwalletMain->GetUnconfirmedBalance(), unconfirmedBalPrivate = pwalletMain->GetUnconfirmedSpectreBalance(); + obj.push_back(Pair("unconfirmedbalance", ValueFromAmount(unconfirmedBalPublic + unconfirmedBalPrivate))); + obj.push_back(Pair("unconfirmedbalance_public", ValueFromAmount(unconfirmedBalPublic))); + obj.push_back(Pair("unconfirmedbalance_private",ValueFromAmount(unconfirmedBalPrivate))); + int64_t stakeweightPublic = pwalletMain->GetStakeWeight(), stakeweightPrivate = pwalletMain->GetSpectreStakeWeight(); + obj.push_back(Pair("stakeweight", ValueFromAmount(stakeweightPublic + stakeweightPrivate))); + obj.push_back(Pair("stakeweight_public", ValueFromAmount(stakeweightPublic))); + obj.push_back(Pair("stakeweight_private", ValueFromAmount(stakeweightPrivate))); + obj.push_back(Pair("reserve", ValueFromAmount(nReserveBalance))); obj.push_back(Pair("blocks", (int)nBestHeight)); if (nNodeMode == NT_THIN) @@ -160,8 +174,10 @@ Value getinfo(const Array& params, bool fHelp) if (nNodeMode == NT_FULL) { - obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); - obj.push_back(Pair("shadowsupply", ValueFromAmount(pindexBest->nAnonSupply))); + int64_t moneysupply_total = pindexBest->nMoneySupply, moneysupply_private = pindexBest->nAnonSupply; + obj.push_back(Pair("moneysupply", ValueFromAmount(moneysupply_total))); + obj.push_back(Pair("moneysupply_public", ValueFromAmount(moneysupply_total - moneysupply_private))); + obj.push_back(Pair("moneysupply_private", ValueFromAmount(moneysupply_private))); } obj.push_back(Pair("connections", (int)vNodes.size())); @@ -219,7 +235,7 @@ Value getnewpubkey(const Array& params, bool fHelp) throw std::runtime_error("NewKeyFromAccount failed."); CKeyID keyID = newKey.GetID(); - pwalletMain->SetAddressBookName(keyID, strAccount, NULL, true, true); + pwalletMain->SetAddressBookName(keyID, strAccount, nullptr, true, true); return HexStr(newKey.begin(), newKey.end()); } @@ -230,7 +246,7 @@ Value getnewaddress(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw std::runtime_error( "getnewaddress [account]\n" - "Returns a new ShadowCoin address for receiving payments. " + "Returns a new Alias address for receiving payments. " "If [account] is specified, it is added to the address book " "so payments received with the address will be credited to [account]."); @@ -246,7 +262,7 @@ Value getnewaddress(const Array& params, bool fHelp) throw std::runtime_error("NewKeyFromAccount failed."); CKeyID keyID = newKey.GetID(); - pwalletMain->SetAddressBookName(keyID, strAccount, NULL, true, true); + pwalletMain->SetAddressBookName(keyID, strAccount, nullptr, true, true); return CBitcoinAddress(keyID).ToString(); } @@ -256,7 +272,7 @@ Value getnewextaddress(const Array& params, bool fHelp) if (fHelp || params.size() > 1) throw std::runtime_error( "getnewextaddress [label]\n" - "Returns a new ShadowCoin ext address for receiving payments." + "Returns a new Alias ext address for receiving payments." "If [label] is specified, it is added to the address book. "); std::string strLabel; @@ -271,7 +287,7 @@ Value getnewextaddress(const Array& params, bool fHelp) delete sek; throw std::runtime_error("NewExtKeyFromAccount failed."); }; - pwalletMain->SetAddressBookName(sek->kp, strLabel, NULL, true, true); + pwalletMain->SetAddressBookName(sek->kp, strLabel, nullptr, true, true); // - CBitcoinAddress displays public key only return CBitcoinAddress(sek->kp).ToString(); @@ -294,12 +310,12 @@ CBitcoinAddress GetAccountAddress(std::string strAccount, bool bForceNew=false) { CScript scriptPubKey; scriptPubKey.SetDestination(account.vchPubKey.GetID()); - for (std::map::iterator it = pwalletMain->mapWallet.begin(); - it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid(); - ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (!account.vchPubKey.IsValid()) + break; + const CWalletTx& wtx = item.second; + for (const CTxOut& txout : wtx.vout) if (txout.scriptPubKey == scriptPubKey) bKeyUsed = true; } @@ -327,7 +343,7 @@ Value getaccountaddress(const Array& params, bool fHelp) if (fHelp || params.size() != 1) throw std::runtime_error( "getaccountaddress \n" - "Returns the current ShadowCoin address for receiving payments to this account."); + "Returns the current Alias address for receiving payments to this account."); // Parse the account first so we don't generate a key if there's an error std::string strAccount = AccountFromValue(params[0]); @@ -345,12 +361,12 @@ Value setaccount(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw std::runtime_error( - "setaccount \n" + "setaccount \n" "Sets the account associated with the given address."); CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); std::string strAccount; @@ -375,12 +391,12 @@ Value getaccount(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw std::runtime_error( - "getaccount \n" + "getaccount \n" "Returns the account associated with the given address."); CBitcoinAddress address(params[0].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); std::string strAccount; std::map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); @@ -401,7 +417,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp) // Find all addresses that have the given account Array ret; - BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, pwalletMain->mapAddressBook) + for (const auto& item : pwalletMain->mapAddressBook) { const CBitcoinAddress& address = item.first; const std::string& strName = item.second; @@ -415,8 +431,8 @@ Value sendtoaddress(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 5) throw std::runtime_error( - "sendtoaddress [comment] [comment-to] [narration]\n" // Exchanges use the comments internally... - "sendtoaddress [narration]\n" + "sendtoaddress [comment] [comment-to] [narration]\n" // Exchanges use the comments internally... + "sendtoaddress [narration]\n" " is a real and is rounded to the nearest 0.000001" + HelpRequiringPassphrase()); @@ -424,13 +440,12 @@ Value sendtoaddress(const Array& params, bool fHelp) if (params[0].get_str().length() > 75 && IsStealthAddress(params[0].get_str())) - return sendtostealthaddress(params, false); - + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Only private Alias can be send to a private address, use sendprivate instead"); std::string sAddrIn = params[0].get_str(); CBitcoinAddress address(sAddrIn); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); // Amount int64_t nAmount = AmountFromValue(params[1]); @@ -467,10 +482,10 @@ Value listaddressgroupings(const Array& params, bool fHelp) Array jsonGroupings; std::map balances = pwalletMain->GetAddressBalances(); - BOOST_FOREACH(std::set grouping, pwalletMain->GetAddressGroupings()) + for (const std::set& grouping : pwalletMain->GetAddressGroupings()) { Array jsonGrouping; - BOOST_FOREACH(CTxDestination address, grouping) + for (const CTxDestination& address : grouping) { Array addressInfo; addressInfo.push_back(CBitcoinAddress(address).ToString()); @@ -491,7 +506,7 @@ Value signmessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) throw std::runtime_error( - "signmessage \n" + "signmessage \n" "Sign a message with the private key of an address"); EnsureWalletIsUnlocked(); @@ -526,7 +541,7 @@ Value verifymessage(const Array& params, bool fHelp) { if (fHelp || params.size() != 3) throw std::runtime_error( - "verifymessage \n" + "verifymessage \n" "Verify a signed message"); std::string strAddress = params[0].get_str(); @@ -563,14 +578,14 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw std::runtime_error( - "getreceivedbyaddress [minconf=1]\n" - "Returns the total amount received by in transactions with at least [minconf] confirmations."); + "getreceivedbyaddress [minconf=1]\n" + "Returns the total amount received by in transactions with at least [minconf] confirmations."); // Bitcoin address CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); CScript scriptPubKey; if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); scriptPubKey.SetDestination(address.Get()); if (!IsMine(*pwalletMain,scriptPubKey)) return (double)0.0; @@ -582,13 +597,13 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) // Tally int64_t nAmount = 0; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) if (txout.scriptPubKey == scriptPubKey) if (wtx.GetDepthInMainChain() >= nMinDepth) nAmount += txout.nValue; @@ -600,8 +615,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) void GetAccountAddresses(std::string strAccount, std::set& setAddress) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& item, pwalletMain->mapAddressBook) - { + for (const auto& item : pwalletMain->mapAddressBook) { const CTxDestination& address = item.first; const std::string& strName = item.second; if (strName == strAccount) @@ -630,13 +644,13 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) // Tally int64_t nAmount = 0; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*pwalletMain, address) && setAddress.count(address)) @@ -654,9 +668,9 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, in int64_t nBalance = 0; // Tally wallet transactions - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; if (!wtx.IsFinal() || wtx.GetDepthInMainChain() < 0) continue; @@ -702,24 +716,24 @@ Value getbalance(const Array& params, bool fHelp) // (GetBalance() sums up all unspent TxOuts) // getbalance and getbalance '*' 0 should return the same number. int64_t nBalance = 0; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; if (!wtx.IsTrusted()) continue; int64_t allFee; std::string strSentAccount; - std::list > listReceived; - std::list > listSent; - wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); + std::list listReceived; + std::list listSent; + wtx.GetDestinationDetails(listReceived, listSent, allFee, strSentAccount); if (wtx.GetDepthInMainChain() >= nMinDepth && wtx.GetBlocksToMaturity() == 0) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) - nBalance += r.second; + for(const auto & destination : listReceived) + nBalance += destination.amount; }; - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listSent) - nBalance -= r.second; + for(const auto & destination : listSent) + nBalance -= destination.amount; nBalance -= allFee; }; return ValueFromAmount(nBalance); @@ -792,7 +806,7 @@ Value sendfrom(const Array& params, bool fHelp) { if (fHelp || params.size() < 3 || params.size() > 7) throw std::runtime_error( - "sendfrom [minconf=1] [comment] [comment-to] [narration] \n" + "sendfrom [minconf=1] [comment] [comment-to] [narration] \n" " is a real and is rounded to the nearest 0.000001" + HelpRequiringPassphrase()); @@ -801,7 +815,7 @@ Value sendfrom(const Array& params, bool fHelp) std::string strAccount = AccountFromValue(params[0]); CBitcoinAddress address(params[1].get_str()); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid ShadowCoin address"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Alias address"); int64_t nAmount = AmountFromValue(params[2]); int nMinDepth = 1; @@ -841,7 +855,7 @@ Value sendmany(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 4) throw std::runtime_error( - "sendmany {address:amount,...} [minconf=1] [comment]\n" + "sendmany {public_address:amount,...} [minconf=1] [comment]\n" "amounts are double-precision floating point numbers" + HelpRequiringPassphrase()); @@ -860,11 +874,11 @@ Value sendmany(const Array& params, bool fHelp) std::vector > vecSend; int64_t totalAmount = 0; - BOOST_FOREACH(const Pair& s, sendTo) + for (const Pair& s : sendTo) { CBitcoinAddress address(s.name_); if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid ShadowCoin address: ")+s.name_); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Alias address: ")+s.name_); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ")+s.name_); @@ -970,7 +984,7 @@ Value addmultisigaddress(const Array& params, bool fHelp) { std::string msg = "addmultisigaddress <'[\"key\",\"key\"]'> [account]\n" "Add a nrequired-to-sign multisignature address to the wallet\"\n" - "each key is a ShadowCoin address or hex-encoded public key\n" + "each key is a Alias address or hex-encoded public key\n" "If [account] is specified, assign address to [account]."; throw std::runtime_error(msg); }; @@ -999,7 +1013,7 @@ Value createmultisig(const Array& params, bool fHelp) std::string msg = "addmultisigaddress <'[\"key\",\"key\"]'> [account]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "Returns a json object with the address and redeemScript.\n" - "Each key is a ShadowCoin address or hex-encoded public key.\n" + "Each key is a Alias address or hex-encoded public key.\n" "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n" @@ -1078,9 +1092,9 @@ Value ListReceived(const Array& params, bool fByAccounts) // Tally std::map mapTally; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; if (wtx.IsCoinBase() || wtx.IsCoinStake() || !wtx.IsFinal()) continue; @@ -1089,7 +1103,7 @@ Value ListReceived(const Array& params, bool fByAccounts) if (nDepth < nMinDepth) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) { CTxDestination address; if (!ExtractDestination(txout.scriptPubKey, address) || !IsDestMine(*pwalletMain, address)) @@ -1104,7 +1118,7 @@ Value ListReceived(const Array& params, bool fByAccounts) // Reply Array ret; std::map mapAccountTally; - BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, std::string)& item, pwalletMain->mapAddressBook) + for (const auto& item : pwalletMain->mapAddressBook) { const CBitcoinAddress& address = item.first; const std::string& strAccount = item.second; @@ -1138,12 +1152,12 @@ Value ListReceived(const Array& params, bool fByAccounts) if (fByAccounts) { - for (std::map::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it) + for (const auto& item : mapAccountTally) { - int64_t nAmount = (*it).second.nAmount; - int nConf = (*it).second.nConf; + int64_t nAmount = item.second.nAmount; + int nConf = item.second.nConf; Object obj; - obj.push_back(Pair("account", (*it).first)); + obj.push_back(Pair("account", item.first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); ret.push_back(obj); @@ -1188,35 +1202,58 @@ Value listreceivedbyaccount(const Array& params, bool fHelp) static void MaybePushAddress(Object & entry, const CTxDestination &dest) { - CBitcoinAddress addr; - if (addr.Set(dest)) - entry.push_back(Pair("address", addr.ToString())); + if (dest.type() == typeid(CStealthAddress)) { + entry.push_back(Pair("address", boost::get(dest).Encoded())); + } + else { + CBitcoinAddress addr; + if (addr.Set(dest)) + entry.push_back(Pair("address", addr.ToString())); + } } void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, Array& ret) { int64_t nFee; std::string strSentAccount; - std::list > listReceived; - std::list > listSent; + std::list listReceived; + std::list listSent; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetDestinationDetails(listReceived, listSent, nFee, strSentAccount); bool fAllAccounts = (strAccount == std::string("*")); // Sent - if ((!wtx.IsCoinStake()) && (!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) + if (!listSent.empty() && wtx.GetBlocksToMaturity() == 0 && (fAllAccounts || strAccount == strSentAccount)) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) + for(const auto & destination : listSent) { + std::string category = "send"; + if (wtx.IsCoinStake()) + { + // only add contributions/donations + std::string strAddress = CBitcoinAddress(destination.address).ToString(); + if (strAddress != ChainParamsMigration::GetDevContributionAddress() && strAddress != ChainParamsMigration::GetSupplyIncreaseAddress()) + continue; + if (wtx.GetDepthAndHeightInMainChain().second % 6 == 0) + category = "contributed"; + else + category = "donated"; + } Object entry; entry.push_back(Pair("account", strSentAccount)); - MaybePushAddress(entry, s.first); - entry.push_back(Pair("category", "send")); - entry.push_back(Pair("amount", ValueFromAmount(-s.second))); - entry.push_back(Pair("fee", ValueFromAmount(-nFee))); + MaybePushAddress(entry, destination.address); + entry.push_back(Pair("category", category)); + entry.push_back(Pair("amount", ValueFromAmount(-destination.amount))); + if (destination.vout) + entry.push_back(Pair("vout", (int)destination.vout.value_or(-1))); + if (!(wtx.IsCoinBase() || wtx.IsCoinStake())) + entry.push_back(Pair("fee", ValueFromAmount(-nFee))); + entry.push_back(Pair("currency", destination.currency == PRIVATE ? "PRIVATE" : "PUBLIC")); + if (!destination.narration.empty()) + entry.push_back(Pair("narration", destination.narration)); if (fLong) - WalletTxToJSON(wtx, entry); + WalletTxToJSON(wtx, entry, false); ret.push_back(entry); }; }; @@ -1225,17 +1262,23 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) { bool stop = false; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) + for(const auto & destination : listReceived) { std::string account; - if (pwalletMain->mapAddressBook.count(r.first)) - account = pwalletMain->mapAddressBook[r.first]; + if (destination.address.type() == typeid(CStealthAddress)) + { + CStealthAddress stealthAddress = boost::get(destination.address); + account = stealthAddress.label; + } + else if (pwalletMain->mapAddressBook.count(destination.address)) + account = pwalletMain->mapAddressBook[destination.address]; + if (fAllAccounts || (account == strAccount)) { Object entry; entry.push_back(Pair("account", account)); - MaybePushAddress(entry, r.first); + MaybePushAddress(entry, destination.address); if (wtx.IsCoinBase() || wtx.IsCoinStake()) { if (wtx.GetDepthInMainChain() < 1) @@ -1252,15 +1295,19 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n if (!wtx.IsCoinStake()) { - entry.push_back(Pair("amount", ValueFromAmount(r.second))); + entry.push_back(Pair("amount", ValueFromAmount(destination.amount))); } else { entry.push_back(Pair("amount", ValueFromAmount(-nFee))); stop = true; // only one coinstake output }; - + if (destination.vout) + entry.push_back(Pair("vout", (int)destination.vout.value_or(-1))); + entry.push_back(Pair("currency", (destination.currency == PRIVATE ? "PRIVATE" : "PUBLIC"))); + if (!destination.narration.empty()) + entry.push_back(Pair("narration", destination.narration)); if (fLong) - WalletTxToJSON(wtx, entry); + WalletTxToJSON(wtx, entry, false); ret.push_back(entry); }; if (stop) @@ -1327,11 +1374,11 @@ Value listtransactions(const Array& params, bool fHelp) { CWalletTx *const pwtx = (*it).second.first; - if (pwtx != 0) + if (pwtx != nullptr) ListTransactions(*pwtx, strAccount, 0, true, ret); CAccountingEntry *const pacentry = (*it).second.second; - if (pacentry != 0) + if (pacentry != nullptr) AcentryToJSON(*pacentry, strAccount, ret); if ((int)ret.size() >= (nCount+nFrom)) break; @@ -1369,46 +1416,46 @@ Value listaccounts(const Array& params, bool fHelp) nMinDepth = params[0].get_int(); std::map mapAccountBalances; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& entry, pwalletMain->mapAddressBook) + for (const auto& entry : pwalletMain->mapAddressBook) { if (IsDestMine(*pwalletMain, entry.first)) // This address belongs to me mapAccountBalances[entry.second] = 0; }; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (const auto& item : pwalletMain->mapWallet) { - const CWalletTx& wtx = (*it).second; + const CWalletTx& wtx = item.second; int64_t nFee; std::string strSentAccount; - std::list > listReceived; - std::list > listSent; + std::list listReceived; + std::list listSent; int nDepth = wtx.GetDepthInMainChain(); if (nDepth < 0) continue; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetDestinationDetails(listReceived, listSent, nFee, strSentAccount); mapAccountBalances[strSentAccount] -= nFee; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) - mapAccountBalances[strSentAccount] -= s.second; + for(const auto & destination : listSent) + mapAccountBalances[strSentAccount] -= destination.amount; if (nDepth >= nMinDepth && wtx.GetBlocksToMaturity() == 0) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& r, listReceived) - if (pwalletMain->mapAddressBook.count(r.first)) - mapAccountBalances[pwalletMain->mapAddressBook[r.first]] += r.second; + for(const auto & destination : listReceived) + if (pwalletMain->mapAddressBook.count(destination.address)) + mapAccountBalances[pwalletMain->mapAddressBook[destination.address]] += destination.amount; else - mapAccountBalances[""] += r.second; + mapAccountBalances[""] += destination.amount; }; }; std::list acentries; CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries); - BOOST_FOREACH(const CAccountingEntry& entry, acentries) + for (const CAccountingEntry& entry : acentries) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; Object ret; - BOOST_FOREACH(const PAIRTYPE(std::string, int64_t)& accountBalance, mapAccountBalances) + for (const auto& accountBalance : mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); }; @@ -1422,7 +1469,7 @@ Value listsinceblock(const Array& params, bool fHelp) "listsinceblock [blockhash] [target-confirmations]\n" "Get all transactions in blocks since block [blockhash], or all transactions if omitted"); - CBlockIndex *pindex = NULL; + CBlockIndex *pindex = nullptr; int target_confirms = 1; if (params.size() > 0) @@ -1445,9 +1492,9 @@ Value listsinceblock(const Array& params, bool fHelp) Array transactions; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++) + for (const auto& item : pwalletMain->mapWallet) { - CWalletTx tx = (*it).second; + CWalletTx tx = item.second; if (depth == -1 || tx.GetDepthInMainChain() < depth) ListTransactions(tx, "*", 0, true, transactions); @@ -1512,11 +1559,11 @@ Value gettransaction(const Array& params, bool fHelp) } else { CTransaction tx; - uint256 hashBlock = 0; + uint256 hashBlock = uint256(); if (GetTransaction(hash, tx, hashBlock)) { - TxToJSON(tx, 0, entry); - if (hashBlock == 0) + TxToJSON(tx, uint256(), entry); + if (hashBlock == uint256()) { entry.push_back(Pair("confirmations", 0)); } else @@ -1601,6 +1648,11 @@ Value walletpassphrase(const Array& params, bool fHelp) if (!pwalletMain->IsLocked()) throw JSONRPCError(RPC_WALLET_ALREADY_UNLOCKED, "Error: Wallet is already unlocked, use walletlock first if need to change unlock settings."); + + if (!IsRPCServerRunning()) { + throw JSONRPCError(RPC_SERVER_NOT_STARTED, "Error: To use the walletpassphrase you need to start the wallet with argument -server. Start the wallet with -server argument and try again.\n"); + } + // Note that the walletpassphrase is stored in params[0] which is not mlock()ed SecureString strWalletPass; strWalletPass.reserve(100); @@ -1623,7 +1675,11 @@ Value walletpassphrase(const Array& params, bool fHelp) int64_t nSleepTime = params[1].get_int64(); LOCK(cs_nWalletUnlockTime); nWalletUnlockTime = GetTime() + nSleepTime; - RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime); + try { + RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime); + } catch (std::runtime_error &e) { + throw e; + } // ppcoin: if user OS account compromised prevent trivial sendmoney commands if (params.size() > 2) @@ -1720,7 +1776,7 @@ Value encryptwallet(const Array& params, bool fHelp) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; ShadowCoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; + return "wallet encrypted; Alias server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; } class DescribeAddressVisitor : public boost::static_visitor @@ -1750,7 +1806,7 @@ class DescribeAddressVisitor : public boost::static_visitor obj.push_back(Pair("script", GetTxnOutputType(whichType))); obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) + for (const CTxDestination& addr : addresses) a.push_back(CBitcoinAddress(addr).ToString()); obj.push_back(Pair("addresses", a)); if (whichType == TX_MULTISIG) @@ -1775,8 +1831,8 @@ Value validateaddress(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw std::runtime_error( - "validateaddress \n" - "Return information about ."); + "validateaddress \n" + "Return information about ."); CBitcoinAddress address(params[0].get_str()); bool isValid = address.IsValid(); @@ -1806,8 +1862,8 @@ Value validatepubkey(const Array& params, bool fHelp) { if (fHelp || !params.size() || params.size() > 2) throw std::runtime_error( - "validatepubkey \n" - "Return information about ."); + "validatepubkey \n" + "Return information about ."); std::vector vchPubKey = ParseHex(params[0].get_str()); CPubKey pubKey(vchPubKey); @@ -1964,12 +2020,12 @@ Value makekeypair(const Array& params, bool fHelp) -Value getnewstealthaddress(const Array& params, bool fHelp) +Value getnewprivateaddress(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw std::runtime_error( - "getnewstealthaddress [label]\n" - "Returns a new ShadowCoin stealth address for receiving payments anonymously." + "getnewprivateaddress [label]\n" + "Returns a new Alias private address for receiving payments anonymously." + HelpRequiringPassphrase()); if (pwalletMain->IsLocked()) @@ -1988,11 +2044,11 @@ Value getnewstealthaddress(const Array& params, bool fHelp) return akStealth.ToStealthAddress(); } -Value liststealthaddresses(const Array& params, bool fHelp) +Value listprivateaddresses(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw std::runtime_error( - "liststealthaddresses [show_secrets=0]\n" + "listprivateaddresses [show_secrets=0]\n" "List owned stealth addresses."); bool fShowSecrets = false; @@ -2080,11 +2136,11 @@ Value liststealthaddresses(const Array& params, bool fHelp) return result; } -Value importstealthaddress(const Array& params, bool fHelp) +Value importprivateaddress(const Array& params, bool fHelp) { if (fHelp || params.size() < 2) throw std::runtime_error( - "importstealthaddress [label]\n" + "importprivateaddress [label]\n" "Import an owned stealth addresses." + HelpRequiringPassphrase()); @@ -2189,198 +2245,27 @@ Value importstealthaddress(const Array& params, bool fHelp) return result; } - -Value sendtostealthaddress(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 5) - throw std::runtime_error( - "sendtostealthaddress [comment] [comment-to] [narration]\n" - "sendtostealthaddress [narration]\n" - " is a real and is rounded to the nearest 0.000001" - + HelpRequiringPassphrase()); - - if (pwalletMain->IsLocked()) - throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); - - std::string sEncoded = params[0].get_str(); - int64_t nAmount = AmountFromValue(params[1]); - - std::string sNarr; - if (params.size() == 3 || params.size() == 5) - { - int nNarr = params.size() - 1; - if(params[nNarr].type() != null_type && !params[nNarr].get_str().empty()) - sNarr = params[nNarr].get_str(); - } - - if (sNarr.length() > 24) - throw std::runtime_error("Narration must be 24 characters or less."); - - CStealthAddress sxAddr; - - if (!sxAddr.SetEncoded(sEncoded)) - throw std::runtime_error("Invalid ShadowCoin stealth address."); - - CWalletTx wtx; - if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) - wtx.mapValue["comment"] = params[3].get_str(); - if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty()) - wtx.mapValue["to"] = params[4].get_str(); - - std::string sError; - if (!pwalletMain->SendStealthMoneyToDestination(sxAddr, nAmount, sNarr, wtx, sError)) - throw JSONRPCError(RPC_WALLET_ERROR, sError); - - return wtx.GetHash().GetHex(); -} - Value clearwallettransactions(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw std::runtime_error( "clearwallettransactions [unaccepted]\n" "[unaccepted] optional to deleted unaccepted stakes only\n" - "delete all transactions from wallet - reload with reloadanondata\n" + "delete all transactions from wallet - reload with scanforalltxns\n" "Warning: Backup your wallet first!"); - Object result; - - uint32_t nTransactions = 0; - bool fUnaccepted = false; if (params.size() > 0) fUnaccepted = params[0].get_bool(); - char cbuf[256]; - - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - CWalletDB walletdb(pwalletMain->strWalletFile); - walletdb.TxnBegin(); - Dbc* pcursor = walletdb.GetTxnCursor(); - if (!pcursor) - throw std::runtime_error("Cannot get wallet DB cursor"); - - Dbt datKey; - Dbt datValue; - - datKey.set_flags(DB_DBT_USERMEM); - datValue.set_flags(DB_DBT_USERMEM); - - std::vector vchKey; - std::vector vchType; - std::vector vchKeyData; - std::vector vchValueData; - - vchKeyData.resize(100); - vchValueData.resize(100); - - datKey.set_ulen(vchKeyData.size()); - datKey.set_data(&vchKeyData[0]); - - datValue.set_ulen(vchValueData.size()); - datValue.set_data(&vchValueData[0]); - - unsigned int fFlags = DB_NEXT; // same as using DB_FIRST for new cursor - while (true) - { - int ret = pcursor->get(&datKey, &datValue, fFlags); - - if (ret == ENOMEM - || ret == DB_BUFFER_SMALL) - { - if (datKey.get_size() > datKey.get_ulen()) - { - vchKeyData.resize(datKey.get_size()); - datKey.set_ulen(vchKeyData.size()); - datKey.set_data(&vchKeyData[0]); - }; - - if (datValue.get_size() > datValue.get_ulen()) - { - vchValueData.resize(datValue.get_size()); - datValue.set_ulen(vchValueData.size()); - datValue.set_data(&vchValueData[0]); - }; - // -- try once more, when DB_BUFFER_SMALL cursor is not expected to move - ret = pcursor->get(&datKey, &datValue, fFlags); - }; - - if (ret == DB_NOTFOUND) - break; - else - if (datKey.get_data() == NULL || datValue.get_data() == NULL - || ret != 0) - { - snprintf(cbuf, sizeof(cbuf), "wallet DB error %d, %s", ret, db_strerror(ret)); - throw std::runtime_error(cbuf); - }; - - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - ssValue.SetType(SER_DISK); - ssValue.clear(); - ssValue.write((char*)datKey.get_data(), datKey.get_size()); - - ssValue >> vchType; - - - std::string strType(vchType.begin(), vchType.end()); - - //LogPrintf("strType %s\n", strType.c_str()); - - if (strType == "tx") - { - uint256 hash; - ssValue >> hash; - - if (fUnaccepted) - { - const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - if (!wtx.IsInMainChain()) - { - if ((ret = pcursor->del(0)) != 0) - { - LogPrintf("Delete transaction failed %d, %s\n", ret, db_strerror(ret)); - continue; - } - pwalletMain->mapWallet.erase(hash); - pwalletMain->NotifyTransactionChanged(pwalletMain, hash, CT_DELETED); - nTransactions++; - } - continue; - } - - if ((ret = pcursor->del(0)) != 0) - { - LogPrintf("Delete transaction failed %d, %s\n", ret, db_strerror(ret)); - continue; - } - - pwalletMain->mapWallet.erase(hash); - pwalletMain->NotifyTransactionChanged(pwalletMain, hash, CT_DELETED); - - nTransactions++; - }; - }; - pcursor->close(); - walletdb.TxnCommit(); - - //pwalletMain->mapWallet.clear(); - - if (nNodeMode == NT_THIN) - { - // reset LastFilteredHeight - walletdb.WriteLastFilteredHeight(0); - } - } - + uint32_t nTransactions = pwalletMain->ClearWalletTransactions(fUnaccepted); + Object result; + char cbuf[256]; snprintf(cbuf, sizeof(cbuf), "Removed %u transactions.", nTransactions); result.push_back(Pair("complete", std::string(cbuf))); - result.push_back(Pair("", "Reload with reloadanondata, reindex or re-download blockchain.")); - + result.push_back(Pair("", "Reload with scanforalltxns, reindex or re-download blockchain.")); return result; } @@ -2392,62 +2277,20 @@ Value scanforalltxns(const Array& params, bool fHelp) "scanforalltxns [fromHeight]\n" "Scan blockchain for owned transactions."); - if (nNodeMode != NT_FULL) throw std::runtime_error("Can't run in thin mode."); - Object result; - int32_t nFromHeight = 0; - - CBlockIndex *pindex = pindexGenesisBlock; - - if (params.size() > 0) - nFromHeight = params[0].get_int(); - - if (nFromHeight > 0) - { - pindex = mapBlockIndex[hashBestChain]; - while (pindex->nHeight > nFromHeight - && pindex->pprev) - pindex = pindex->pprev; - }; - - if (pindex == NULL) - throw std::runtime_error("Genesis Block is not set."); - - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - pwalletMain->MarkDirty(); - - pwalletMain->ScanForWalletTransactions(pindex, true); - pwalletMain->ReacceptWalletTransactions(); - } // cs_main, pwalletMain->cs_wallet - - result.push_back(Pair("result", "Scan complete.")); - - return result; -} - -Value scanforstealthtxns(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 1) - throw std::runtime_error( - "scanforstealthtxns [fromHeight]\n" - "Scan blockchain for owned stealth transactions."); + if (pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); Object result; - uint32_t nBlocks = 0; - uint32_t nTransactions = 0; int32_t nFromHeight = 0; CBlockIndex *pindex = pindexGenesisBlock; - if (params.size() > 0) nFromHeight = params[0].get_int(); - if (nFromHeight > 0) { pindex = mapBlockIndex[hashBestChain]; @@ -2456,36 +2299,21 @@ Value scanforstealthtxns(const Array& params, bool fHelp) pindex = pindex->pprev; }; - if (pindex == NULL) + if (pindex == nullptr) throw std::runtime_error("Genesis Block is not set."); - // -- locks in AddToWalletIfInvolvingMe - - bool fUpdate = true; // todo: option? - pwalletMain->nStealth = 0; pwalletMain->nFoundStealth = 0; - while (pindex) { - nBlocks++; - CBlock block; - block.ReadFromDisk(pindex, true); - - BOOST_FOREACH(CTransaction& tx, block.vtx) - { - if (!tx.IsStandard()) - continue; // leave out coinbase and others - nTransactions++; + LOCK2(cs_main, pwalletMain->cs_wallet); - uint256 hash = tx.GetHash(); - pwalletMain->AddToWalletIfInvolvingMe(tx, hash, &block, fUpdate); - }; + pwalletMain->MarkDirty(); + pwalletMain->ScanForWalletTransactions(pindex, true); + pwalletMain->ReacceptWalletTransactions(); - pindex = pindex->pnext; - }; + } // cs_main, pwalletMain->cs_wallet - LogPrintf("Scanned %u blocks, %u transactions\n", nBlocks, nTransactions); LogPrintf("Found %u stealth transactions in blockchain.\n", pwalletMain->nStealth); LogPrintf("Found %u new owned stealth transactions.\n", pwalletMain->nFoundStealth); @@ -2498,12 +2326,11 @@ Value scanforstealthtxns(const Array& params, bool fHelp) return result; } - -Value sendsdctoanon(const Array& params, bool fHelp) +Value sendpublictoprivate(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 5) throw std::runtime_error( - "sendsdctoanon [narration] [comment] [comment-to]\n" + "sendpublictoprivate [narration] [comment] [comment-to]\n" " is a real number and is rounded to the nearest 0.000001" + HelpRequiringPassphrase()); @@ -2524,7 +2351,12 @@ Value sendsdctoanon(const Array& params, bool fHelp) CStealthAddress sxAddr; if (!sxAddr.SetEncoded(sEncoded)) - throw std::runtime_error("Invalid ShadowCoin stealth address."); + throw std::runtime_error("Invalid Alias private address."); + + // -- Check that we own the recipient address (XSPEC to SPECTRE only allowed for transformation) + if (!pwalletMain->IsMine(sxAddr)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transfer ALIAS from public to private is only allowed within your account."); + } CWalletTx wtx; if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) @@ -2533,22 +2365,22 @@ Value sendsdctoanon(const Array& params, bool fHelp) wtx.mapValue["to"] = params[4].get_str(); std::string sError; - if (!pwalletMain->SendSdcToAnon(sxAddr, nAmount, sNarr, wtx, sError)) + if (!pwalletMain->SendSpecToAnon(sxAddr, nAmount, sNarr, wtx, sError)) { - LogPrintf("SendSdcToAnon failed %s\n", sError.c_str()); + LogPrintf("SendSpecToAnon failed %s\n", sError.c_str()); throw JSONRPCError(RPC_WALLET_ERROR, sError); }; return wtx.GetHash().GetHex(); } -Value sendanontoanon(const Array& params, bool fHelp) +Value sendprivate(const Array& params, bool fHelp) { if (fHelp || params.size() < 3 || params.size() > 6) throw std::runtime_error( - "sendanontoanon [narration] [comment] [comment-to]\n" + "sendprivate [narration] [comment] [comment-to]\n" " is a real number and is rounded to the nearest 0.000001\n" " is a number of outputs of the same amount to include in the signature\n" - " warning: using a ring_size less than 3 is not recommended" + " warning: using a ring_size other than 10 is not possible" + HelpRequiringPassphrase()); if (pwalletMain->IsLocked()) @@ -2561,11 +2393,15 @@ Value sendanontoanon(const Array& params, bool fHelp) Object result; std::ostringstream ssThrow; - if (nRingSize < MIN_RING_SIZE) - result.push_back(Pair("warning", "Ring size was below the recommended size, your existing will be marked as compromised.")); - - if (nRingSize > MAX_RING_SIZE) - ssThrow << "Ring size must be >= " << MIN_RING_SIZE << " and <= " << MAX_RING_SIZE << ".", throw std::runtime_error(ssThrow.str()); + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (nRingSize < nMinRingSize || nRingSize > nMaxRingSize) + { + if (nMinRingSize == nMaxRingSize) + ssThrow << "Ring size must be = " << nMinRingSize << "."; + else + ssThrow << "Ring size must be >= " << nMinRingSize << " and <= " << nMaxRingSize << "."; + throw std::runtime_error(ssThrow.str()); + } std::string sNarr; @@ -2578,7 +2414,7 @@ Value sendanontoanon(const Array& params, bool fHelp) CStealthAddress sxAddr; if (!sxAddr.SetEncoded(sEncoded)) - throw std::runtime_error("Invalid ShadowCoin stealth address."); + throw std::runtime_error("Invalid Alias private address."); CWalletTx wtx; if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty()) @@ -2602,13 +2438,14 @@ Value sendanontoanon(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } -Value sendanontosdc(const Array& params, bool fHelp) +Value sendprivatetopublic(const Array& params, bool fHelp) { if (fHelp || params.size() < 3 || params.size() > 6) throw std::runtime_error( - "sendanontosdc [narration] [comment] [comment-to]\n" + "sendprivatetopublic [narration] [comment] [comment-to]\n" " is a real number and is rounded to the nearest 0.000001\n" - " is a number of outputs of the same amount to include in the signature" + " is a number of outputs of the same amount to include in the signature\n" + " warning: using a ring_size other than 10 is not possible" + HelpRequiringPassphrase()); if (pwalletMain->IsLocked()) @@ -2620,9 +2457,15 @@ Value sendanontosdc(const Array& params, bool fHelp) uint32_t nRingSize = (uint32_t)params[2].get_int(); std::ostringstream ssThrow; - if (nRingSize < 1 || nRingSize > MAX_RING_SIZE) - ssThrow << "Ring size must be >= 1 and <= " << MAX_RING_SIZE << ".", throw std::runtime_error(ssThrow.str()); - + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (nRingSize < nMinRingSize || nRingSize > nMaxRingSize) + { + if (nMinRingSize == nMaxRingSize) + ssThrow << "Ring size must be = " << nMinRingSize << "."; + else + ssThrow << "Ring size must be >= " << nMinRingSize << " and <= " << nMaxRingSize << "."; + throw std::runtime_error(ssThrow.str()); + } std::string sNarr; if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) @@ -2634,7 +2477,12 @@ Value sendanontosdc(const Array& params, bool fHelp) CStealthAddress sxAddr; if (!sxAddr.SetEncoded(sEncoded)) - throw std::runtime_error("Invalid ShadowCoin stealth address."); + throw std::runtime_error("Invalid Alias private address."); + + // -- Check that we own the recipient address (SPECTRE to XSPEC only allowed for transformation) + if (!pwalletMain->IsMine(sxAddr)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transfer ALIAS from private to public is only allowed within your account."); + } CWalletTx wtx; if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty()) @@ -2644,19 +2492,19 @@ Value sendanontosdc(const Array& params, bool fHelp) std::string sError; - if (!pwalletMain->SendAnonToSdc(sxAddr, nAmount, nRingSize, sNarr, wtx, sError)) + if (!pwalletMain->SendAnonToSpec(sxAddr, nAmount, nRingSize, sNarr, wtx, sError)) { - LogPrintf("SendAnonToSdc failed %s\n", sError.c_str()); + LogPrintf("SendAnonToSpec failed %s\n", sError.c_str()); throw JSONRPCError(RPC_WALLET_ERROR, sError); }; return wtx.GetHash().GetHex(); } -Value estimateanonfee(const Array& params, bool fHelp) +Value estimateprivatefee(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 3) throw std::runtime_error( - "estimateanonfee [narration]\n" + "estimateprivatefee [narration]\n" "is a real number and is rounded to the nearest 0.000001\n" " is a number of outputs of the same amount to include in the signature"); @@ -2665,8 +2513,15 @@ Value estimateanonfee(const Array& params, bool fHelp) uint32_t nRingSize = (uint32_t)params[1].get_int(); std::ostringstream ssThrow; - if (nRingSize < MIN_RING_SIZE || nRingSize > MAX_RING_SIZE) - ssThrow << "Ring size must be >= " << MIN_RING_SIZE << " and <= " << MAX_RING_SIZE << ".", throw std::runtime_error(ssThrow.str()); + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (nRingSize < nMinRingSize || nRingSize > nMaxRingSize) + { + if (nMinRingSize == nMaxRingSize) + ssThrow << "Ring size must be = " << nMinRingSize << "."; + else + ssThrow << "Ring size must be >= " << nMinRingSize << " and <= " << nMaxRingSize << "."; + throw std::runtime_error(ssThrow.str()); + } std::string sNarr; @@ -2698,11 +2553,11 @@ Value estimateanonfee(const Array& params, bool fHelp) return result; } -Value anonoutputs(const Array& params, bool fHelp) +Value privateoutputs(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw std::runtime_error( - "anonoutputs [systemTotals] [show_immature_outputs]\n" + "privateoutputs [systemTotals] [show_immature_outputs]\n" "[systemTotals] if true displays the total no. of coins in the system."); if (nNodeMode != NT_FULL) @@ -2716,16 +2571,16 @@ Value anonoutputs(const Array& params, bool fHelp) fSystemTotals = true; }; - bool fMatureOnly = true; + CWallet::MaturityFilter nFilter = CWallet::MaturityFilter::FOR_SPENDING; if (params.size() > 1) { std::string value = params[1].get_str(); if (IsStringBoolPositive(value)) - fMatureOnly = false; + nFilter = CWallet::MaturityFilter::NONE; }; std::list lAvailableCoins; - if (pwalletMain->ListUnspentAnonOutputs(lAvailableCoins, fMatureOnly) != 0) + if (pwalletMain->ListUnspentAnonOutputs(lAvailableCoins, nFilter) != 0) throw std::runtime_error("ListUnspentAnonOutputs() failed."); @@ -2740,17 +2595,17 @@ Value anonoutputs(const Array& params, bool fHelp) int64_t nTotal = 0; int64_t nLast = 0; int nCount = 0; - for (std::list::iterator it = lAvailableCoins.begin(); it != lAvailableCoins.end(); ++it) + for (const COwnedAnonOutput& coin : lAvailableCoins) { - if (nLast > 0 && it->nValue != nLast) + if (nLast > 0 && coin.nValue != nLast) { snprintf(cbuf, sizeof(cbuf), "%3d", nCount); result.push_back(Pair(cbuf, ValueFromAmount(nLast))); nCount = 0; }; nCount++; - nLast = it->nValue; - nTotal += it->nValue; + nLast = coin.nValue; + nTotal += coin.nValue; }; if (nCount > 0) @@ -2762,10 +2617,10 @@ Value anonoutputs(const Array& params, bool fHelp) } else { std::map mOutputCounts; - for (std::list::iterator it = lAvailableCoins.begin(); it != lAvailableCoins.end(); ++it) - mOutputCounts[it->nValue] = 0; + for (const COwnedAnonOutput& coin : lAvailableCoins) + mOutputCounts[coin.nValue] = 0; - if (pwalletMain->CountAnonOutputs(mOutputCounts, fMatureOnly) != 0) + if (pwalletMain->CountAnonOutputs(mOutputCounts, nFilter) != 0) throw std::runtime_error("CountAnonOutputs() failed."); result.push_back(Pair("No. of coins owned, No. of system coins available", "amount")); @@ -2775,9 +2630,9 @@ Value anonoutputs(const Array& params, bool fHelp) int64_t nLast = 0; int64_t nCount = 0; int64_t nSystemCount; - for (std::list::iterator it = lAvailableCoins.begin(); it != lAvailableCoins.end(); ++it) + for (const COwnedAnonOutput& coin : lAvailableCoins) { - if (nLast > 0 && it->nValue != nLast) + if (nLast > 0 && coin.nValue != nLast) { nSystemCount = mOutputCounts[nLast]; std::string str = strprintf("%4d, %4d", nCount, nSystemCount); @@ -2785,8 +2640,8 @@ Value anonoutputs(const Array& params, bool fHelp) nCount = 0; }; nCount++; - nLast = it->nValue; - nTotal += it->nValue; + nLast = coin.nValue; + nTotal += coin.nValue; }; if (nCount > 0) @@ -2801,18 +2656,16 @@ Value anonoutputs(const Array& params, bool fHelp) return result; } -Value anoninfo(const Array& params, bool fHelp) +Value privateinfo(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw std::runtime_error( - "anoninfo [recalculate]\n" + "privateinfo [recalculate]\n" "list outputs in system."); if (nNodeMode != NT_FULL) throw std::runtime_error("Must be in full mode."); - bool fMatureOnly = false; // TODO: add parameter - bool fRecalculate = false; if (params.size() > 0) @@ -2828,101 +2681,63 @@ Value anoninfo(const Array& params, bool fHelp) if (fRecalculate) { - if (pwalletMain->CountAllAnonOutputs(lOutputCounts, fMatureOnly) != 0) + if (pwalletMain->CountAllAnonOutputs(lOutputCounts, nBestHeight) != 0) throw std::runtime_error("CountAllAnonOutputs() failed."); } else { // TODO: make mapAnonOutputStats a vector preinitialised with all possible coin values? - for (std::map::iterator mi = mapAnonOutputStats.begin(); mi != mapAnonOutputStats.end(); ++mi) + for (auto & [nValue, anonOutputCount] : mapAnonOutputStats) { - bool fProcessed = false; - CAnonOutputCount aoc = mi->second; - if (aoc.nLeastDepth > 0) - aoc.nLeastDepth = nBestHeight - aoc.nLeastDepth; - for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) - { - if (aoc.nValue > it->nValue) - continue; - lOutputCounts.insert(it, aoc); - fProcessed = true; - break; - }; - if (!fProcessed) - lOutputCounts.push_back(aoc); + anonOutputCount.nValue = nValue; // make sure nValue is correctly set + lOutputCounts.push_back(anonOutputCount); }; }; - result.push_back(Pair("No. Exists, No. Spends, No. Compromised, Least Depth", "value")); + result.push_back(Pair("No.Exists, No.Mature, No.Unspends, No.Mixins, No.MixinsStaking, No.Stakes, No.Compromised, Compromised Height, Least Depth", "value")); // -- lOutputCounts is ordered by value char cbuf[256]; - int64_t nTotalIn = 0; - int64_t nTotalOut = 0; - int64_t nTotalCompromised = 0; int64_t nTotalCoins = 0; - for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) - { - snprintf(cbuf, sizeof(cbuf), "%5d, %5d, %7d, %3d", it->nExists, it->nSpends, it->nCompromised, it->nLeastDepth); - result.push_back(Pair(cbuf, ValueFromAmount(it->nValue))); - - - nTotalIn += it->nValue * it->nExists; - nTotalOut += it->nValue * it->nSpends; - nTotalCompromised += it->nValue * it->nCompromised; - nTotalCoins += it->nExists; + int64_t nTotalIn = 0, nOutputsIn = 0; + int64_t nTotalOut = 0, nOutputsOut = 0; + int64_t nTotalCompromised = 0, nOutputsCompromised = 0; + int64_t nTotalMature = 0, nOutputsMature = 0; + int64_t nTotalStakes = 0, nOutputsStakes = 0; + for (const CAnonOutputCount& count : lOutputCounts) + { + snprintf(cbuf, sizeof(cbuf), "%5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %3d", + count.nExists, count.nMature, count.nExists - count.nSpends, count.nMixins, count.nMixinsStaking, count.nStakes, count.nCompromised, count.nCompromisedHeight, + count.nLastHeight == 0 ? -1 : nBestHeight - count.nLastHeight + 1); + result.push_back(Pair(cbuf, ValueFromAmount(count.nValue))); + + nTotalCoins += count.nExists; + nTotalIn += count.nValue * count.nExists; + nOutputsIn += count.nExists; + nTotalOut += count.nValue * count.nSpends; + nOutputsOut += count.nSpends; + nTotalCompromised += count.nValue * count.nCompromised; + nOutputsCompromised += count.nCompromised; + nTotalMature += count.nValue * count.nMature; + nOutputsMature += count.nMature; + nTotalStakes += count.nValue * count.nStakes; + nOutputsStakes += count.nStakes; }; - result.push_back(Pair("total anon value in", ValueFromAmount(nTotalIn))); - result.push_back(Pair("total anon value out", ValueFromAmount(nTotalOut))); - result.push_back(Pair("total anon value compromised", ValueFromAmount(nTotalCompromised))); - result.push_back(Pair("total anon outputs", nTotalCoins)); + result.push_back(Pair("total outputs", nTotalCoins)); + result.push_back(Pair("total value", ValueFromAmount(nTotalIn))); + result.push_back(Pair("total mature outputs", nOutputsMature)); + result.push_back(Pair("total mature value", ValueFromAmount(nTotalMature))); + result.push_back(Pair("total spend outputs", nOutputsOut)); + result.push_back(Pair("total spend value", ValueFromAmount(nTotalOut))); + result.push_back(Pair("total stake outputs", nOutputsStakes)); + result.push_back(Pair("total stake value", ValueFromAmount(nTotalStakes))); + result.push_back(Pair("total compromised outputs", nOutputsCompromised)); + result.push_back(Pair("total compromised value", ValueFromAmount(nTotalCompromised))); return result; } -Value reloadanondata(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 0) - throw std::runtime_error( - "reloadanondata \n" - "clears all anon txn data from system, and runs scanforalltxns.\n" - "WARNING: Intended for development use only." - + HelpRequiringPassphrase()); - - if (nNodeMode != NT_FULL) - throw std::runtime_error("Must be in full mode."); - - - CBlockIndex *pindex = pindexGenesisBlock; - - // check from 257000, once anon transactions started - while (pindex->nHeight < (fTestNet ? 0 : 257000) && pindex->pnext) - pindex = pindex->pnext; - - Object result; - if (pindex) - { - LOCK2(cs_main, pwalletMain->cs_wallet); - - if (!pwalletMain->EraseAllAnonData()) - throw std::runtime_error("EraseAllAnonData() failed."); - - pwalletMain->MarkDirty(); - pwalletMain->ScanForWalletTransactions(pindex, true); - pwalletMain->ReacceptWalletTransactions(); - - pwalletMain->CacheAnonStats(); - result.push_back(Pair("result", "reloadanondata complete.")); - } else - { - result.push_back(Pair("result", "reloadanondata failed - !pindex.")); - }; - - return result; -} - - static bool compareTxnTime(const CWalletTx* pa, const CWalletTx* pb) { return pa->nTime < pb->nTime; @@ -2962,10 +2777,10 @@ Value txnreport(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); std::list listOrdered; - for (std::map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + for (auto& item : pwalletMain->mapWallet) { - if (it->second.GetDepthInMainChain() > 0) // exclude txns not in the chain - listOrdered.push_back(&it->second); + if (item.second.GetDepthInMainChain() > 0) // exclude txns not in the chain + listOrdered.push_back(&item.second); }; listOrdered.sort(compareTxnTime); @@ -3035,7 +2850,7 @@ Value txnreport(const Array& params, bool fHelp) if (pwtx->nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) { - entry.push_back("shadow in"); + entry.push_back("ALIAS (private) in"); entry.push_back(""); std::vector vchImage; txin.ExtractKeyImage(vchImage); @@ -3068,7 +2883,7 @@ Value txnreport(const Array& params, bool fHelp) if (txin.prevout.IsNull()) // coinbase continue; - entry.push_back("sdc in"); + entry.push_back("ALIAS (public) in"); entry.push_back(fCoinBase ? "coinbase" : fCoinStake ? "coinstake" : ""); if (pwalletMain->IsMine(txin)) @@ -3135,7 +2950,7 @@ Value txnreport(const Array& params, bool fHelp) if (pwtx->nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { - entry.push_back("shadow out"); + entry.push_back("ALIAS (private) out"); entry.push_back(""); CPubKey pkCoin = txout.ExtractAnonPk(); @@ -3162,7 +2977,7 @@ Value txnreport(const Array& params, bool fHelp) }; } else { - entry.push_back("sdc out"); + entry.push_back("ALIAS (public) out"); entry.push_back(fCoinBase ? "coinbase" : fCoinStake ? "coinstake" : ""); diff --git a/src/script.cpp b/src/script.cpp index 09101e58a3..9d45504c1a 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1,9 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT -#include #include #include @@ -109,7 +111,7 @@ const char* GetTxnOutputType(txnouttype t) case TX_MULTISIG: return "multisig"; case TX_NULL_DATA: return "nulldata"; } - return NULL; + return nullptr; } @@ -1005,17 +1007,17 @@ bool EvalScript(vector >& stack, const CScript& script, co break; case OP_MUL: - if (!BN_mul(&bn, &bn1, &bn2, pctx)) + if (!BN_mul(bn.pbn, bn1.pbn, bn2.pbn, pctx)) return false; break; case OP_DIV: - if (!BN_div(&bn, NULL, &bn1, &bn2, pctx)) + if (!BN_div(bn.pbn, nullptr, bn1.pbn, bn2.pbn, pctx)) return false; break; case OP_MOD: - if (!BN_mod(&bn, &bn1, &bn2, pctx)) + if (!BN_mod(bn.pbn, bn1.pbn, bn2.pbn, pctx)) return false; break; @@ -1328,13 +1330,20 @@ uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int txTmp.vin.resize(1); } - // Serialize and hash + // Serialize CHashWriter ss(SER_GETHASH, 0); - ss << txTmp << nHashType; + ss << txTmp << nHashType; + + // If forkId is greater 0, add forkId into the hash. + int forkId = Params().GetForkId(txTo.nTime); + if (forkId > 0) { + ss << forkId; + } + + // Hash return ss.GetHash(); } - // Valid signature cache, to avoid doing expensive ECDSA signature checking // twice for every transaction (once when accepted into memory pool, and // again when accepted into the block chain) @@ -1467,7 +1476,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector { std::vector vDest; int nRequired; if (ExtractDestinations(script, type, vDest, nRequired)) { - BOOST_FOREACH(const CTxDestination &dest, vDest) + for (const CTxDestination& dest : vDest) boost::apply_visitor(*this, dest); } } @@ -1878,7 +1887,7 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig static CScript PushAll(const vector& values) { CScript result; - BOOST_FOREACH(const valtype& v, values) + for (const valtype& v : values) result << v; return result; } @@ -1889,12 +1898,12 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u { // Combine all the signatures we've got: set allsigs; - BOOST_FOREACH(const valtype& v, sigs1) + for (const valtype& v : sigs1) { if (!v.empty()) allsigs.insert(v); } - BOOST_FOREACH(const valtype& v, sigs2) + for (const valtype& v : sigs2) { if (!v.empty()) allsigs.insert(v); @@ -1905,7 +1914,7 @@ static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, u unsigned int nSigsRequired = vSolutions.front()[0]; unsigned int nPubKeys = vSolutions.size()-2; map sigs; - BOOST_FOREACH(const valtype& sig, allsigs) + for (const valtype& sig : allsigs) { for (unsigned int i = 0; i < nPubKeys; i++) { @@ -2087,7 +2096,7 @@ class CScriptVisitor : public boost::static_visitor private: CScript *script; public: - CScriptVisitor(CScript *scriptin) { script = scriptin; } + CScriptVisitor(CScript *scriptin) : script(scriptin) {} bool operator()(const CNoDestination &dest) const { script->clear(); @@ -2129,7 +2138,7 @@ void CScript::SetMultisig(int nRequired, const std::vector& keys) this->clear(); *this << EncodeOP_N(nRequired); - BOOST_FOREACH(const CPubKey& key, keys) + for (const CPubKey& key : keys) *this << key; *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; } @@ -2260,7 +2269,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector& keys) CScript script; script << CScript::EncodeOP_N(nRequired); - BOOST_FOREACH(const CPubKey& key, keys) + for (const CPubKey& key : keys) script << ToByteVector(key); script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; return script; diff --git a/src/script.h b/src/script.h index f5b9bc5ab2..36255e7728 100644 --- a/src/script.h +++ b/src/script.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef H_BITCOIN_SCRIPT #define H_BITCOIN_SCRIPT @@ -11,8 +14,9 @@ #include -#include +#ifndef Q_MOC_RUN #include +#endif #include "stealth.h" #include "extkey.h" @@ -288,7 +292,7 @@ inline std::string ValueString(const std::vector& vch) inline std::string StackString(const std::vector >& vStack) { std::string str; - BOOST_FOREACH(const std::vector& vch, vStack) + for (const std::vector& vch : vStack) { if (!str.empty()) str += " "; @@ -340,9 +344,7 @@ class CScript : public std::vector CScript() { } CScript(const CScript& b) : std::vector(b.begin(), b.end()) { } CScript(const_iterator pbegin, const_iterator pend) : std::vector(pbegin, pend) { } -#ifndef _MSC_VER CScript(const unsigned char* pbegin, const unsigned char* pend) : std::vector(pbegin, pend) { } -#endif CScript& operator+=(const CScript& b) { @@ -472,7 +474,7 @@ class CScript : public std::vector bool GetOp(iterator& pc, opcodetype& opcodeRet) { const_iterator pc2 = pc; - bool fRet = GetOp2(pc2, opcodeRet, NULL); + bool fRet = GetOp2(pc2, opcodeRet, nullptr); pc = begin() + (pc2 - begin()); return fRet; } @@ -484,7 +486,7 @@ class CScript : public std::vector bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const { - return GetOp2(pc, opcodeRet, NULL); + return GetOp2(pc, opcodeRet, nullptr); } bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, std::vector* pvchRet) const diff --git a/src/scrypt-arm.S b/src/scrypt-arm.S index 143eb3a4b1..232efd5038 100644 --- a/src/scrypt-arm.S +++ b/src/scrypt-arm.S @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 2012 pooler +// +// SPDX-License-Identifier: GPL-2.0-or-later + /* * Copyright 2012 pooler@litecoinpool.org * diff --git a/src/scrypt-x86.S b/src/scrypt-x86.S index c1d2cef3f1..0822bd279a 100644 --- a/src/scrypt-x86.S +++ b/src/scrypt-x86.S @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: © 2011 pooler +# +# SPDX-License-Identifier: BSD-2-Clause + # Copyright 2011 pooler@litecoinpool.org # All rights reserved. # diff --git a/src/scrypt-x86_64.S b/src/scrypt-x86_64.S index 3036d03e74..4c7073f9a0 100644 --- a/src/scrypt-x86_64.S +++ b/src/scrypt-x86_64.S @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: © 2011 pooler +# +# SPDX-License-Identifier: BSD-2-Clause + # Copyright 2011-2012 pooler@litecoinpool.org # All rights reserved. # diff --git a/src/scrypt.cpp b/src/scrypt.cpp index 06ef53cd2b..0a1597c39e 100644 --- a/src/scrypt.cpp +++ b/src/scrypt.cpp @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2013 Balthazar +// SPDX-FileCopyrightText: © 2011 pooler +// SPDX-FileCopyrightText: © 2011 ArtForz +// SPDX-FileCopyrightText: © 2009 Colin Percival +// +// SPDX-License-Identifier: BSD-2-Clause + /*- * Copyright 2009 Colin Percival, 2011 ArtForz, 2011 pooler, 2013 Balthazar * All rights reserved. diff --git a/src/scrypt.h b/src/scrypt.h index 17afd85158..f4da1037ac 100644 --- a/src/scrypt.h +++ b/src/scrypt.h @@ -1,3 +1,10 @@ +// SPDX-FileCopyrightText: © 2013 Balthazar +// SPDX-FileCopyrightText: © 2011 pooler +// SPDX-FileCopyrightText: © 2011 ArtForz +// SPDX-FileCopyrightText: © 2009 Colin Percival +// +// SPDX-License-Identifier: BSD-2-Clause + #ifndef SCRYPT_MINE_H #define SCRYPT_MINE_H diff --git a/src/serialize.h b/src/serialize.h index 6b3c09f90d..7b63b74d6e 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_SERIALIZE_H #define BITCOIN_SERIALIZE_H @@ -10,14 +13,17 @@ #include #include #include +#undef NDEBUG #include #include #include #include #include +#ifndef Q_MOC_RUN #include #include +#endif #include "allocators.h" #include "version.h" @@ -64,7 +70,7 @@ enum const bool fRead = false; \ unsigned int nSerSize = 0; \ ser_streamplaceholder s; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + assert(fGetSize||fWrite||fRead); \ s.nType = nType; \ s.nVersion = nVersion; \ {statements} \ @@ -78,7 +84,7 @@ enum const bool fWrite = true; \ const bool fRead = false; \ unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + assert(fGetSize||fWrite||fRead); \ {statements} \ } \ template \ @@ -89,7 +95,7 @@ enum const bool fWrite = false; \ const bool fRead = true; \ unsigned int nSerSize = 0; \ - assert(fGetSize||fWrite||fRead); /* suppress warning */ \ + assert(fGetSize||fWrite||fRead); \ {statements} \ } @@ -889,10 +895,23 @@ class CDataStream Init(nTypeIn, nVersionIn); } + std::vector transform(const std::vector & vec) + { + std::vector result; + result.resize(vec.size()); + + std::transform(vec.begin(), vec.end(), result.begin(), [](unsigned char in) {return *reinterpret_cast(&in); }); + return result; + } + + CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : CDataStream(transform(vchIn), nTypeIn, nVersionIn) {}; + +/* //typedef std::vector > CSerializeData; CDataStream(const std::vector& vchIn, int nTypeIn, int nVersionIn) : vch((char*)&vchIn.begin()[0], (char*)&vchIn.end()[0]) { Init(nTypeIn, nVersionIn); } +*/ void Init(int nTypeIn, int nVersionIn) { @@ -1048,6 +1067,12 @@ class CDataStream CDataStream& read(char* pch, size_t nSize) { + if (nSize == 0) { + // nothing to read + nReadPos = 0; + vch.clear(); + return (*this); + } // Read from the beginning of the buffer unsigned int nReadPosNext = nReadPos + nSize; if (nReadPosNext >= vch.size()) @@ -1170,18 +1195,18 @@ class CAutoFile void fclose() { - if (file != NULL && file != stdin && file != stdout && file != stderr) + if (file != nullptr && file != stdin && file != stdout && file != stderr) ::fclose(file); - file = NULL; + file = nullptr; } - FILE* release() { FILE* ret = file; file = NULL; return ret; } + FILE* release() { FILE* ret = file; file = nullptr; return ret; } operator FILE*() { return file; } FILE* operator->() { return file; } FILE& operator*() { return *file; } FILE** operator&() { return &file; } FILE* operator=(FILE* pnew) { return file = pnew; } - bool operator!() { return (file == NULL); } + bool operator!() { return (file == nullptr); } // diff --git a/src/shutdown.cpp b/src/shutdown.cpp new file mode 100644 index 0000000000..9a6e3f09d6 --- /dev/null +++ b/src/shutdown.cpp @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + +#include "shutdown.h" + +#include +#include +#include +#include +#include + +#ifndef WIN32 +#include +#include +#endif + +namespace util { + +SignalInterrupt::SignalInterrupt() { +#ifndef WIN32 + int fds[2]; + if (pipe(fds) == 0) { + m_pipe_r = fds[0]; + m_pipe_w = fds[1]; + fcntl(m_pipe_r, F_SETFL, fcntl(m_pipe_r, F_GETFL) | O_NONBLOCK); + fcntl(m_pipe_w, F_SETFL, fcntl(m_pipe_w, F_GETFL) | O_NONBLOCK); + } +#endif +} + +SignalInterrupt::operator bool() const { + return m_flag.load(std::memory_order_acquire); +} + +bool SignalInterrupt::operator()() { + bool expected = false; + if (m_flag.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) { +#ifndef WIN32 + if (m_pipe_w != -1) { + char dummy = 0; + [[maybe_unused]] auto result = write(m_pipe_w, &dummy, 1); + } +#endif + return true; + } + return false; +} + +bool SignalInterrupt::wait() { + while (!m_flag.load(std::memory_order_acquire)) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + return true; +} + +bool SignalInterrupt::reset() { + m_flag.store(false, std::memory_order_release); +#ifndef WIN32 + if (m_pipe_r != -1) { + char buf[256]; + while (read(m_pipe_r, buf, sizeof(buf)) > 0) {} + } +#endif + return true; +} + +bool SignalInterrupt::sleep_for(std::chrono::milliseconds duration) { + auto start = std::chrono::steady_clock::now(); + while (!m_flag.load(std::memory_order_acquire)) { + auto elapsed = std::chrono::steady_clock::now() - start; + if (elapsed >= duration) return true; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + return false; +} + +} // namespace util + +static std::atomic fRequestShutdown{false}; +static std::mutex cs_shutdown; +static std::condition_variable cv_shutdown; +static std::function g_shutdown_callback; + +void StartShutdown() { + fRequestShutdown.store(true, std::memory_order_release); + cv_shutdown.notify_all(); + if (g_shutdown_callback) { + g_shutdown_callback(); + } +} + +void AbortShutdown() { + fRequestShutdown.store(false, std::memory_order_release); +} + +bool ShutdownRequested() { + return fRequestShutdown.load(std::memory_order_acquire); +} + +void WaitForShutdown() { + std::unique_lock lock(cs_shutdown); + cv_shutdown.wait(lock, [] { return fRequestShutdown.load(std::memory_order_acquire); }); +} + +void SetShutdownCallback(std::function callback) { + g_shutdown_callback = std::move(callback); +} diff --git a/src/shutdown.h b/src/shutdown.h new file mode 100644 index 0000000000..a6198131a1 --- /dev/null +++ b/src/shutdown.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_SHUTDOWN_H +#define ALIAS_SHUTDOWN_H + +#include +#include +#include + +namespace util { + +class SignalInterrupt { +public: + SignalInterrupt(); + + explicit operator bool() const; + [[nodiscard]] bool operator()(); + + bool wait(); + bool reset(); + bool sleep_for(std::chrono::milliseconds duration); + +private: + std::atomic m_flag{false}; +#ifndef WIN32 + int m_pipe_r{-1}; + int m_pipe_w{-1}; +#endif +}; + +} // namespace util + +void StartShutdown(); +void AbortShutdown(); +bool ShutdownRequested(); + +void WaitForShutdown(); + +void SetShutdownCallback(std::function callback); + +#endif // ALIAS_SHUTDOWN_H diff --git a/src/smessage.cpp b/src/smessage.cpp index 980d9f2d67..d09dced0bd 100644 --- a/src/smessage.cpp +++ b/src/smessage.cpp @@ -1,39 +1,13 @@ -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -/* -Notes: - Running with -debug could leave to and from address hashes and public keys in the log. - - - parameters: - -nosmsg Disable secure messaging (fNoSmsg) - -debugsmsg Show extra debug messages (fDebugSmsg) - -smsgscanchain Scan the block chain for public key addresses on startup - - - Wallet Locked - A copy of each incoming message is stored in bucket files ending in _wl.dat - wl (wallet locked) bucket files are deleted if they expire, like normal buckets - When the wallet is unlocked all the messages in wl files are scanned. - - - Address Whitelist - Owned Addresses are stored in smsgAddresses vector - Saved to smsg.ini - Modify options using the smsglocalkeys rpc command or edit the smsg.ini file (with client closed) - - - TODO: - For buckets older than current, only need to store no. messages and hash in memory - -*/ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "smessage.h" #include -#include #include #include #include @@ -47,44 +21,10 @@ #include #include -#include -#include -#include - #include "base58.h" -#include "db.h" -#include "init.h" // pwalletMain -#include "txdb.h" -#include "sync.h" #include "eckey.h" -#include "lz4/lz4.c" - #include "xxhash/xxhash.h" -#include "xxhash/xxhash.c" - - -boost::thread_group threadGroupSmsg; - -boost::signals2::signal NotifySecMsgInboxChanged; -boost::signals2::signal NotifySecMsgOutboxChanged; -boost::signals2::signal NotifySecMsgWalletUnlocked; - -bool fSecMsgEnabled = false; - -std::map smsgBuckets; -std::vector smsgAddresses; -SecMsgOptions smsgOptions; - - -CCriticalSection cs_smsg; -CCriticalSection cs_smsgDB; -CCriticalSection cs_smsgThreads; - -leveldb::DB *smsgDB = NULL; - - -namespace fs = boost::filesystem; bool SecMsgCrypter::SetKey(const std::vector& vchNewKey, uint8_t* chNewIV) { @@ -115,15 +55,15 @@ bool SecMsgCrypter::Encrypt(uint8_t* chPlaintext, uint32_t nPlain, std::vector (nCLen); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; + ctx = EVP_CIPHER_CTX_new(); bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, &chKey[0], &chIV[0]); - if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, chPlaintext, nLen); - if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); - EVP_CIPHER_CTX_cleanup(&ctx); + if (fOk) fOk = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, &chKey[0], &chIV[0]); + if (fOk) fOk = EVP_EncryptUpdate(ctx, &vchCiphertext[0], &nCLen, chPlaintext, nLen); + if (fOk) fOk = EVP_EncryptFinal_ex(ctx, (&vchCiphertext[0])+nCLen, &nFLen); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; @@ -143,15 +83,15 @@ bool SecMsgCrypter::Decrypt(uint8_t* chCiphertext, uint32_t nCipher, std::vector vchPlaintext.resize(nCipher); - EVP_CIPHER_CTX ctx; + EVP_CIPHER_CTX *ctx; + ctx = EVP_CIPHER_CTX_new(); bool fOk = true; - EVP_CIPHER_CTX_init(&ctx); - if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, &chKey[0], &chIV[0]); - if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &chCiphertext[0], nCipher); - if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); - EVP_CIPHER_CTX_cleanup(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, &chKey[0], &chIV[0]); + if (fOk) fOk = EVP_DecryptUpdate(ctx, &vchPlaintext[0], &nPLen, &chCiphertext[0], nCipher); + if (fOk) fOk = EVP_DecryptFinal_ex(ctx, (&vchPlaintext[0])+nPLen, &nFLen); + EVP_CIPHER_CTX_free(ctx); if (!fOk) return false; @@ -160,3907 +100,3 @@ bool SecMsgCrypter::Decrypt(uint8_t* chCiphertext, uint32_t nCipher, std::vector return true; }; - -void SecMsgBucket::hashBucket() -{ - if (fDebugSmsg) - LogPrintf("SecMsgBucket::hashBucket()\n"); - - - std::set::iterator it; - - void* state = XXH32_init(1); - - for (it = setTokens.begin(); it != setTokens.end(); ++it) - { - XXH32_update(state, it->sample, 8); - }; - - uint32_t hash_new = XXH32_digest(state); - - if(hash != hash_new) - { - - if(fDebugSmsg) - LogPrintf("Bucket hash updated from %u to %u.\n", hash, hash_new); - - hash = hash_new; //use memcpy here? - - timeChanged = GetTime(); - } - - if (fDebugSmsg) - LogPrintf("Hashed %u messages, hash %u\n", setTokens.size(), hash_new); -}; - - -bool SecMsgDB::Open(const char* pszMode) -{ - if (smsgDB) - { - pdb = smsgDB; - return true; - }; - - bool fCreate = strchr(pszMode, 'c'); - - fs::path fullpath = GetDataDir() / "smsgDB"; - - if (!fCreate - && (!fs::exists(fullpath) - || !fs::is_directory(fullpath))) - { - LogPrintf("SecMsgDB::open() - DB does not exist.\n"); - return false; - }; - - leveldb::Options options; - options.create_if_missing = fCreate; - leveldb::Status s = leveldb::DB::Open(options, fullpath.string(), &smsgDB); - - if (!s.ok()) - { - LogPrintf("SecMsgDB::open() - Error opening db: %s.\n", s.ToString().c_str()); - return false; - }; - - pdb = smsgDB; - - return true; -}; - - -class SecMsgBatchScanner : public leveldb::WriteBatch::Handler -{ -public: - std::string needle; - bool* deleted; - std::string* foundValue; - bool foundEntry; - - SecMsgBatchScanner() : foundEntry(false) {} - - virtual void Put(const leveldb::Slice& key, const leveldb::Slice& value) - { - if (key.ToString() == needle) - { - foundEntry = true; - *deleted = false; - *foundValue = value.ToString(); - }; - }; - - virtual void Delete(const leveldb::Slice& key) - { - if (key.ToString() == needle) - { - foundEntry = true; - *deleted = true; - }; - }; -}; - -// When performing a read, if we have an active batch we need to check it first -// before reading from the database, as the rest of the code assumes that once -// a database transaction begins reads are consistent with it. It would be good -// to change that assumption in future and avoid the performance hit, though in -// practice it does not appear to be large. -bool SecMsgDB::ScanBatch(const CDataStream& key, std::string* value, bool* deleted) const -{ - if (!activeBatch) - return false; - - *deleted = false; - SecMsgBatchScanner scanner; - scanner.needle = key.str(); - scanner.deleted = deleted; - scanner.foundValue = value; - leveldb::Status s = activeBatch->Iterate(&scanner); - if (!s.ok()) - { - LogPrintf("SecMsgDB ScanBatch error: %s\n", s.ToString().c_str()); - return false; - }; - - return scanner.foundEntry; -} - -bool SecMsgDB::TxnBegin() -{ - if (activeBatch) - return true; - activeBatch = new leveldb::WriteBatch(); - return true; -}; - -bool SecMsgDB::TxnCommit() -{ - if (!activeBatch) - return false; - - leveldb::WriteOptions writeOptions; - writeOptions.sync = true; - leveldb::Status status = pdb->Write(writeOptions, activeBatch); - delete activeBatch; - activeBatch = NULL; - - if (!status.ok()) - { - LogPrintf("SecMsgDB batch commit failure: %s\n", status.ToString().c_str()); - return false; - }; - - return true; -}; - -bool SecMsgDB::TxnAbort() -{ - delete activeBatch; - activeBatch = NULL; - return true; -}; - -bool SecMsgDB::ReadPK(CKeyID& addr, CPubKey& pubkey) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(sizeof(addr) + 2); - ssKey << 'p'; - ssKey << 'k'; - ssKey << addr; - std::string strValue; - - bool readFromDb = true; - if (activeBatch) - { - // -- check activeBatch first - bool deleted = false; - readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false; - if (deleted) - return false; - }; - - if (readFromDb) - { - leveldb::Status s = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &strValue); - if (!s.ok()) - { - if (s.IsNotFound()) - return false; - LogPrintf("LevelDB read failure: %s\n", s.ToString().c_str()); - return false; - }; - }; - - try { - CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); - ssValue >> pubkey; - } catch (std::exception& e) { - LogPrintf("SecMsgDB::ReadPK() unserialize threw: %s.\n", e.what()); - return false; - } - - return true; -}; - -bool SecMsgDB::WritePK(CKeyID& addr, CPubKey& pubkey) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(sizeof(addr) + 2); - ssKey << 'p'; - ssKey << 'k'; - ssKey << addr; - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - ssValue.reserve(sizeof(pubkey)); - ssValue << pubkey; - - if (activeBatch) - { - activeBatch->Put(ssKey.str(), ssValue.str()); - return true; - }; - - leveldb::WriteOptions writeOptions; - writeOptions.sync = true; - leveldb::Status s = pdb->Put(writeOptions, ssKey.str(), ssValue.str()); - if (!s.ok()) - { - LogPrintf("SecMsgDB write failure: %s\n", s.ToString().c_str()); - return false; - }; - - return true; -}; - -bool SecMsgDB::ExistsPK(CKeyID& addr) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.reserve(sizeof(addr)+2); - ssKey << 'p'; - ssKey << 'k'; - ssKey << addr; - std::string unused; - - if (activeBatch) - { - bool deleted; - if (ScanBatch(ssKey, &unused, &deleted) && !deleted) - { - return true; - }; - }; - - leveldb::Status s = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused); - return s.IsNotFound() == false; -}; - - -bool SecMsgDB::NextSmesg(leveldb::Iterator* it, std::string& prefix, uint8_t* chKey, SecMsgStored& smsgStored) -{ - if (!pdb) - return false; - - if (!it->Valid()) // first run - it->Seek(prefix); - else - it->Next(); - - if (!(it->Valid() - && it->key().size() == 18 - && memcmp(it->key().data(), prefix.data(), 2) == 0)) - return false; - - memcpy(chKey, it->key().data(), 18); - - try { - CDataStream ssValue(it->value().data(), it->value().data() + it->value().size(), SER_DISK, CLIENT_VERSION); - ssValue >> smsgStored; - } catch (std::exception& e) { - LogPrintf("SecMsgDB::NextSmesg() unserialize threw: %s.\n", e.what()); - return false; - } - - return true; -}; - -bool SecMsgDB::NextSmesgKey(leveldb::Iterator* it, std::string& prefix, uint8_t* chKey) -{ - if (!pdb) - return false; - - if (!it->Valid()) // first run - it->Seek(prefix); - else - it->Next(); - - if (!(it->Valid() - && it->key().size() == 18 - && memcmp(it->key().data(), prefix.data(), 2) == 0)) - return false; - - memcpy(chKey, it->key().data(), 18); - - return true; -}; - -bool SecMsgDB::ReadSmesg(uint8_t* chKey, SecMsgStored& smsgStored) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.write((const char*)chKey, 18); - std::string strValue; - - bool readFromDb = true; - if (activeBatch) - { - // -- check activeBatch first - bool deleted = false; - readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false; - if (deleted) - return false; - }; - - if (readFromDb) - { - leveldb::Status s = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &strValue); - if (!s.ok()) - { - if (s.IsNotFound()) - return false; - LogPrintf("LevelDB read failure: %s\n", s.ToString().c_str()); - return false; - }; - }; - - try { - CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION); - ssValue >> smsgStored; - } catch (std::exception& e) { - LogPrintf("SecMsgDB::ReadSmesg() unserialize threw: %s.\n", e.what()); - return false; - } - - return true; -}; - -bool SecMsgDB::WriteSmesg(uint8_t* chKey, SecMsgStored& smsgStored) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.write((const char*)chKey, 18); - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - ssValue << smsgStored; - - if (activeBatch) - { - activeBatch->Put(ssKey.str(), ssValue.str()); - return true; - }; - - leveldb::WriteOptions writeOptions; - writeOptions.sync = true; - leveldb::Status s = pdb->Put(writeOptions, ssKey.str(), ssValue.str()); - if (!s.ok()) - { - LogPrintf("SecMsgDB write failed: %s\n", s.ToString().c_str()); - return false; - }; - - return true; -}; - -bool SecMsgDB::ExistsSmesg(uint8_t* chKey) -{ - if (!pdb) - return false; - - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.write((const char*)chKey, 18); - std::string unused; - - if (activeBatch) - { - bool deleted; - if (ScanBatch(ssKey, &unused, &deleted) && !deleted) - { - return true; - }; - }; - - leveldb::Status s = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused); - return s.IsNotFound() == false; - return true; -}; - -bool SecMsgDB::EraseSmesg(uint8_t* chKey) -{ - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - ssKey.write((const char*)chKey, 18); - - if (activeBatch) - { - activeBatch->Delete(ssKey.str()); - return true; - }; - - leveldb::WriteOptions writeOptions; - writeOptions.sync = true; - leveldb::Status s = pdb->Delete(writeOptions, ssKey.str()); - - if (s.ok() || s.IsNotFound()) - return true; - LogPrintf("SecMsgDB erase failed: %s\n", s.ToString().c_str()); - return false; -}; - -void ThreadSecureMsg() -{ - // -- bucket management thread - SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); - - uint32_t nLoop = 0; - std::vector > vTimedOutLocks; - while (fSecMsgEnabled) - { - nLoop++; - int64_t now = GetTime(); - - if (fDebugSmsg && nLoop % SMSG_THREAD_LOG_GAP == 0) // log every SMSG_THREAD_LOG_GAP instance, is useful source of timestamps - LogPrintf("SecureMsgThread %d \n", now); - - vTimedOutLocks.resize(0); - - int64_t cutoffTime = now - SMSG_RETENTION; - { - LOCK(cs_smsg); - for (std::map::iterator it(smsgBuckets.begin()); it != smsgBuckets.end(); ) - { - //if (fDebugSmsg) - // LogPrintf("Checking bucket %d, size %u \n", it->first, it->second.setTokens.size()); - - if (it->first < cutoffTime) - { - if (fDebugSmsg) - LogPrintf("Removing bucket %d \n", it->first); - - std::string fileName = boost::lexical_cast(it->first); - - fs::path fullPath = GetDataDir() / "smsgStore" / (fileName + "_01.dat"); - if (fs::exists(fullPath)) - { - try { fs::remove(fullPath); - } catch (const fs::filesystem_error& ex) - { - LogPrintf("Error removing bucket file %s.\n", ex.what()); - }; - } else - { - LogPrintf("Path %s does not exist \n", fullPath.string().c_str()); - }; - - // -- look for a wl file, it stores incoming messages when wallet is locked - fullPath = GetDataDir() / "smsgStore" / (fileName + "_01_wl.dat"); - if (fs::exists(fullPath)) - { - try { fs::remove(fullPath); - } catch (const fs::filesystem_error& ex) - { - LogPrintf("Error removing wallet locked file %s.\n", ex.what()); - }; - }; - - smsgBuckets.erase(it++); - } else - { - if (it->second.nLockCount > 0) // -- tick down nLockCount, so will eventually expire if peer never sends data - { - it->second.nLockCount--; - - if (it->second.nLockCount == 0) // lock timed out - { - vTimedOutLocks.push_back(std::make_pair(it->first, it->second.nLockPeerId)); // cs_vNodes - - it->second.nLockPeerId = 0; - }; // if (it->second.nLockCount == 0) - }; // ! if (it->first < cutoffTime) - ++it; - } - }; - } // cs_smsg - - for (std::vector >::iterator it(vTimedOutLocks.begin()); it != vTimedOutLocks.end(); it++) - { - NodeId nPeerId = it->second; - uint32_t fExists = 0; - - if (fDebugSmsg) - LogPrintf("Lock on bucket %d for peer %d timed out.\n", it->first, nPeerId); - - // -- look through the nodes for the peer that locked this bucket - - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - if (pnode->id != nPeerId) - continue; - - fExists = 1; //found in vNodes - - LOCK(pnode->smsgData.cs_smsg_net); - int64_t ignoreUntil = GetTime() + SMSG_TIME_IGNORE; - pnode->smsgData.ignoreUntil = ignoreUntil; - - // -- alert peer that they are being ignored - std::vector vchData; - vchData.resize(8); - memcpy(&vchData[0], &ignoreUntil, 8); - pnode->PushMessage("smsgIgnore", vchData); - - if (fDebugSmsg) - LogPrintf("This node will ignore peer %d until %d.\n", nPeerId, ignoreUntil); - break; - }; - } // cs_vNodes - - if(fDebugSmsg) - LogPrintf("shadow-smsg thread: ignoring - looked peer %d, status on search %u\n", nPeerId, fExists); - }; - - MilliSleep(SMSG_THREAD_DELAY * 1000); // // check every SMSG_THREAD_DELAY seconds - }; -}; - -void ThreadSecureMsgPow() -{ - // -- proof of work thread - - int rv; - std::vector vchKey; - SecMsgStored smsgStored; - - std::string sPrefix("qm"); - uint8_t chKey[18]; - - - while (fSecMsgEnabled) - { - // -- sleep at end, then fSecMsgEnabled is tested on wake - - SecMsgDB dbOutbox; - leveldb::Iterator* it; - { - LOCK(cs_smsgDB); - - if (!dbOutbox.Open("cr+")) - continue; - - // -- fifo (smallest key first) - it = dbOutbox.pdb->NewIterator(leveldb::ReadOptions()); - } - // -- break up lock, SecureMsgSetHash will take long - - for (;;) - { - { - LOCK(cs_smsgDB); - if (!dbOutbox.NextSmesg(it, sPrefix, chKey, smsgStored)) - break; - } - - uint8_t* pHeader = &smsgStored.vchMessage[0]; - uint8_t* pPayload = &smsgStored.vchMessage[SMSG_HDR_LEN]; - SecureMessage* psmsg = (SecureMessage*) pHeader; - - // -- do proof of work - rv = SecureMsgSetHash(pHeader, pPayload, psmsg->nPayload); - if (rv == 2) - break; // leave message in db, if terminated due to shutdown - - // -- message is removed here, no matter what - { - LOCK(cs_smsgDB); - dbOutbox.EraseSmesg(chKey); - } - if (rv != 0) - { - LogPrintf("SecMsgPow: Could not get proof of work hash, message removed.\n"); - continue; - }; - - // -- add to message store - { - LOCK(cs_smsg); - if (SecureMsgStore(pHeader, pPayload, psmsg->nPayload, true) != 0) - { - LogPrintf("SecMsgPow: Could not place message in buckets, message removed.\n"); - continue; - }; - } - - // -- test if message was sent to self - if (SecureMsgScanMessage(pHeader, pPayload, psmsg->nPayload, true) != 0) - { - // message recipient is not this node (or failed) - }; - }; - - delete it; - - // -- shutdown thread waits 5 seconds, this should be less - MilliSleep(2000); // seconds - }; -}; - -int SecureMsgBuildBucketSet() -{ - /* - Build the bucket set by scanning the files in the smsgStore dir. - - smsgBuckets should be empty - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgBuildBucketSet()\n"); - - int64_t now = GetTime(); - uint32_t nFiles = 0; - uint32_t nMessages = 0; - - fs::path pathSmsgDir = GetDataDir() / "smsgStore"; - fs::directory_iterator itend; - - - if (!fs::exists(pathSmsgDir) - || !fs::is_directory(pathSmsgDir)) - { - LogPrintf("Message store directory does not exist.\n"); - return 0; // not an error - } - - - for (fs::directory_iterator itd(pathSmsgDir) ; itd != itend ; ++itd) - { - if (!fs::is_regular_file(itd->status())) - continue; - - std::string fileType = (*itd).path().extension().string(); - - if (fileType.compare(".dat") != 0) - continue; - - std::string fileName = (*itd).path().filename().string(); - - if (fDebugSmsg) - LogPrintf("Processing file: %s.\n", fileName.c_str()); - - nFiles++; - - // TODO files must be split if > 2GB - // time_noFile.dat - size_t sep = fileName.find_first_of("_"); - if (sep == std::string::npos) - continue; - - std::string stime = fileName.substr(0, sep); - - int64_t fileTime = boost::lexical_cast(stime); - - if (fileTime < now - SMSG_RETENTION) - { - LogPrintf("Dropping file %s, expired.\n", fileName.c_str()); - try { - fs::remove((*itd).path()); - } catch (const fs::filesystem_error& ex) - { - LogPrintf("Error removing bucket file %s, %s.\n", fileName.c_str(), ex.what()); - }; - continue; - }; - - if (boost::algorithm::ends_with(fileName, "_wl.dat")) - { - if (fDebugSmsg) - LogPrintf("Skipping wallet locked file: %s.\n", fileName.c_str()); - continue; - }; - - size_t nTokenSetSize = 0; - SecureMessage smsg; - { - LOCK(cs_smsg); - - std::set& tokenSet = smsgBuckets[fileTime].setTokens; - - FILE *fp; - - if (!(fp = fopen((*itd).path().string().c_str(), "rb"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - continue; - }; - - for (;;) - { - long int ofs = ftell(fp); - SecMsgToken token; - token.offset = ofs; - errno = 0; - if (fread(&smsg.hash[0], sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN) - { - if (errno != 0) - { - LogPrintf("fread header failed: %s\n", strerror(errno)); - } else - { - //LogPrintf("End of file.\n"); - }; - break; - }; - token.timestamp = smsg.timestamp; - - if (smsg.nPayload < 8) - continue; - - if (fread(token.sample, sizeof(uint8_t), 8, fp) != 8) - { - LogPrintf("fread data failed: %s\n", strerror(errno)); - break; - }; - - if (fseek(fp, smsg.nPayload-8, SEEK_CUR) != 0) - { - LogPrintf("fseek, strerror: %s.\n", strerror(errno)); - break; - }; - - tokenSet.insert(token); - }; - - fclose(fp); - - smsgBuckets[fileTime].hashBucket(); - - nTokenSetSize = tokenSet.size(); - } // LOCK(cs_smsg); - - nMessages += nTokenSetSize; - if (fDebugSmsg) - LogPrintf("Bucket %d contains %u messages.\n", fileTime, nTokenSetSize); - }; - - LogPrintf("Processed %u files, loaded %u buckets containing %u messages.\n", nFiles, smsgBuckets.size(), nMessages); - - return 0; -}; - -/* -SecureMsgAddWalletAddresses -Enumerates the AddressBook, filters out anon outputs and checks the "real addresses" -Adds these to the vector smsgAddresses to be used for decryption - -Returns on success! -*/ - -int SecureMsgAddWalletAddresses() -{ - if (fDebugSmsg) - LogPrintf("SecureMsgAddWalletAddresses()\n"); - - std::string sAnonPrefix("ao "); - - uint32_t nAdded = 0; - - - BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& entry, pwalletMain->mapAddressBook) - { - if (!IsDestMine(*pwalletMain, entry.first)) - continue; - - // -- skip addresses for anon outputs - if (entry.second.compare(0, sAnonPrefix.length(), sAnonPrefix) == 0) - continue; - - // TODO: skip addresses for stealth transactions - - CBitcoinAddress coinAddress(entry.first); - if (!coinAddress.IsValid()) - continue; - - std::string address; - std::string strPublicKey; - address = coinAddress.ToString(); - - bool fExists = 0; - for (std::vector::iterator it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (address != it->sAddress) - continue; - fExists = 1; - break; - }; - - if (fExists) - continue; - - bool recvEnabled = 1; - bool recvAnon = 1; - - smsgAddresses.push_back(SecMsgAddress(address, recvEnabled, recvAnon)); - nAdded++; - }; - - if (fDebugSmsg) - LogPrintf("Added %u addresses to whitelist.\n", nAdded); - - return 0; -}; - - -int SecureMsgReadIni() -{ - if (!fSecMsgEnabled) - return false; - - if (fDebugSmsg) - LogPrintf("SecureMsgReadIni()\n"); - - fs::path fullpath = GetDataDir() / "smsg.ini"; - - - FILE *fp; - errno = 0; - if (!(fp = fopen(fullpath.string().c_str(), "r"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - return 1; - }; - - char cLine[512]; - char *pName, *pValue; - - char cAddress[64]; - int addrRecv, addrRecvAnon; - - while (fgets(cLine, 512, fp)) - { - cLine[strcspn(cLine, "\n")] = '\0'; - cLine[strcspn(cLine, "\r")] = '\0'; - cLine[511] = '\0'; // for safety - - // -- check that line contains a name value pair and is not a comment, or section header - if (cLine[0] == '#' || cLine[0] == '[' || strcspn(cLine, "=") < 1) - continue; - - if (!(pName = strtok(cLine, "=")) - || !(pValue = strtok(NULL, "="))) - continue; - - if (strcmp(pName, "newAddressRecv") == 0) - { - smsgOptions.fNewAddressRecv = (strcmp(pValue, "true") == 0) ? true : false; - } else - if (strcmp(pName, "newAddressAnon") == 0) - { - smsgOptions.fNewAddressAnon = (strcmp(pValue, "true") == 0) ? true : false; - } else - if (strcmp(pName, "scanIncoming") == 0) - { - smsgOptions.fScanIncoming = (strcmp(pValue, "true") == 0) ? true : false; - } else - if (strcmp(pName, "key") == 0) - { - int rv = sscanf(pValue, "%64[^|]|%d|%d", cAddress, &addrRecv, &addrRecvAnon); - if (rv == 3) - { - smsgAddresses.push_back(SecMsgAddress(std::string(cAddress), addrRecv, addrRecvAnon)); - } else - { - LogPrintf("Could not parse key line %s, rv %d.\n", pValue, rv); - } - } else - { - LogPrintf("Unknown setting name: '%s'.", pName); - }; - }; - - LogPrintf("Loaded %u addresses.\n", smsgAddresses.size()); - - fclose(fp); - - return 0; -}; - -int SecureMsgWriteIni() -{ - if (!fSecMsgEnabled) - return false; - - if (fDebugSmsg) - LogPrintf("SecureMsgWriteIni()\n"); - - fs::path fullpath = GetDataDir() / "smsg.ini~"; - - FILE *fp; - errno = 0; - if (!(fp = fopen(fullpath.string().c_str(), "w"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - return 1; - }; - - if (fwrite("[Options]\n", sizeof(char), 10, fp) != 10) - { - LogPrintf("fwrite error: %s\n", strerror(errno)); - fclose(fp); - return false; - }; - - if (fprintf(fp, "newAddressRecv=%s\n", smsgOptions.fNewAddressRecv ? "true" : "false") < 0 - || fprintf(fp, "newAddressAnon=%s\n", smsgOptions.fNewAddressAnon ? "true" : "false") < 0 - || fprintf(fp, "scanIncoming=%s\n", smsgOptions.fScanIncoming ? "true" : "false") < 0) - { - LogPrintf("fprintf error: %s\n", strerror(errno)); - fclose(fp); - return false; - } - - if (fwrite("\n[Keys]\n", sizeof(char), 8, fp) != 8) - { - LogPrintf("fwrite error: %s\n", strerror(errno)); - fclose(fp); - return false; - }; - for (std::vector::iterator it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - errno = 0; - if (fprintf(fp, "key=%s|%d|%d\n", it->sAddress.c_str(), it->fReceiveEnabled, it->fReceiveAnon) < 0) - { - LogPrintf("fprintf error: %s\n", strerror(errno)); - continue; - }; - }; - - - fclose(fp); - - - try { - fs::path finalpath = GetDataDir() / "smsg.ini"; - fs::rename(fullpath, finalpath); - } catch (const fs::filesystem_error& ex) - { - LogPrintf("Error renaming file %s, %s.\n", fullpath.string().c_str(), ex.what()); - }; - return 0; -}; - - -/** called from AppInit2() in init.cpp */ -bool SecureMsgStart(bool fDontStart, bool fScanChain) -{ - if (fDontStart) - { - LogPrintf("Secure messaging not started.\n"); - return false; - }; - - LogPrintf("Secure messaging starting.\n"); - - fSecMsgEnabled = true; - - if (SecureMsgReadIni() != 0) - LogPrintf("Failed to read smsg.ini\n"); - - if (smsgAddresses.size() < 1) - { - LogPrintf("No address keys loaded.\n"); - if (SecureMsgAddWalletAddresses() != 0) - LogPrintf("Failed to load addresses from wallet.\n"); - else - LogPrintf("Loaded addresses from wallet.\n"); - - } else { - LogPrintf("Loaded addresses from SMSG.ini\n"); - } - - if (fScanChain) - { - SecureMsgScanBlockChain(); - }; - - if (SecureMsgBuildBucketSet() != 0) - { - LogPrintf("SecureMsg could not load bucket sets, secure messaging disabled.\n"); - fSecMsgEnabled = false; - return false; - }; - - threadGroupSmsg.create_thread(boost::bind(&TraceThread, "smsg", &ThreadSecureMsg)); - threadGroupSmsg.create_thread(boost::bind(&TraceThread, "smsg-pow", &ThreadSecureMsgPow)); - - return true; -}; - -bool SecureMsgShutdown() -{ - if (!fSecMsgEnabled) - return false; - - LogPrintf("Stopping secure messaging.\n"); - - - if (SecureMsgWriteIni() != 0) - LogPrintf("Failed to save smsg.ini\n"); - - fSecMsgEnabled = false; - - threadGroupSmsg.interrupt_all(); - threadGroupSmsg.join_all(); - - if (smsgDB) - { - LOCK(cs_smsgDB); - delete smsgDB; - smsgDB = NULL; - }; - - return true; -}; - -bool SecureMsgEnable() -{ - // -- start secure messaging at runtime - if (fSecMsgEnabled) - { - LogPrintf("SecureMsgEnable: secure messaging is already enabled.\n"); - return false; - }; - - { - LOCK(cs_smsg); - fSecMsgEnabled = true; - - smsgAddresses.clear(); // should be empty already - if (SecureMsgReadIni() != 0) - LogPrintf("Failed to read smsg.ini\n"); - - if (smsgAddresses.size() < 1) - { - LogPrintf("No address keys loaded.\n"); - if (SecureMsgAddWalletAddresses() != 0) - LogPrintf("Failed to load addresses from wallet.\n"); - }; - - smsgBuckets.clear(); // should be empty already - - if (SecureMsgBuildBucketSet() != 0) - { - LogPrintf("SecureMsgEnable: could not load bucket sets, secure messaging disabled.\n"); - fSecMsgEnabled = false; - return false; - }; - - } // cs_smsg - - // -- start threads - threadGroupSmsg.create_thread(boost::bind(&TraceThread, "smsg", &ThreadSecureMsg)); - threadGroupSmsg.create_thread(boost::bind(&TraceThread, "smsg-pow", &ThreadSecureMsgPow)); - - /* - if (!NewThread(ThreadSecureMsg, NULL) - || !NewThread(ThreadSecureMsgPow, NULL)) - { - LogPrintf("SecureMsgEnable could not start threads, secure messaging disabled.\n"); - fSecMsgEnabled = false; - return false; - }; - */ - // -- ping each peer, don't know which have messaging enabled - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - pnode->PushMessage("smsgPing"); - pnode->PushMessage("smsgPong"); // Send pong as have missed initial ping sent by peer when it connected - }; - } // cs_vNodes - LogPrintf("Secure messaging enabled.\n"); - return true; -}; - -bool SecureMsgDisable() -{ - // -- stop secure messaging at runtime - if (!fSecMsgEnabled) - { - LogPrintf("SecureMsgDisable: secure messaging is already disabled.\n"); - return false; - }; - - { - LOCK(cs_smsg); - fSecMsgEnabled = false; - - threadGroupSmsg.interrupt_all(); - threadGroupSmsg.join_all(); - - // -- clear smsgBuckets - std::map::iterator it; - it = smsgBuckets.begin(); - for (it = smsgBuckets.begin(); it != smsgBuckets.end(); ++it) - { - it->second.setTokens.clear(); - }; - smsgBuckets.clear(); - smsgAddresses.clear(); - } // cs_smsg - - // -- tell each smsg enabled peer that this node is disabling - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - if (!pnode->smsgData.fEnabled) - continue; - LOCK(pnode->smsgData.cs_smsg_net); - pnode->PushMessage("smsgDisabled"); - pnode->smsgData.fEnabled = false; - }; - } // cs_vNodes - - - if (SecureMsgWriteIni() != 0) - LogPrintf("Failed to save smsg.ini\n"); - - // -- allow time for threads to stop - MilliSleep(3000); // seconds - // TODO be certain that threads have stopped - - if (smsgDB) - { - LOCK(cs_smsgDB); - delete smsgDB; - smsgDB = NULL; - }; - - - LogPrintf("Secure messaging disabled.\n"); - return true; -}; - - -bool SecureMsgReceiveData(CNode* pfrom, std::string strCommand, CDataStream& vRecv) -{ - /* - Called from ProcessMessage - Runs in ThreadMessageHandler2 - */ - - /* - Commands - + smsgInv = - (1) received inventory of other node. - (1.1) sanity checks - (2) loop through buckets - (2.1) sanity checks - (2.2) check if bucket is locked to another node, if so continue but don't match. TODO: handle this properly, add critical section, lock on write. On read: nothing changes = no lock - (2.2.3) If our bucket is not locked to another node then add hash to buffer to be requested.. - (3) send smsgShow with list of hashes to request. - - + smsgShow = - + smsgHave = - + smsgWant = - + smsgMsg = ?? - + smsgPing - + smsgPong - + smsgMatch - - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgReceiveData() %s %s.\n", pfrom->addrName.c_str(), strCommand.c_str()); - - - - if (strCommand == "smsgInv") - { - std::vector vchData; - vRecv >> vchData; - - if (vchData.size() < 4) - { - pfrom->Misbehaving(1); - return false; // not enough data received to be a valid smsgInv - }; - - int64_t now = GetTime(); - - { - LOCK(pfrom->smsgData.cs_smsg_net); - - if (now < pfrom->smsgData.ignoreUntil) - { - if (fDebugSmsg) - LogPrintf("Node is ignoring peer %d until %d.\n", pfrom->id, pfrom->smsgData.ignoreUntil); - return false; - }; - } - - uint32_t nBuckets = smsgBuckets.size(); - uint32_t nLocked = 0; // no. of locked buckets on this node - uint32_t nInvBuckets; // no. of bucket headers sent by peer in smsgInv - memcpy(&nInvBuckets, &vchData[0], 4); - if (fDebugSmsg) - LogPrintf("Remote node sent %d bucket headers, this has %d.\n", nInvBuckets, nBuckets); - - - // -- Check no of buckets: - if (nInvBuckets > (SMSG_RETENTION / SMSG_BUCKET_LEN) + 1) // +1 for some leeway - { - LogPrintf("Peer sent more bucket headers than possible %u, %u.\n", nInvBuckets, (SMSG_RETENTION / SMSG_BUCKET_LEN)); - pfrom->Misbehaving(1); - return false; - }; - - if (vchData.size() < 4 + nInvBuckets*16) - { - LogPrintf("Remote node did not send enough data.\n"); - pfrom->Misbehaving(1); - return false; - }; - - std::vector vchDataOut; - vchDataOut.reserve(4 + 8 * nInvBuckets); // reserve max possible size - vchDataOut.resize(4); - uint32_t nShowBuckets = 0; - - - uint8_t *p = &vchData[4]; - for (uint32_t i = 0; i < nInvBuckets; ++i) - { - int64_t time; - uint32_t ncontent, hash; - memcpy(&time, p, 8); - memcpy(&ncontent, p+8, 4); - memcpy(&hash, p+12, 4); - - p += 16; - - // Check time valid: - if (time < now - SMSG_RETENTION) - { - if (fDebugSmsg) - LogPrintf("Not interested in peer bucket %d, has expired.\n", time); - - if (time < now - SMSG_RETENTION - SMSG_TIME_LEEWAY) - pfrom->Misbehaving(1); - continue; - }; - if (time > now + SMSG_TIME_LEEWAY) - { - if (fDebugSmsg) - LogPrintf("Not interested in peer bucket %d, in the future.\n", time); - pfrom->Misbehaving(1); - continue; - }; - - if (ncontent < 1) - { - if (fDebugSmsg) - LogPrintf("Peer sent empty bucket, ignore %d %u %u.\n", time, ncontent, hash); - continue; - }; - - if (fDebugSmsg) - { - LogPrintf("peer bucket %d %u %u.\n", time, ncontent, hash); - LogPrintf("this bucket %d %u %u.\n", time, smsgBuckets[time].setTokens.size(), smsgBuckets[time].hash); - }; - { - LOCK(cs_smsg); - if (smsgBuckets[time].nLockCount > 0) - { - if (fDebugSmsg) - LogPrintf("Bucket is locked %u, waiting for peer %u to send data.\n", smsgBuckets[time].nLockCount, smsgBuckets[time].nLockPeerId); - nLocked++; - continue; - }; - - // -- if this node has more than the peer node, peer node will pull from this - // if then peer node has more this node will pull fom peer - if (smsgBuckets[time].setTokens.size() < ncontent - || (smsgBuckets[time].setTokens.size() == ncontent - && smsgBuckets[time].hash != hash)) // if same amount in buckets check hash - { - if (fDebugSmsg) - LogPrintf("Requesting contents of bucket %d.\n", time); - - uint32_t sz = vchDataOut.size(); - vchDataOut.resize(sz + 8); - memcpy(&vchDataOut[sz], &time, 8); - - nShowBuckets++; - }; - } // LOCK(cs_smsg); - }; - - // TODO: should include hash? - memcpy(&vchDataOut[0], &nShowBuckets, 4); - if (vchDataOut.size() > 4) - { - pfrom->PushMessage("smsgShow", vchDataOut); - } else - if (nLocked < 1) // Don't report buckets as matched if any are locked - { - // -- peer has no buckets we want, don't send them again until something changes - // peer will still request buckets from this node if needed (< ncontent) - vchDataOut.resize(8); - memcpy(&vchDataOut[0], &now, 8); - pfrom->PushMessage("smsgMatch", vchDataOut); - if (fDebugSmsg) - LogPrintf("Sending smsgMatch, no locked buckets, time= %d.\n", now); - } else - if (nLocked >= 1) - { - if (fDebugSmsg) - LogPrintf("%u buckets were locked, time= %d.\n", nLocked, now); - }; - - } else - if (strCommand == "smsgShow") - { - std::vector vchData; - vRecv >> vchData; - - if (vchData.size() < 4) - return false; - - uint32_t nBuckets; - memcpy(&nBuckets, &vchData[0], 4); - - if (vchData.size() < 4 + nBuckets * 8) - return false; - - if (fDebugSmsg) - LogPrintf("smsgShow: peer wants to see content of %u buckets.\n", nBuckets); - - std::map::iterator itb; - std::set::iterator it; - - std::vector vchDataOut; - int64_t time; - uint8_t* pIn = &vchData[4]; - for (uint32_t i = 0; i < nBuckets; ++i, pIn += 8) - { - memcpy(&time, pIn, 8); - - { - LOCK(cs_smsg); - itb = smsgBuckets.find(time); - if (itb == smsgBuckets.end()) - { - if (fDebugSmsg) - LogPrintf("Don't have bucket %d.\n", time); - continue; - }; - - std::set& tokenSet = (*itb).second.setTokens; - - try { vchDataOut.resize(8 + 16 * tokenSet.size()); } catch (std::exception& e) - { - LogPrintf("vchDataOut.resize %u threw: %s.\n", 8 + 16 * tokenSet.size(), e.what()); - continue; - }; - memcpy(&vchDataOut[0], &time, 8); - - uint8_t* p = &vchDataOut[8]; - for (it = tokenSet.begin(); it != tokenSet.end(); ++it) - { - memcpy(p, &it->timestamp, 8); - memcpy(p+8, &it->sample, 8); - - p += 16; - }; - } - pfrom->PushMessage("smsgHave", vchDataOut); - }; - - - } else - if (strCommand == "smsgHave") - { - // -- peer has these messages in bucket - std::vector vchData; - vRecv >> vchData; - - if (vchData.size() < 8) - return false; - - int n = (vchData.size() - 8) / 16; - - int64_t time; - memcpy(&time, &vchData[0], 8); - - // -- Check time valid: - int64_t now = GetTime(); - if (time < now - SMSG_RETENTION) - { - if (fDebugSmsg) - LogPrintf("Not interested in peer bucket %d, has expired.\n", time); - return false; - }; - if (time > now + SMSG_TIME_LEEWAY) - { - if (fDebugSmsg) - LogPrintf("Not interested in peer bucket %d, in the future.\n", time); - pfrom->Misbehaving(1); - return false; - }; - - std::vector vchDataOut; - - { - LOCK(cs_smsg); - if (smsgBuckets[time].nLockCount > 0) - { - if (fDebugSmsg) - LogPrintf("Bucket %d lock count %u, waiting for message data from peer %u.\n", time, smsgBuckets[time].nLockCount, smsgBuckets[time].nLockPeerId); - return false; - }; - - if (fDebugSmsg) - LogPrintf("Sifting through bucket %d.\n", time); - - vchDataOut.resize(8); - memcpy(&vchDataOut[0], &vchData[0], 8); - - std::set& tokenSet = smsgBuckets[time].setTokens; - std::set::iterator it; - SecMsgToken token; - uint8_t* p = &vchData[8]; - - for (int i = 0; i < n; ++i) - { - memcpy(&token.timestamp, p, 8); - memcpy(&token.sample, p+8, 8); - - it = tokenSet.find(token); - if (it == tokenSet.end()) - { - int nd = vchDataOut.size(); - try { - vchDataOut.resize(nd + 16); - } catch (std::exception& e) { - LogPrintf("vchDataOut.resize %d threw: %s.\n", nd + 16, e.what()); - continue; - }; - - memcpy(&vchDataOut[nd], p, 16); - }; - - p += 16; - }; - } - - if (vchDataOut.size() > 8) - { - if (fDebugSmsg) - { - LogPrintf("Asking peer for %u messages.\n", (vchDataOut.size() - 8) / 16); - LogPrintf("Locking bucket %u for peer %d.\n", time, pfrom->id); - }; - { - LOCK(cs_smsg); - smsgBuckets[time].nLockCount = 3; // lock this bucket for at most 3 * SMSG_THREAD_DELAY seconds, unset when peer sends smsgMsg - smsgBuckets[time].nLockPeerId = pfrom->id; - } - pfrom->PushMessage("smsgWant", vchDataOut); - }; - } else - if (strCommand == "smsgWant") - { - std::vector vchData; - vRecv >> vchData; - - if (vchData.size() < 8) - return false; - - std::vector vchOne; - std::vector vchBunch; - - vchBunch.resize(4+8); // nmessages + bucketTime - - int n = (vchData.size() - 8) / 16; - - int64_t time; - uint32_t nBunch = 0; - memcpy(&time, &vchData[0], 8); - - - std::map::iterator itb; - - { - LOCK(cs_smsg); - itb = smsgBuckets.find(time); - if (itb == smsgBuckets.end()) - { - if (fDebugSmsg) - LogPrintf("Don't have bucket %d.\n", time); - return false; - }; - - std::set& tokenSet = itb->second.setTokens; - std::set::iterator it; - SecMsgToken token; - uint8_t* p = &vchData[8]; - for (int i = 0; i < n; ++i) - { - memcpy(&token.timestamp, p, 8); - memcpy(&token.sample, p+8, 8); - - it = tokenSet.find(token); - if (it == tokenSet.end()) - { - if (fDebugSmsg) - LogPrintf("Don't have wanted message %d.\n", token.timestamp); - } else - { - //LogPrintf("Have message at %d.\n", it->offset); // DEBUG - token.offset = it->offset; - //LogPrintf("winb before SecureMsgRetrieve %d.\n", token.timestamp); - - // -- place in vchOne so if SecureMsgRetrieve fails it won't corrupt vchBunch - if (SecureMsgRetrieve(token, vchOne) == 0) - { - nBunch++; - vchBunch.insert(vchBunch.end(), vchOne.begin(), vchOne.end()); // append - } else - { - LogPrintf("SecureMsgRetrieve failed %d.\n", token.timestamp); - }; - - if (nBunch >= 500 - || vchBunch.size() >= 96000) - { - if (fDebugSmsg) - LogPrintf("Break bunch %u, %u.\n", nBunch, vchBunch.size()); - break; // end here, peer will send more want messages if needed. - }; - }; - p += 16; - }; - } // LOCK(cs_smsg); - - if (nBunch > 0) - { - if (fDebugSmsg) - LogPrintf("Sending block of %u messages for bucket %d.\n", nBunch, time); - - memcpy(&vchBunch[0], &nBunch, 4); - memcpy(&vchBunch[4], &time, 8); - pfrom->PushMessage("smsgMsg", vchBunch); - }; - } else - if (strCommand == "smsgMsg") - { - std::vector vchData; - vRecv >> vchData; - - if (fDebugSmsg) - LogPrintf("smsgMsg vchData.size() %u.\n", vchData.size()); - - SecureMsgReceive(pfrom, vchData); - } else - if (strCommand == "smsgMatch") - { - /* - Basically all this code has to go.. - For now we can use it to punish nodes running the older version, not that it's really need because the overhead is small. - TODO: remove this code. - */ - std::vector vchData; - vRecv >> vchData; - - - if (vchData.size() < 8) - { - LogPrintf("smsgMatch, not enough data %u.\n", vchData.size()); - pfrom->Misbehaving(1); - return false; - }; - - int64_t time; - memcpy(&time, &vchData[0], 8); - - int64_t now = GetTime(); - if (time > now + SMSG_TIME_LEEWAY) - { - LogPrintf("Warning: Peer buckets matched in the future: %d.\nEither this node or the peer node has the incorrect time set.\n", time); - if (fDebugSmsg) - LogPrintf("Peer match time set to now.\n"); - time = now; - }; - /* - { - LOCK(pfrom->smsgData.cs_smsg_net); - pfrom->smsgData.lastMatched = time; - }*/ - if (fDebugSmsg) - LogPrintf("[BLOCKED] Peer buckets matched in smsgWant at %d.\n", time); - - } else - if (strCommand == "smsgPing") - { - // -- smsgPing is the initial message, send reply - pfrom->PushMessage("smsgPong"); - } else - if (strCommand == "smsgPong") - { - if (fDebugSmsg) - LogPrintf("Peer replied, secure messaging enabled.\n"); - - { - LOCK(pfrom->smsgData.cs_smsg_net); - pfrom->smsgData.fEnabled = true; - } - - } else - if (strCommand == "smsgDisabled") - { - // -- peer has disabled secure messaging. - - { - LOCK(pfrom->smsgData.cs_smsg_net); - pfrom->smsgData.fEnabled = false; - } - - if (fDebugSmsg) - LogPrintf("Peer %d has disabled secure messaging.\n", pfrom->id); - - } else - if (strCommand == "smsgIgnore") - { - // -- peer is reporting that it will ignore this node until time. - // Ignore peer too - std::vector vchData; - vRecv >> vchData; - - if (vchData.size() < 8) - { - LogPrintf("smsgIgnore, not enough data %u.\n", vchData.size()); - pfrom->Misbehaving(1); - return false; - }; - - int64_t time; - memcpy(&time, &vchData[0], 8); - - { - LOCK(pfrom->smsgData.cs_smsg_net); - pfrom->smsgData.ignoreUntil = time; - } - - - if (fDebugSmsg) - LogPrintf("Peer %d is ignoring this node until %d, ignore peer too.\n", pfrom->id, time); - } else - { - // Unknown message - }; - - return true; -}; - -bool SecureMsgSendData(CNode* pto, bool fSendTrickle) -{ - /* - Called from ProcessMessage - Runs in ThreadMessageHandler2 - */ - - LOCK(pto->smsgData.cs_smsg_net); - - //LogPrintf("SecureMsgSendData() %s.\n", pto->addrName.c_str()); - - int64_t now = GetTime(); - - if (pto->smsgData.lastSeen == 0) - { - // -- first contact - if (fDebugSmsg) - LogPrintf("SecureMsgSendData() new node %s, peer id %u.\n", pto->addrName.c_str(), pto->id); - // -- Send smsgPing once, do nothing until receive 1st smsgPong (then set fEnabled) - pto->PushMessage("smsgPing"); - pto->smsgData.lastSeen = GetTime(); - return true; - } else - if (!pto->smsgData.fEnabled - || now - pto->smsgData.lastSeen < SMSG_SEND_DELAY - || now < pto->smsgData.ignoreUntil) - { - return true; - }; - - // -- When nWakeCounter == 0, resend bucket inventory. - /* - if (pto->smsgData.nWakeCounter < 1) - { - pto->smsgData.lastMatched = GetTime(); //used to be 0. - pto->smsgData.nWakeCounter = 10 + GetRandInt(300); // set to a random time between [10, 300] * SMSG_SEND_DELAY seconds - - if (fDebugSmsg) - LogPrintf("SecureMsgSendData(): nWakeCounter expired, sending bucket inventory to %s.\n" - "Now %d next wake counter %u\n", pto->addrName.c_str(), now, pto->smsgData.nWakeCounter); - }; - pto->smsgData.nWakeCounter--; - */ - - /*Why resend the whole bucket inventory? - Seems like a very odd way to handle it. - TODO: remove this code. - - */ - - - - { - LOCK(cs_smsg); - std::map::iterator it; - - uint32_t nBuckets = smsgBuckets.size(); - if (nBuckets > 0) // no need to send keep alive pkts, coin messages already do that - { - std::vector vchData; - // should reserve? - vchData.reserve(4 + nBuckets*16); // timestamp + size + hash - - uint32_t nBucketsShown = 0; - vchData.resize(4); - uint8_t* p = &vchData[4]; - - - /* - Get time before loop and after looping through messages set nLastMatched to time before loop. - This prevents scenario where: - Loop() - message = locked and thus skipped - message become free and nTimeChanged is updated - End loop - - nLastMatched = GetTime() - => bucket that became free in loop is now skipped :/ - - Scenario 2: - Same as one but time is updated before - - bucket nTimeChanged is updated but not unlocked yet - now = GetTime() - Loop of buckets skips message - - But this is nanoseconds, very unlikely. - - */ - - for (it = smsgBuckets.begin(); it != smsgBuckets.end(); ++it) - { - SecMsgBucket &bkt = it->second; - - uint32_t nMessages = bkt.setTokens.size(); - - if (bkt.timeChanged < pto->smsgData.lastMatched // peer was last sent all buckets at time of lastMatched. It should have this bucket - || nMessages < 1) // this bucket is empty - continue; - - uint32_t hash = bkt.hash; - - if(fDebugSmsg) - LogPrintf("Preparing bucket with hash %d for transfer to node %u. timeChanged=%d > lastMatched=%d\n", hash, pto->id, bkt.timeChanged, pto->smsgData.lastMatched); - - try { vchData.resize(vchData.size() + 16); } catch (std::exception& e) - { - LogPrintf("vchData.resize %u threw: %s.\n", vchData.size() + 16, e.what()); - continue; - }; - memcpy(p, &it->first, 8); - memcpy(p+8, &nMessages, 4); - memcpy(p+12, &hash, 4); - - p += 16; - nBucketsShown++; - //if (fDebug) - // LogPrintf("Sending bucket %d, size %d \n", it->first, it->second.size()); - }; - - if (vchData.size() > 4) - { - memcpy(&vchData[0], &nBucketsShown, 4); - if (fDebugSmsg) - LogPrintf("Sending %d bucket headers.\n", nBucketsShown); - - pto->PushMessage("smsgInv", vchData); - }; - }; - } // cs_smsg - - pto->smsgData.lastSeen = now; - pto->smsgData.lastMatched = now; //bug fix smsg 3 - - return true; -}; - - -static int SecureMsgInsertAddress(CKeyID& hashKey, CPubKey& pubKey, SecMsgDB& addrpkdb) -{ - /* Insert key hash and public key to addressdb. - - (+) Called when receiving a message, it will automatically add the public key of the sender to our database so we can reply. - - should have LOCK(cs_smsg) where db is opened - - returns - 0 success - 1 error - 4 address is already in db - */ - - - if (addrpkdb.ExistsPK(hashKey)) - { - //LogPrintf("DB already contains public key for address.\n"); - CPubKey cpkCheck; - if (!addrpkdb.ReadPK(hashKey, cpkCheck)) - { - LogPrintf("addrpkdb.Read failed.\n"); - } else - { - if (cpkCheck != pubKey) - LogPrintf("DB already contains existing public key that does not match .\n"); - }; - return 4; - }; - - if (!addrpkdb.WritePK(hashKey, pubKey)) - { - LogPrintf("Write pair failed.\n"); - return 1; - }; - - return 0; -}; - -int SecureMsgInsertAddress(CKeyID& hashKey, CPubKey& pubKey) -{ - int rv; - { - LOCK(cs_smsgDB); - SecMsgDB addrpkdb; - - if (!addrpkdb.Open("cr+")) - return 1; - - rv = SecureMsgInsertAddress(hashKey, pubKey, addrpkdb); - } - return rv; -}; - - -static bool ScanBlock(CBlock& block, CTxDB& txdb, SecMsgDB& addrpkdb, - uint32_t& nTransactions, uint32_t& nElements, uint32_t& nPubkeys, uint32_t& nDuplicates) -{ - AssertLockHeld(cs_smsgDB); - - valtype vch; - opcodetype opcode; - - // -- only scan inputs of standard txns and coinstakes - BOOST_FOREACH(CTransaction& tx, block.vtx) - { - // - harvest public keys from coinstake txns - if (tx.IsCoinStake()) - { - const CTxOut& txout = tx.vout[1]; - CScript::const_iterator pc = txout.scriptPubKey.begin(); - while (pc < txout.scriptPubKey.end()) - { - if (!txout.scriptPubKey.GetOp(pc, opcode, vch)) - break; - - if (vch.size() == 33) // pubkey - { - CPubKey pubKey(vch); - - if (!pubKey.IsValid() - || !pubKey.IsCompressed()) - { - LogPrintf("Public key is invalid %s.\n", HexStr(pubKey).c_str()); - continue; - }; - - CKeyID addrKey = pubKey.GetID(); - switch (SecureMsgInsertAddress(addrKey, pubKey, addrpkdb)) - { - case 0: nPubkeys++; break; // added key - case 4: nDuplicates++; break; // duplicate key - } - break; - }; - }; - nElements++; - } else - if (tx.IsStandard()) - { - for (uint32_t i = 0; i < tx.vin.size(); i++) - { - if (tx.nVersion == ANON_TXN_VERSION - && tx.vin[i].IsAnonInput()) - continue; // skip anon inputs - - CScript *script = &tx.vin[i].scriptSig; - CScript::const_iterator pc = script->begin(); - CScript::const_iterator pend = script->end(); - - CKey key; - - while (pc < pend) - { - if (!script->GetOp(pc, opcode, vch)) - break; - // - opcode is the length of the following data, compressed public key is always 33 - if (opcode == 33) - { - CPubKey pubKey(vch); - - if (!pubKey.IsValid() - || !pubKey.IsCompressed()) - { - LogPrintf("Public key is invalid %s.\n", HexStr(pubKey).c_str()); - continue; - }; - - CKeyID addrKey = pubKey.GetID(); - switch (SecureMsgInsertAddress(addrKey, pubKey, addrpkdb)) - { - case 0: nPubkeys++; break; // added key - case 4: nDuplicates++; break; // duplicate key - } - break; - }; - - //LogPrintf("opcode %d, %s, value %s.\n", opcode, GetOpName(opcode), ValueString(vch).c_str()); - }; - nElements++; - }; - }; - nTransactions++; - - if (nTransactions % 10000 == 0) // for ScanChainForPublicKeys - { - LogPrintf("Scanning transaction no. %u.\n", nTransactions); - }; - }; - return true; -}; - - -bool SecureMsgScanBlock(CBlock& block) -{ - // - scan block for public key addresses - - if (!smsgOptions.fScanIncoming) - return true; - - if (fDebugSmsg) - LogPrintf("SecureMsgScanBlock().\n"); - - uint32_t nTransactions = 0; - uint32_t nElements = 0; - uint32_t nPubkeys = 0; - uint32_t nDuplicates = 0; - - { - LOCK(cs_smsgDB); - CTxDB txdb("r"); - - SecMsgDB addrpkdb; - if (!addrpkdb.Open("cw") - || !addrpkdb.TxnBegin()) - return false; - - ScanBlock(block, txdb, addrpkdb, - nTransactions, nElements, nPubkeys, nDuplicates); - - addrpkdb.TxnCommit(); - } // cs_smsgDB - - if (fDebugSmsg) - LogPrintf("Found %u transactions, %u elements, %u new public keys, %u duplicates.\n", nTransactions, nElements, nPubkeys, nDuplicates); - - return true; -}; - -bool ScanChainForPublicKeys(CBlockIndex* pindexStart) -{ - LogPrintf("Scanning block chain for public keys.\n"); - int64_t nStart = GetTimeMillis(); - - if (fDebugSmsg) - LogPrintf("From height %u.\n", pindexStart->nHeight); - - // -- public keys are in txin.scriptSig - // matching addresses are in scriptPubKey of txin's referenced output - - uint32_t nBlocks = 0; - uint32_t nTransactions = 0; - uint32_t nInputs = 0; - uint32_t nPubkeys = 0; - uint32_t nDuplicates = 0; - - { - LOCK(cs_smsgDB); - - CTxDB txdb("r"); - - SecMsgDB addrpkdb; - if (!addrpkdb.Open("cw") - || !addrpkdb.TxnBegin()) - return false; - - CBlockIndex* pindex = pindexStart; - while (pindex) - { - nBlocks++; - CBlock block; - block.ReadFromDisk(pindex, true); - - ScanBlock(block, txdb, addrpkdb, - nTransactions, nInputs, nPubkeys, nDuplicates); - - pindex = pindex->pnext; - }; - - addrpkdb.TxnCommit(); - } // cs_smsgDB - - LogPrintf("Scanned %u blocks, %u transactions, %u inputs\n", nBlocks, nTransactions, nInputs); - LogPrintf("Found %u public keys, %u duplicates.\n", nPubkeys, nDuplicates); - LogPrintf("Took %d ms\n", GetTimeMillis() - nStart); - - return true; -}; - -bool SecureMsgScanBlockChain() -{ - TRY_LOCK(cs_main, lockMain); - if (lockMain) - { - CBlockIndex *pindexScan = pindexGenesisBlock; - if (pindexScan == NULL) - { - LogPrintf("Error: pindexGenesisBlock not set.\n"); - return false; - }; - - - try { // -- in try to catch errors opening db, - if (!ScanChainForPublicKeys(pindexScan)) - return false; - } catch (std::exception& e) - { - LogPrintf("ScanChainForPublicKeys() threw: %s.\n", e.what()); - return false; - }; - } else - { - LogPrintf("ScanChainForPublicKeys() Could not lock main.\n"); - return false; - }; - - return true; -}; - -bool SecureMsgScanBuckets() -{ - if (fDebugSmsg) - LogPrintf("SecureMsgScanBuckets()\n"); - - if (!fSecMsgEnabled - || pwalletMain->IsLocked()) - return false; - - int64_t mStart = GetTimeMillis(); - int64_t now = GetTime(); - uint32_t nFiles = 0; - uint32_t nMessages = 0; - uint32_t nFoundMessages = 0; - - fs::path pathSmsgDir = GetDataDir() / "smsgStore"; - fs::directory_iterator itend; - - if (!fs::exists(pathSmsgDir) - || !fs::is_directory(pathSmsgDir)) - { - LogPrintf("Message store directory does not exist.\n"); - return 0; // not an error - }; - - SecureMessage smsg; - std::vector vchData; - - for (fs::directory_iterator itd(pathSmsgDir) ; itd != itend ; ++itd) - { - if (!fs::is_regular_file(itd->status())) - continue; - - std::string fileType = (*itd).path().extension().string(); - - if (fileType.compare(".dat") != 0) - continue; - - std::string fileName = (*itd).path().filename().string(); - - - if (fDebugSmsg) - LogPrintf("Processing file: %s.\n", fileName.c_str()); - - nFiles++; - - // TODO files must be split if > 2GB - // time_noFile.dat - size_t sep = fileName.find_first_of("_"); - if (sep == std::string::npos) - continue; - - std::string stime = fileName.substr(0, sep); - - int64_t fileTime = boost::lexical_cast(stime); - - if (fileTime < now - SMSG_RETENTION) - { - LogPrintf("Dropping file %s, expired.\n", fileName.c_str()); - try { - fs::remove((*itd).path()); - } catch (const fs::filesystem_error& ex) - { - LogPrintf("Error removing bucket file %s, %s.\n", fileName.c_str(), ex.what()); - }; - continue; - }; - - if (boost::algorithm::ends_with(fileName, "_wl.dat")) - { - if (fDebugSmsg) - LogPrintf("Skipping wallet locked file: %s.\n", fileName.c_str()); - continue; - }; - - { - LOCK(cs_smsg); - FILE *fp; - errno = 0; - if (!(fp = fopen((*itd).path().string().c_str(), "rb"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - continue; - }; - - for (;;) - { - errno = 0; - if (fread(&smsg.hash[0], sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN) - { - if (errno != 0) - { - LogPrintf("fread header failed: %s\n", strerror(errno)); - } else - { - //LogPrintf("End of file.\n"); - }; - break; - }; - - try { vchData.resize(smsg.nPayload); } catch (std::exception& e) - { - LogPrintf("SecureMsgWalletUnlocked(): Could not resize vchData, %u, %s\n", smsg.nPayload, e.what()); - fclose(fp); - return 1; - }; - - if (fread(&vchData[0], sizeof(uint8_t), smsg.nPayload, fp) != smsg.nPayload) - { - LogPrintf("fread data failed: %s\n", strerror(errno)); - break; - }; - - // -- don't report to gui, - int rv = SecureMsgScanMessage(&smsg.hash[0], &vchData[0], smsg.nPayload, false); - - if (rv == 0) - { - nFoundMessages++; - } else - if (rv != 0) - { - // SecureMsgScanMessage failed - }; - - nMessages++; - }; - - fclose(fp); - - // -- remove wl file when scanned - try { - fs::remove((*itd).path()); - } catch (const boost::filesystem::filesystem_error& ex) - { - LogPrintf("Error removing wl file %s - %s\n", fileName.c_str(), ex.what()); - return 1; - }; - } // cs_smsg - }; - - LogPrintf("Processed %u files, scanned %u messages, received %u messages.\n", nFiles, nMessages, nFoundMessages); - LogPrintf("Took %d ms\n", GetTimeMillis() - mStart); - - return true; -} - - -int SecureMsgWalletUnlocked() -{ - /* - When the wallet is unlocked, scan messages received while wallet was locked. - */ - if (!fSecMsgEnabled) - return 0; - - LogPrintf("SecureMsgWalletUnlocked()\n"); - - if (pwalletMain->IsLocked()) - { - LogPrintf("Error: Wallet is locked.\n"); - return 1; - }; - - int64_t now = GetTime(); - uint32_t nFiles = 0; - uint32_t nMessages = 0; - uint32_t nFoundMessages = 0; - - fs::path pathSmsgDir = GetDataDir() / "smsgStore"; - fs::directory_iterator itend; - - if (!fs::exists(pathSmsgDir) - || !fs::is_directory(pathSmsgDir)) - { - LogPrintf("Message store directory does not exist.\n"); - return 0; // not an error - }; - - SecureMessage smsg; - std::vector vchData; - - for (fs::directory_iterator itd(pathSmsgDir) ; itd != itend ; ++itd) - { - if (!fs::is_regular_file(itd->status())) - continue; - - std::string fileName = (*itd).path().filename().string(); - - if (!boost::algorithm::ends_with(fileName, "_wl.dat")) - continue; - - if (fDebugSmsg) - LogPrintf("Processing file: %s.\n", fileName.c_str()); - - nFiles++; - - // TODO files must be split if > 2GB - // time_noFile_wl.dat - size_t sep = fileName.find_first_of("_"); - if (sep == std::string::npos) - continue; - - std::string stime = fileName.substr(0, sep); - - int64_t fileTime = boost::lexical_cast(stime); - - if (fileTime < now - SMSG_RETENTION) - { - LogPrintf("Dropping wallet locked file %s, expired.\n", fileName.c_str()); - try { - fs::remove((*itd).path()); - } catch (const boost::filesystem::filesystem_error& ex) - { - LogPrintf("Error removing wl file %s - %s\n", fileName.c_str(), ex.what()); - return 1; - }; - continue; - }; - - { - LOCK(cs_smsg); - FILE *fp; - errno = 0; - if (!(fp = fopen((*itd).path().string().c_str(), "rb"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - continue; - }; - - for (;;) - { - errno = 0; - if (fread(&smsg.hash[0], sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN) - { - if (errno != 0) - { - LogPrintf("fread header failed: %s\n", strerror(errno)); - } else - { - //LogPrintf("End of file.\n"); - }; - break; - }; - - try { vchData.resize(smsg.nPayload); } catch (std::exception& e) - { - LogPrintf("SecureMsgWalletUnlocked(): Could not resize vchData, %u, %s\n", smsg.nPayload, e.what()); - fclose(fp); - return 1; - }; - - if (fread(&vchData[0], sizeof(uint8_t), smsg.nPayload, fp) != smsg.nPayload) - { - LogPrintf("fread data failed: %s\n", strerror(errno)); - break; - }; - - // -- don't report to gui, - int rv = SecureMsgScanMessage(&smsg.hash[0], &vchData[0], smsg.nPayload, false); - - if (rv == 0) - { - nFoundMessages++; - } else - if (rv != 0) - { - // SecureMsgScanMessage failed - }; - - nMessages++; - }; - - fclose(fp); - - // -- remove wl file when scanned - try { - fs::remove((*itd).path()); - } catch (const boost::filesystem::filesystem_error& ex) - { - LogPrintf("Error removing wl file %s - %s\n", fileName.c_str(), ex.what()); - return 1; - }; - } // cs_smsg - }; - - LogPrintf("Processed %u files, scanned %u messages, received %u messages.\n", nFiles, nMessages, nFoundMessages); - - // -- notify gui - NotifySecMsgWalletUnlocked(); - return 0; -}; - - -int SecureMsgWalletKeyChanged(std::string sAddress, std::string sLabel, ChangeType mode) -{ - /* - SecureMsgWalletKeyChanged(): - When a key changes in the wallet, this function should be called to update the smsgAddresses vector. - - mode: - CT_NEW : a new key was added - CT_DELETED : delete an existing key from vector. - */ - - if (!fSecMsgEnabled) - return 0; - - LogPrintf("SecureMsgWalletKeyChanged()\n"); - - // TODO: default recv and recvAnon - - { - LOCK(cs_smsg); - - switch(mode) - { - case CT_NEW: - smsgAddresses.push_back(SecMsgAddress(sAddress, smsgOptions.fNewAddressRecv, smsgOptions.fNewAddressAnon)); - break; - case CT_DELETED: - for (std::vector::iterator it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (sAddress != it->sAddress) - continue; - smsgAddresses.erase(it); - break; - }; - break; - default: - break; - } - - } // cs_smsg - - - return 0; -}; - -int SecureMsgScanMessage(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, bool reportToGui) -{ - /* - Check if message belongs to this node. - If so add to inbox db. - - if !reportToGui don't fire NotifySecMsgInboxChanged - - loads messages received when wallet locked in bulk. - - returns - 0 success, - 1 error - 2 no match - 3 wallet is locked - message stored for scanning later. - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgScanMessage()\n"); - - if (pwalletMain->IsLocked()) - { - if (fDebugSmsg) - LogPrintf("ScanMessage: Wallet is locked, storing message to scan later.\n"); - - int rv; - if ((rv = SecureMsgStoreUnscanned(pHeader, pPayload, nPayload)) != 0) - return 1; - - return 3; - }; - - std::string addressTo; - MessageData msg; // placeholder - bool fOwnMessage = false; - - for (std::vector::iterator it = smsgAddresses.begin(); it != smsgAddresses.end(); ++it) - { - if (!it->fReceiveEnabled) - continue; - - CBitcoinAddress coinAddress(it->sAddress); - addressTo = coinAddress.ToString(); - - if (!it->fReceiveAnon) - { - // -- have to do full decrypt to see address from - if (SecureMsgDecrypt(false, addressTo, pHeader, pPayload, nPayload, msg) == 0) - { - if (fDebugSmsg) - LogPrintf("Decrypted message with %s.\n", addressTo.c_str()); - - if (msg.sFromAddress.compare("anon") != 0) - fOwnMessage = true; - break; - }; - } else - { - - if (SecureMsgDecrypt(true, addressTo, pHeader, pPayload, nPayload, msg) == 0) - { - if (fDebugSmsg) - LogPrintf("Decrypted message with %s.\n", addressTo.c_str()); - - fOwnMessage = true; - break; - }; - } - }; - - if (fOwnMessage) - { - // -- save to inbox - SecureMessage* psmsg = (SecureMessage*) pHeader; - std::string sPrefix("im"); - uint8_t chKey[18]; - memcpy(&chKey[0], sPrefix.data(), 2); - memcpy(&chKey[2], &psmsg->timestamp, 8); - memcpy(&chKey[10], pPayload, 8); - - SecMsgStored smsgInbox; - smsgInbox.timeReceived = GetTime(); - smsgInbox.status = (SMSG_MASK_UNREAD) & 0xFF; - smsgInbox.sAddrTo = addressTo; - - // -- data may not be contiguous - try { - smsgInbox.vchMessage.resize(SMSG_HDR_LEN + nPayload); - } catch (std::exception& e) { - LogPrintf("SecureMsgScanMessage(): Could not resize vchData, %u, %s\n", SMSG_HDR_LEN + nPayload, e.what()); - return 1; - }; - memcpy(&smsgInbox.vchMessage[0], pHeader, SMSG_HDR_LEN); - memcpy(&smsgInbox.vchMessage[SMSG_HDR_LEN], pPayload, nPayload); - - { - LOCK(cs_smsgDB); - SecMsgDB dbInbox; - - if (dbInbox.Open("cw")) - { - if (dbInbox.ExistsSmesg(chKey)) - { - if (fDebugSmsg) - LogPrintf("Message already exists in inbox db.\n"); - } else - { - dbInbox.WriteSmesg(chKey, smsgInbox); - - if (reportToGui) - NotifySecMsgInboxChanged(smsgInbox); - LogPrintf("SecureMsg saved to inbox, received with %s.\n", addressTo.c_str()); - }; - }; - } // cs_smsgDB - - // notify an external script when a message comes in - std::string strCmd = GetArg("-smsgnotify", ""); - - //TODO: Format message - if (!strCmd.empty()) - { - boost::replace_all(strCmd, "%s", addressTo); - boost::thread t(runCommand, strCmd); // thread runs free - }; - - }; - - return 0; -}; - -int SecureMsgGetLocalKey(CKeyID& ckid, CPubKey& cpkOut) -{ - if (fDebugSmsg) - LogPrintf("SecureMsgGetLocalKey()\n"); - - if (!pwalletMain->GetPubKey(ckid, cpkOut)) - return 4; - - if (!cpkOut.IsValid() - || !cpkOut.IsCompressed()) - { - LogPrintf("Public key is invalid %s.\n", HexStr(cpkOut).c_str()); - return 1; - }; - - return 0; -}; - -int SecureMsgGetLocalPublicKey(std::string& strAddress, std::string& strPublicKey) -{ - /* returns - 0 success, - 1 error - 2 invalid address - 3 address does not refer to a key - 4 address not in wallet - */ - //if (fDebugSmsg) - // LogPrintf("SecureMsgGetLocalPublicKey().\n"); - - CBitcoinAddress address; - if (!address.SetString(strAddress)) - return 2; // Invalid coin address - - CKeyID keyID; - if (!address.GetKeyID(keyID)) - return 3; - - int rv; - CPubKey pubKey; - if ((rv = SecureMsgGetLocalKey(keyID, pubKey)) != 0) - return rv; - - strPublicKey = EncodeBase58(pubKey.begin(), pubKey.end()); - - return 0; -}; - -int SecureMsgGetStoredKey(CKeyID& ckid, CPubKey& cpkOut) -{ - /* returns - 0 success, - 1 error - 2 public key not in database - */ - if (fDebugSmsg) - LogPrintf("SecureMsgGetStoredKey().\n"); - - { - LOCK(cs_smsgDB); - SecMsgDB addrpkdb; - - if (!addrpkdb.Open("r")) - return 1; - - if (!addrpkdb.ReadPK(ckid, cpkOut)) - { - //LogPrintf("addrpkdb.Read failed: %s.\n", coinAddress.ToString().c_str()); - return 2; - }; - } // cs_smsgDB - - return 0; -}; - -int SecureMsgAddAddress(std::string& address, std::string& publicKey) -{ - /* - Add address and matching public key to the database - address and publicKey are in base58 - - returns - 0 success - 1 error - 2 publicKey is invalid - 3 publicKey != address - 4 address is already in db - 5 address is invalid - */ - - CBitcoinAddress coinAddress(address); - - if (!coinAddress.IsValid()) - { - LogPrintf("%s - Address is not valid: %s.\n", __func__, address.c_str()); - return 5; - }; - - CKeyID hashKey; - - if (!coinAddress.GetKeyID(hashKey)) - { - LogPrintf("%s - coinAddress.GetKeyID failed: %s.\n", __func__, coinAddress.ToString().c_str()); - return 5; - }; - - std::vector vchTest; - DecodeBase58(publicKey, vchTest); - CPubKey pubKey(vchTest); - - // -- check that public key matches address hash - CPubKey pubKeyT(pubKey); - if (!pubKeyT.IsValid()) - { - LogPrintf("%s - Invalid PubKey.\n", __func__); - return 2; - }; - - CKeyID keyIDT = pubKeyT.GetID(); - CBitcoinAddress addressT(keyIDT); - - if (addressT.ToString().compare(address) != 0) - { - LogPrintf("%s - Public key does not hash to address, addressT %s.\n", __func__, addressT.ToString().c_str()); - return 3; - }; - - return SecureMsgInsertAddress(hashKey, pubKey); -}; - -int SecureMsgRetrieve(SecMsgToken &token, std::vector& vchData) -{ - if (fDebugSmsg) - LogPrintf("SecureMsgRetrieve() %d.\n", token.timestamp); - - // -- has cs_smsg lock from SecureMsgReceiveData - - fs::path pathSmsgDir = GetDataDir() / "smsgStore"; - - //LogPrintf("token.offset %d.\n", token.offset); // DEBUG - int64_t bucket = token.timestamp - (token.timestamp % SMSG_BUCKET_LEN); - std::string fileName = boost::lexical_cast(bucket) + "_01.dat"; - fs::path fullpath = pathSmsgDir / fileName; - - //LogPrintf("bucket %d.\n", bucket); - //LogPrintf("bucket d %d.\n", bucket); - //LogPrintf("fileName %s.\n", fileName.c_str()); - - FILE *fp; - errno = 0; - if (!(fp = fopen(fullpath.string().c_str(), "rb"))) - { - LogPrintf("Error opening file: %s\nPath %s\n", strerror(errno), fullpath.string().c_str()); - return 1; - }; - - errno = 0; - if (fseek(fp, token.offset, SEEK_SET) != 0) - { - LogPrintf("fseek, strerror: %s.\n", strerror(errno)); - fclose(fp); - return 1; - }; - - SecureMessage smsg; - errno = 0; - if (fread(&smsg.hash[0], sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN) - { - LogPrintf("fread header failed: %s\n", strerror(errno)); - fclose(fp); - return 1; - }; - - try { - vchData.resize(SMSG_HDR_LEN + smsg.nPayload); - } catch (std::exception& e) { - LogPrintf("SecureMsgRetrieve(): Could not resize vchData, %u, %s\n", SMSG_HDR_LEN + smsg.nPayload, e.what()); - return 1; - }; - - memcpy(&vchData[0], &smsg.hash[0], SMSG_HDR_LEN); - errno = 0; - if (fread(&vchData[SMSG_HDR_LEN], sizeof(uint8_t), smsg.nPayload, fp) != smsg.nPayload) - { - LogPrintf("fread data failed: %s. Wanted %u bytes.\n", strerror(errno), smsg.nPayload); - fclose(fp); - return 1; - }; - - - fclose(fp); - - return 0; -}; - -int SecureMsgReceive(CNode* pfrom, std::vector& vchData) -{ - if (fDebugSmsg) - LogPrintf("SecureMsgReceive().\n"); - - if (vchData.size() < 12) // nBunch4 + timestamp8 - { - LogPrintf("Error: not enough data.\n"); - return 1; - }; - - uint32_t nBunch; - int64_t bktTime; - - memcpy(&nBunch, &vchData[0], 4); - memcpy(&bktTime, &vchData[4], 8); - - - // -- check bktTime () - // bucket may not exist yet - will be created when messages are added - int64_t now = GetTime(); - if (bktTime > now + SMSG_TIME_LEEWAY) - { - if (fDebugSmsg) - LogPrintf("bktTime > now.\n"); - // misbehave? - return 1; - } else - if (bktTime < now - SMSG_RETENTION) - { - if (fDebugSmsg) - LogPrintf("bktTime < now - SMSG_RETENTION.\n"); - // misbehave? - return 1; - }; - - std::map::iterator itb; - - if (nBunch == 0 || nBunch > 500) - { - LogPrintf("Error: Invalid no. messages received in bunch %u, for bucket %d.\n", nBunch, bktTime); - pfrom->Misbehaving(1); - - { - LOCK(cs_smsg); - // -- release lock on bucket if it exists - itb = smsgBuckets.find(bktTime); - if (itb != smsgBuckets.end()) - itb->second.nLockCount = 0; - } // cs_smsg - return 1; - }; - - uint32_t n = 12; - - for (uint32_t i = 0; i < nBunch; ++i) - { - if (vchData.size() - n < SMSG_HDR_LEN) - { - LogPrintf("Error: not enough data sent, n = %u.\n", n); - break; - }; - - SecureMessage *psmsg = (SecureMessage*) &vchData[n]; - - int rv; - if ((rv = SecureMsgValidate(&vchData[n], &vchData[n + SMSG_HDR_LEN], psmsg->nPayload)) != 0) - { - // message dropped - if (rv == 2) // invalid proof of work - { - pfrom->Misbehaving(10); - } else - { - pfrom->Misbehaving(1); - }; - continue; - }; - - { - LOCK(cs_smsg); - // -- store message, but don't hash bucket - if (SecureMsgStore(&vchData[n], &vchData[n + SMSG_HDR_LEN], psmsg->nPayload, false) != 0) - { - // message dropped - break; // continue? - }; - - if (SecureMsgScanMessage(&vchData[n], &vchData[n + SMSG_HDR_LEN], psmsg->nPayload, true) != 0) - { - // message recipient is not this node (or failed) - }; - } // cs_smsg - - n += SMSG_HDR_LEN + psmsg->nPayload; - }; - - { - LOCK(cs_smsg); - // -- if messages have been added, bucket must exist now - itb = smsgBuckets.find(bktTime); - if (itb == smsgBuckets.end()) - { - if (fDebugSmsg) - LogPrintf("Don't have bucket %d.\n", bktTime); - return 1; - }; - - itb->second.nLockCount = 0; // this node has received data from peer, release lock - itb->second.nLockPeerId = 0; - itb->second.hashBucket(); - } // cs_smsg - return 0; -}; - -int SecureMsgStoreUnscanned(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload) -{ - /* - When the wallet is locked a copy of each received message is stored to be scanned later if wallet is unlocked - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgStoreUnscanned()\n"); - - if (!pHeader - || !pPayload) - { - LogPrintf("Error: null pointer to header or payload.\n"); - return 1; - }; - - SecureMessage* psmsg = (SecureMessage*) pHeader; - - fs::path pathSmsgDir; - try { - pathSmsgDir = GetDataDir() / "smsgStore"; - fs::create_directory(pathSmsgDir); - } catch (const boost::filesystem::filesystem_error& ex) - { - LogPrintf("Error: Failed to create directory %s - %s\n", pathSmsgDir.string().c_str(), ex.what()); - return 1; - }; - - int64_t now = GetTime(); - if (psmsg->timestamp > now + SMSG_TIME_LEEWAY) - { - LogPrintf("Message > now.\n"); - return 1; - } else - if (psmsg->timestamp < now - SMSG_RETENTION) - { - LogPrintf("Message < SMSG_RETENTION.\n"); - return 1; - }; - - int64_t bucket = psmsg->timestamp - (psmsg->timestamp % SMSG_BUCKET_LEN); - - std::string fileName = boost::lexical_cast(bucket) + "_01_wl.dat"; - fs::path fullpath = pathSmsgDir / fileName; - - FILE *fp; - errno = 0; - if (!(fp = fopen(fullpath.string().c_str(), "ab"))) - { - LogPrintf("Error opening file: %s\n", strerror(errno)); - return 1; - }; - - if (fwrite(pHeader, sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN - || fwrite(pPayload, sizeof(uint8_t), nPayload, fp) != nPayload) - { - LogPrintf("fwrite failed: %s\n", strerror(errno)); - fclose(fp); - return 1; - }; - - fclose(fp); - - return 0; -}; - - -int SecureMsgStore(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, bool fUpdateBucket) -{ - if (fDebugSmsg) - { - LogPrintf("SecureMsgStore()\n"); - AssertLockHeld(cs_smsg); - }; - - - if (!pHeader - || !pPayload) - { - return errorN(1, "null pointer to header or payload."); - }; - - SecureMessage* psmsg = (SecureMessage*) pHeader; - - - long int ofs; - fs::path pathSmsgDir; - try { - pathSmsgDir = GetDataDir() / "smsgStore"; - fs::create_directory(pathSmsgDir); - } catch (const boost::filesystem::filesystem_error& ex) - { - return errorN(1, "Failed to create directory %s - %s.", pathSmsgDir.string().c_str(), ex.what()); - }; - - int64_t now = GetTime(); - if (psmsg->timestamp > now + SMSG_TIME_LEEWAY) - { - LogPrintf("Message > now.\n"); - return 1; - } else - if (psmsg->timestamp < now - SMSG_RETENTION) - { - LogPrintf("Message < SMSG_RETENTION.\n"); - return 1; - }; - - int64_t bucket = psmsg->timestamp - (psmsg->timestamp % SMSG_BUCKET_LEN); - - SecMsgToken token(psmsg->timestamp, pPayload, nPayload, 0); - - std::set& tokenSet = smsgBuckets[bucket].setTokens; - std::set::iterator it; - it = tokenSet.find(token); - if (it != tokenSet.end()) - { - LogPrintf("Already have message.\n"); - if (fDebugSmsg) - { - LogPrintf("nPayload: %u\n", nPayload); - LogPrintf("bucket: %d\n", bucket); - - LogPrintf("message ts: %d", token.timestamp); - std::vector vchShow; - vchShow.resize(8); - memcpy(&vchShow[0], token.sample, 8); - LogPrintf(" sample %s\n", ValueString(vchShow).c_str()); - /* - LogPrintf("\nmessages in bucket:\n"); - for (it = tokenSet.begin(); it != tokenSet.end(); ++it) - { - LogPrintf("message ts: %d", (*it).timestamp); - vchShow.resize(8); - memcpy(&vchShow[0], (*it).sample, 8); - LogPrintf(" sample %s\n", ValueString(vchShow).c_str()); - }; - */ - }; - return 1; - }; - - std::string fileName = boost::lexical_cast(bucket) + "_01.dat"; - fs::path fullpath = pathSmsgDir / fileName; - - FILE *fp; - errno = 0; - if (!(fp = fopen(fullpath.string().c_str(), "ab"))) - { - return errorN(1, "fopen failed: %s.", strerror(errno)); - }; - - // -- on windows ftell will always return 0 after fopen(ab), call fseek to set. - errno = 0; - if (fseek(fp, 0, SEEK_END) != 0) - return errorN(1, "fseek failed: %s.", strerror(errno)); - - ofs = ftell(fp); - - if (fwrite(pHeader, sizeof(uint8_t), SMSG_HDR_LEN, fp) != (size_t)SMSG_HDR_LEN - || fwrite(pPayload, sizeof(uint8_t), nPayload, fp) != nPayload) - { - fclose(fp); - return errorN(1, "fwrite failed: %s.", strerror(errno)); - }; - - fclose(fp); - - token.offset = ofs; - - //LogPrintf("token.offset: %d\n", token.offset); // DEBUG - tokenSet.insert(token); - - if (fUpdateBucket) - smsgBuckets[bucket].hashBucket(); - - if (fDebugSmsg) - LogPrintf("SecureMsg added to bucket %d.\n", bucket); - - return 0; -}; - -int SecureMsgStore(SecureMessage& smsg, bool fUpdateBucket) -{ - return SecureMsgStore(&smsg.hash[0], smsg.pPayload, smsg.nPayload, fUpdateBucket); -}; - -int SecureMsgValidate(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload) -{ - /* - returns - 0 success - 1 error - 2 invalid hash - 3 checksum mismatch - 4 invalid version - 5 payload is too large - */ - SecureMessage *psmsg = (SecureMessage*) pHeader; - - if (psmsg->version[0] != 1) - return 4; - - if (nPayload > SMSG_MAX_MSG_WORST) - return 5; - - uint8_t civ[32]; - uint8_t sha256Hash[32]; - int rv = 2; // invalid - - uint32_t nonce; - memcpy(&nonce, &psmsg->nonce[0], 4); - - if (fDebugSmsg) - LogPrintf("SecureMsgValidate() nonce %u.\n", nonce); - - for (int i = 0; i < 32; i+=4) - memcpy(civ+i, &nonce, 4); - - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - - uint32_t nBytes; - if (!HMAC_Init_ex(&ctx, &civ[0], 32, EVP_sha256(), NULL) - || !HMAC_Update(&ctx, (uint8_t*) pHeader+4, SMSG_HDR_LEN-4) - || !HMAC_Update(&ctx, (uint8_t*) pPayload, nPayload) - || !HMAC_Update(&ctx, pPayload, nPayload) - || !HMAC_Final(&ctx, sha256Hash, &nBytes) - || nBytes != 32) - { - if (fDebugSmsg) - LogPrintf("HMAC error.\n"); - rv = 1; // error - } else - { - if (sha256Hash[31] == 0 - && sha256Hash[30] == 0 - && (~(sha256Hash[29]) & ((1<<0) | (1<<1) | (1<<2)) )) - { - if (fDebugSmsg) - LogPrintf("Hash Valid.\n"); - rv = 0; // smsg is valid - }; - - if (sdc::memcmp_nta(psmsg->hash, sha256Hash, 4) != 0) - { - if (fDebugSmsg) - LogPrintf("Checksum mismatch.\n"); - rv = 3; // checksum mismatch - } - } - HMAC_CTX_cleanup(&ctx); - - return rv; -}; - -int SecureMsgSetHash(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload) -{ - /* proof of work and checksum - - May run in a thread, if shutdown detected, return. - - returns: - 0 success - 1 error - 2 stopped due to node shutdown - - */ - - SecureMessage* psmsg = (SecureMessage*) pHeader; - - int64_t nStart = GetTimeMillis(); - uint8_t civ[32]; - uint8_t sha256Hash[32]; - - bool found = false; - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - - uint32_t nonce = 0; - - //CBigNum bnTarget(2); - //bnTarget = bnTarget.pow(256 - 40); - - // -- break for HMAC_CTX_cleanup - for (;;) - { - if (!fSecMsgEnabled) - break; - - //psmsg->timestamp = GetTime(); - //memcpy(&psmsg->timestamp, &now, 8); - memcpy(&psmsg->nonce[0], &nonce, 4); - - for (int i = 0; i < 32; i+=4) - memcpy(civ+i, &nonce, 4); - - uint32_t nBytes; - if (!HMAC_Init_ex(&ctx, &civ[0], 32, EVP_sha256(), NULL) - || !HMAC_Update(&ctx, (uint8_t*) pHeader+4, SMSG_HDR_LEN-4) - || !HMAC_Update(&ctx, (uint8_t*) pPayload, nPayload) - || !HMAC_Update(&ctx, pPayload, nPayload) - || !HMAC_Final(&ctx, sha256Hash, &nBytes) - //|| !HMAC_Final(&ctx, &vchHash[0], &nBytes) - || nBytes != 32) - break; - - /* - if (CBigNum(vchHash) <= bnTarget) - { - found = true; - if (fDebugSmsg) - LogPrintf("Match %u\n", nonce); - break; - }; - */ - - if (sha256Hash[31] == 0 - && sha256Hash[30] == 0 - && (~(sha256Hash[29]) & ((1<<0) | (1<<1) | (1<<2)) )) - // && sha256Hash[29] == 0) - { - found = true; - //if (fDebugSmsg) - // LogPrintf("Match %u\n", nonce); - break; - } - - //if (nonce >= UINT32_MAX) - if (nonce >= 4294967295U) - { - if (fDebugSmsg) - LogPrintf("No match %u\n", nonce); - break; - //return 1; - } - nonce++; - }; - - HMAC_CTX_cleanup(&ctx); - - if (!fSecMsgEnabled) - { - if (fDebugSmsg) - LogPrintf("SecureMsgSetHash() stopped, shutdown detected.\n"); - return 2; - }; - - if (!found) - { - if (fDebugSmsg) - LogPrintf("SecureMsgSetHash() failed, took %d ms, nonce %u\n", GetTimeMillis() - nStart, nonce); - return 1; - }; - - memcpy(psmsg->hash, sha256Hash, 4); - //memcpy(psmsg->hash, &vchHash[0], 4); - - if (fDebugSmsg) - LogPrintf("SecureMsgSetHash() took %d ms, nonce %u\n", GetTimeMillis() - nStart, nonce); - - return 0; -}; - -int SecureMsgEncrypt(SecureMessage &smsg, const std::string &addressFrom, const std::string &addressTo, const std::string &message) -{ - /* Create a secure message - - Using similar method to bitmessage. - If bitmessage is secure this should be too. - https://bitmessage.org/wiki/Encryption - - Some differences: - bitmessage seems to use curve sect283r1 - *coin addresses use secp256k1 - - returns - 2 message is too long. - 3 addressFrom is invalid. - 4 addressTo is invalid. - 5 Could not get public key for addressTo. - 6 ECDH_compute_key failed - 7 Could not get private key for addressFrom. - 8 Could not allocate memory. - 9 Could not compress message data. - 10 Could not generate MAC. - 11 Encrypt failed. - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgEncrypt(%s, %s, ...)\n", addressFrom.c_str(), addressTo.c_str()); - - bool fSendAnonymous = (addressFrom.compare("anon") == 0); - - - if (message.size() > (fSendAnonymous ? SMSG_MAX_AMSG_BYTES : SMSG_MAX_MSG_BYTES)) - { - return errorN(2, "%s: Message is too long, %u.", __func__, message.size()); - }; - - smsg.version[0] = 1; - smsg.version[1] = 1; - smsg.timestamp = GetTime(); - - CBitcoinAddress coinAddrFrom; - CKeyID ckidFrom; - CKey keyFrom; - - - if(!fSendAnonymous) - { - if (!coinAddrFrom.SetString(addressFrom)) - { - return errorN(3, "%s: addressFrom is not valid.", __func__); - }; - - if (!coinAddrFrom.GetKeyID(ckidFrom)) - { - return errorN(4, "%s: coinAddrFrom.GetKeyID failed: %s.", __func__, coinAddrFrom.ToString().c_str()); - }; - }; - - - CBitcoinAddress coinAddrDest; - CKeyID ckidDest; - - if (!coinAddrDest.SetString(addressTo)) - { - return errorN(4, "%s: addressTo is not valid.", __func__); - }; - - if (!coinAddrDest.GetKeyID(ckidDest)) - { - return errorN(4, "%s: coinAddrDest.GetKeyID failed: %s.", __func__, coinAddrDest.ToString().c_str()); - }; - - // -- public key K is the destination address - CPubKey cpkDestK; - if (SecureMsgGetStoredKey(ckidDest, cpkDestK) != 0 - && SecureMsgGetLocalKey(ckidDest, cpkDestK) != 0) // maybe it's a local key (outbox?) - { - return errorN(5, "%s: Could not get public key for destination address.", __func__); - }; - - - // -- Generate 16 random bytes as IV. - RandAddSeedPerfmon(); - RAND_bytes(&smsg.iv[0], 16); - - - // -- Generate a new random EC key pair with private key called r and public key called R. - CKey keyR; - keyR.MakeNewKey(true); // make compressed key - - CECKey ecKeyR; - ecKeyR.SetSecretBytes(keyR.begin()); - - // -- Do an EC point multiply with public key K and private key r. This gives you public key P. - CECKey ecKeyK; - if (!ecKeyK.SetPubKey(cpkDestK)) - { - // address to is invalid - return errorN(4, "%s: Could not set pubkey for K: %s.", __func__, HexStr(cpkDestK).c_str()); - }; - - std::vector vchP; - vchP.resize(32); - EC_KEY *pkeyr = ecKeyR.GetECKey(); - EC_KEY *pkeyK = ecKeyK.GetECKey(); - - // always seems to be 32, worth checking? - //int field_size = EC_GROUP_get_degree(EC_KEY_get0_group(pkeyr)); - //int secret_len = (field_size+7)/8; - //LogPrintf("secret_len %d.\n", secret_len); - - // -- ECDH_compute_key returns the same P if fed compressed or uncompressed public keys - ECDH_set_method(pkeyr, ECDH_OpenSSL()); - int lenP = ECDH_compute_key(&vchP[0], 32, EC_KEY_get0_public_key(pkeyK), pkeyr, NULL); - - if (lenP != 32) - { - return errorN(6, "%s: ECDH_compute_key failed, lenP: %d.", __func__, lenP); - }; - - CPubKey cpkR = keyR.GetPubKey(); - if (!cpkR.IsValid() - || !cpkR.IsCompressed()) - { - return errorN(1, "%s: Could not get public key for key R.", __func__); - }; - - memcpy(smsg.cpkR, cpkR.begin(), 33); - - - // -- Use public key P and calculate the SHA512 hash H. - // The first 32 bytes of H are called key_e and the last 32 bytes are called key_m. - std::vector vchHashed; - vchHashed.resize(64); // 512 - SHA512(&vchP[0], vchP.size(), (uint8_t*)&vchHashed[0]); - std::vector key_e(&vchHashed[0], &vchHashed[0]+32); - std::vector key_m(&vchHashed[32], &vchHashed[32]+32); - - - std::vector vchPayload; - std::vector vchCompressed; - uint8_t *pMsgData; - uint32_t lenMsgData; - - uint32_t lenMsg = message.size(); - if (lenMsg > 128) - { - // -- only compress if over 128 bytes - int worstCase = LZ4_compressBound(message.size()); - try { vchCompressed.resize(worstCase); } catch (std::exception& e) - { - return errorN(8, "%s: vchCompressed.resize %u threw: %s.", __func__, worstCase, e.what()); - }; - - int lenComp = LZ4_compress((char*)message.c_str(), (char*)&vchCompressed[0], lenMsg); - if (lenComp < 1) - { - return errorN(9, "%s: Could not compress message data.", __func__); - }; - - pMsgData = &vchCompressed[0]; - lenMsgData = lenComp; - - } else - { - // -- no compression - pMsgData = (uint8_t*)message.c_str(); - lenMsgData = lenMsg; - }; - - if (fSendAnonymous) - { - try { vchPayload.resize(9 + lenMsgData); } catch (std::exception& e) - { - return errorN(8, "%s: vchPayload.resize %u threw: %s.", __func__, 9 + lenMsgData, e.what()); - }; - - memcpy(&vchPayload[9], pMsgData, lenMsgData); - - vchPayload[0] = 250; // id as anonymous message - // -- next 4 bytes are unused - there to ensure encrypted payload always > 8 bytes - memcpy(&vchPayload[5], &lenMsg, 4); // length of uncompressed plain text - } else - { - try { vchPayload.resize(SMSG_PL_HDR_LEN + lenMsgData); } catch (std::exception& e) - { - return errorN(8, "%s: vchPayload.resize %u threw: %s.", __func__, SMSG_PL_HDR_LEN + lenMsgData, e.what()); - }; - - memcpy(&vchPayload[SMSG_PL_HDR_LEN], pMsgData, lenMsgData); - // -- compact signature proves ownership of from address and allows the public key to be recovered, recipient can always reply. - if (!pwalletMain->GetKey(ckidFrom, keyFrom)) - { - return errorN(7, "%s: Could not get private key for addressFrom.", __func__); - }; - - // -- sign the plaintext - std::vector vchSignature; - vchSignature.resize(65); - keyFrom.SignCompact(Hash(message.begin(), message.end()), vchSignature); - - // -- Save some bytes by sending address raw - vchPayload[0] = (static_cast(&coinAddrFrom))->getVersion(); // vchPayload[0] = coinAddrDest.nVersion; - memcpy(&vchPayload[1], (static_cast(&ckidFrom))->GetPPN(), 20); // memcpy(&vchPayload[1], ckidDest.pn, 20); - - memcpy(&vchPayload[1+20], &vchSignature[0], vchSignature.size()); - memcpy(&vchPayload[1+20+65], &lenMsg, 4); // length of uncompressed plain text - }; - - - SecMsgCrypter crypter; - crypter.SetKey(key_e, smsg.iv); - std::vector vchCiphertext; - - if (!crypter.Encrypt(&vchPayload[0], vchPayload.size(), vchCiphertext)) - { - return errorN(11, "%s: crypter.Encrypt failed.", __func__); - }; - - try { smsg.pPayload = new uint8_t[vchCiphertext.size()]; } catch (std::exception& e) - { - return errorN(8, "%s: Could not allocate pPayload, exception: %s.", __func__, e.what()); - }; - - memcpy(smsg.pPayload, &vchCiphertext[0], vchCiphertext.size()); - smsg.nPayload = vchCiphertext.size(); - - - // -- Calculate a 32 byte MAC with HMACSHA256, using key_m as salt - // Message authentication code, (hash of timestamp + destination + payload) - bool fHmacOk = true; - uint32_t nBytes = 32; - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - - if (!HMAC_Init_ex(&ctx, &key_m[0], 32, EVP_sha256(), NULL) - || !HMAC_Update(&ctx, (uint8_t*) &smsg.timestamp, sizeof(smsg.timestamp)) - || !HMAC_Update(&ctx, &vchCiphertext[0], vchCiphertext.size()) - || !HMAC_Final(&ctx, smsg.mac, &nBytes) - || nBytes != 32) - fHmacOk = false; - - HMAC_CTX_cleanup(&ctx); - - if (!fHmacOk) - { - return errorN(10, "%s: Could not generate MAC.", __func__); - }; - - return 0; -}; - -int SecureMsgSend(std::string &addressFrom, std::string &addressTo, std::string &message, std::string &sError) -{ - /* Encrypt secure message, and place it on the network - Make a copy of the message to sender's first address and place in send queue db - proof of work thread will pick up messages from send queue db - */ - - if (fDebugSmsg) - LogPrintf("SecureMsgSend(%s, %s, ...)\n", addressFrom.c_str(), addressTo.c_str()); - - if (pwalletMain->IsLocked()) - { - sError = "Wallet is locked, wallet must be unlocked to send and recieve messages."; - LogPrintf("%s\n", sError); - return 1; - }; - - bool fSendAnonymous = (addressFrom.compare("anon") == 0); - - if (message.size() > (fSendAnonymous ? SMSG_MAX_AMSG_BYTES : SMSG_MAX_MSG_BYTES)) - { - std::ostringstream oss; - oss << message.size() << " > " << (fSendAnonymous ? SMSG_MAX_AMSG_BYTES : SMSG_MAX_MSG_BYTES); - sError = "Message is too long, " + oss.str(); - LogPrintf("Message is too long, %u.\n", message.size()); - return 1; - }; - - int rv; - SecureMessage smsg; - - if ((rv = SecureMsgEncrypt(smsg, addressFrom, addressTo, message)) != 0) - { - LogPrintf("SecureMsgSend(), encrypt for recipient failed.\n"); - - switch(rv) - { - case 2: sError = "Message is too long."; break; - case 3: sError = "Invalid addressFrom."; break; - case 4: sError = "Invalid addressTo."; break; - case 5: sError = "Could not get public key for addressTo."; break; - case 6: sError = "ECDH_compute_key failed."; break; - case 7: sError = "Could not get private key for addressFrom."; break; - case 8: sError = "Could not allocate memory."; break; - case 9: sError = "Could not compress message data."; break; - case 10: sError = "Could not generate MAC."; break; - case 11: sError = "Encrypt failed."; break; - default: sError = "Unspecified Error."; break; - }; - - return rv; - }; - - - // -- Place message in send queue, proof of work will happen in a thread. - std::string sPrefix("qm"); - uint8_t chKey[18]; - memcpy(&chKey[0], sPrefix.data(), 2); - memcpy(&chKey[2], &smsg.timestamp, 8); - memcpy(&chKey[10], &smsg.pPayload, 8); - - SecMsgStored smsgSQ; - - smsgSQ.timeReceived = GetTime(); - smsgSQ.sAddrTo = addressTo; - - try { smsgSQ.vchMessage.resize(SMSG_HDR_LEN + smsg.nPayload); } catch (std::exception& e) - { - LogPrintf("smsgSQ.vchMessage.resize %u threw: %s.\n", SMSG_HDR_LEN + smsg.nPayload, e.what()); - sError = "Could not allocate memory."; - return 8; - }; - - memcpy(&smsgSQ.vchMessage[0], &smsg.hash[0], SMSG_HDR_LEN); - memcpy(&smsgSQ.vchMessage[SMSG_HDR_LEN], smsg.pPayload, smsg.nPayload); - - { - LOCK(cs_smsgDB); - SecMsgDB dbSendQueue; - if (dbSendQueue.Open("cw")) - { - dbSendQueue.WriteSmesg(chKey, smsgSQ); - //NotifySecMsgSendQueueChanged(smsgOutbox); - }; - } // cs_smsgDB - - // TODO: only update outbox when proof of work thread is done. - - // -- for outbox create a copy encrypted for owned address - // if the wallet is encrypted private key needed to decrypt will be unavailable - - if (fDebugSmsg) - LogPrintf("Encrypting message for outbox.\n"); - - std::string addressOutbox = "None"; - CBitcoinAddress coinAddrOutbox; - - BOOST_FOREACH(const PAIRTYPE(CTxDestination, std::string)& entry, pwalletMain->mapAddressBook) - { - // -- get first owned address - if (!IsDestMine(*pwalletMain, entry.first)) - continue; - - const CBitcoinAddress& address = entry.first; - - addressOutbox = address.ToString(); - if (!coinAddrOutbox.SetString(addressOutbox)) // test valid - continue; - break; - }; - - if (addressOutbox == "None") - { - LogPrintf("Warning: SecureMsgSend() could not find an address to encrypt outbox message with.\n"); - } else - { - if (fDebugSmsg) - LogPrintf("Encrypting a copy for outbox, using address %s\n", addressOutbox.c_str()); - - SecureMessage smsgForOutbox; - if ((rv = SecureMsgEncrypt(smsgForOutbox, addressFrom, addressOutbox, message)) != 0) - { - LogPrintf("SecureMsgSend(), encrypt for outbox failed, %d.\n", rv); - } else - { - // -- save sent message to db - std::string sPrefix("sm"); - uint8_t chKey[18]; - memcpy(&chKey[0], sPrefix.data(), 2); - memcpy(&chKey[2], &smsgForOutbox.timestamp, 8); - memcpy(&chKey[10], &smsgForOutbox.pPayload, 8); // sample - - SecMsgStored smsgOutbox; - - smsgOutbox.timeReceived = GetTime(); - smsgOutbox.sAddrTo = addressTo; - smsgOutbox.sAddrOutbox = addressOutbox; - - try { - smsgOutbox.vchMessage.resize(SMSG_HDR_LEN + smsgForOutbox.nPayload); - } catch (std::exception& e) { - LogPrintf("smsgOutbox.vchMessage.resize %u threw: %s.\n", SMSG_HDR_LEN + smsgForOutbox.nPayload, e.what()); - sError = "Could not allocate memory."; - return 8; - }; - memcpy(&smsgOutbox.vchMessage[0], &smsgForOutbox.hash[0], SMSG_HDR_LEN); - memcpy(&smsgOutbox.vchMessage[SMSG_HDR_LEN], smsgForOutbox.pPayload, smsgForOutbox.nPayload); - - - { - LOCK(cs_smsgDB); - SecMsgDB dbSent; - - if (dbSent.Open("cw")) - { - dbSent.WriteSmesg(chKey, smsgOutbox); - NotifySecMsgOutboxChanged(smsgOutbox); - }; - } // cs_smsgDB - }; - }; - - if (fDebugSmsg) - LogPrintf("Secure message queued for sending to %s.\n", addressTo.c_str()); - - return 0; -}; - - -int SecureMsgDecrypt(bool fTestOnly, std::string &address, uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, MessageData &msg) -{ - /* Decrypt secure message - - address is the owned address to decrypt with. - - validate first in SecureMsgValidate - - returns - 1 Error - 2 Unknown version number - 3 Decrypt address is not valid. - 8 Could not allocate memory - */ - - if (fDebugSmsg) - LogPrintf("%s: using %s, testonly %d.\n", __func__, address.c_str(), fTestOnly); - - if (!pHeader - || !pPayload) - { - return errorN(1, "%s: null pointer to header or payload.", __func__); - }; - - SecureMessage* psmsg = (SecureMessage*) pHeader; - - - if (psmsg->version[0] != 1) - { - return errorN(2, "%s: Unknown version number.", __func__); - }; - - - - // -- Fetch private key k, used to decrypt - CBitcoinAddress coinAddrDest; - CKeyID ckidDest; - CKey keyDest; - if (!coinAddrDest.SetString(address)) - { - return errorN(3, "%s: Address is not valid.", __func__); - }; - if (!coinAddrDest.GetKeyID(ckidDest)) - { - return errorN(3, "%s: coinAddrDest.GetKeyID failed: %s.", __func__, coinAddrDest.ToString().c_str()); - }; - if (!pwalletMain->GetKey(ckidDest, keyDest)) - { - return errorN(3, "%s: Could not get private key for addressDest.", __func__); - }; - - - - CPubKey cpkR(psmsg->cpkR, psmsg->cpkR+33); - if (!cpkR.IsValid()) - { - return errorN(1, "%s: Could not get pubkey for key R.", __func__); - }; - - CECKey ecKeyR; - if (!ecKeyR.SetPubKey(cpkR)) - { - return errorN(1, "%s: Could not set pubkey for key R: %s.", __func__, HexStr(cpkR).c_str()); - }; - - CECKey ecKeyDest; - ecKeyDest.SetSecretBytes(keyDest.begin()); - - // -- Do an EC point multiply with private key k and public key R. This gives you public key P. - std::vector vchP; - vchP.resize(32); - EC_KEY* pkeyk = ecKeyDest.GetECKey(); - EC_KEY* pkeyR = ecKeyR.GetECKey(); - - ECDH_set_method(pkeyk, ECDH_OpenSSL()); - int lenPdec = ECDH_compute_key(&vchP[0], 32, EC_KEY_get0_public_key(pkeyR), pkeyk, NULL); - - if (lenPdec != 32) - { - return errorN(1, "%s: ECDH_compute_key failed, lenPdec: %d.", __func__, lenPdec); - }; - - - // -- Use public key P to calculate the SHA512 hash H. - // The first 32 bytes of H are called key_e and the last 32 bytes are called key_m. - std::vector vchHashedDec; - vchHashedDec.resize(64); // 512 bits - SHA512(&vchP[0], vchP.size(), (uint8_t*)&vchHashedDec[0]); - std::vector key_e(&vchHashedDec[0], &vchHashedDec[0]+32); - std::vector key_m(&vchHashedDec[32], &vchHashedDec[32]+32); - - - // -- Message authentication code, (hash of timestamp + destination + payload) - uint8_t MAC[32]; - bool fHmacOk = true; - uint32_t nBytes = 32; - HMAC_CTX ctx; - HMAC_CTX_init(&ctx); - - if (!HMAC_Init_ex(&ctx, &key_m[0], 32, EVP_sha256(), NULL) - || !HMAC_Update(&ctx, (uint8_t*) &psmsg->timestamp, sizeof(psmsg->timestamp)) - || !HMAC_Update(&ctx, pPayload, nPayload) - || !HMAC_Final(&ctx, MAC, &nBytes) - || nBytes != 32) - fHmacOk = false; - - HMAC_CTX_cleanup(&ctx); - - if (!fHmacOk) - { - return errorN(1, "%s: Could not generate MAC.", __func__); - }; - - if (sdc::memcmp_nta(MAC, psmsg->mac, 32) != 0) - { - if (fDebugSmsg) - LogPrintf("MAC does not match.\n"); // expected if message is not to address on node - - return 1; - }; - - if (fTestOnly) - return 0; - - SecMsgCrypter crypter; - crypter.SetKey(key_e, psmsg->iv); - std::vector vchPayload; - if (!crypter.Decrypt(pPayload, nPayload, vchPayload)) - { - return errorN(1, "%s: Decrypt failed.", __func__); - }; - - msg.timestamp = psmsg->timestamp; - uint32_t lenData; - uint32_t lenPlain; - - uint8_t* pMsgData; - bool fFromAnonymous; - if ((uint32_t)vchPayload[0] == 250) - { - fFromAnonymous = true; - lenData = vchPayload.size() - (9); - memcpy(&lenPlain, &vchPayload[5], 4); - pMsgData = &vchPayload[9]; - } else - { - fFromAnonymous = false; - lenData = vchPayload.size() - (SMSG_PL_HDR_LEN); - memcpy(&lenPlain, &vchPayload[1+20+65], 4); - pMsgData = &vchPayload[SMSG_PL_HDR_LEN]; - }; - - try { - msg.vchMessage.resize(lenPlain + 1); - } catch (std::exception& e) { - return errorN(8, "%s: msg.vchMessage.resize %u threw: %s.", __func__, lenPlain + 1, e.what()); - }; - - - if (lenPlain > 128) - { - // -- decompress - if (LZ4_decompress_safe((char*) pMsgData, (char*) &msg.vchMessage[0], lenData, lenPlain) != (int) lenPlain) - { - return errorN(1, "%s: Could not decompress message data.", __func__); - }; - } else - { - // -- plaintext - memcpy(&msg.vchMessage[0], pMsgData, lenPlain); - }; - - msg.vchMessage[lenPlain] = '\0'; - - if (fFromAnonymous) - { - // -- Anonymous sender - msg.sFromAddress = "anon"; - } else - { - std::vector vchUint160; - vchUint160.resize(20); - - memcpy(&vchUint160[0], &vchPayload[1], 20); - - uint160 ui160(vchUint160); - CKeyID ckidFrom(ui160); - - CBitcoinAddress coinAddrFrom; - coinAddrFrom.Set(ckidFrom); - if (!coinAddrFrom.IsValid()) - { - return errorN(1, "%s: From Address is invalid.", __func__); - }; - - std::vector vchSig; - vchSig.resize(65); - - memcpy(&vchSig[0], &vchPayload[1+20], 65); - - CPubKey cpkFromSig; - cpkFromSig.RecoverCompact(Hash(msg.vchMessage.begin(), msg.vchMessage.end()-1), vchSig); - if (!cpkFromSig.IsValid()) - { - return errorN(1, "%s: Signature validation failed.", __func__); - }; - - // -- get address for the compressed public key - CBitcoinAddress coinAddrFromSig; - coinAddrFromSig.Set(cpkFromSig.GetID()); - - if (!(coinAddrFrom == coinAddrFromSig)) - { - return errorN(1, "%s: Signature validation failed.", __func__); - }; - - int rv = 5; - try { - rv = SecureMsgInsertAddress(ckidFrom, cpkFromSig); - } catch (std::exception& e) { - LogPrintf("SecureMsgInsertAddress(), exception: %s.\n", e.what()); - //return 1; - }; - - switch(rv) - { - case 0: - LogPrintf("Sender public key added to db.\n"); - break; - case 4: - LogPrintf("Sender public key already in db.\n"); - break; - default: - LogPrintf("Error adding sender public key to db.\n"); - break; - }; - - msg.sFromAddress = coinAddrFrom.ToString(); - }; - - if (fDebugSmsg) - LogPrintf("Decrypted message for %s.\n", address.c_str()); - - return 0; -}; - -int SecureMsgDecrypt(bool fTestOnly, std::string &address, SecureMessage &smsg, MessageData &msg) -{ - return SecureMsgDecrypt(fTestOnly, address, &smsg.hash[0], smsg.pPayload, smsg.nPayload, msg); -}; diff --git a/src/smessage.h b/src/smessage.h index aa4460d0f3..d7859a09f9 100644 --- a/src/smessage.h +++ b/src/smessage.h @@ -1,220 +1,16 @@ -// Copyright (c) 2014-2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #ifndef SEC_MESSAGE_H #define SEC_MESSAGE_H -#include -#include +#include "allocators.h" +#include -#include "net.h" -#include "db.h" -#include "wallet.h" -#include "lz4/lz4.h" - -const unsigned int SMSG_HDR_LEN = 104; // length of unencrypted header, 4 + 2 + 1 + 8 + 16 + 33 + 32 + 4 +4 -const unsigned int SMSG_PL_HDR_LEN = 1+20+65+4; // length of encrypted header in payload - -const unsigned int SMSG_BUCKET_LEN = 60 * 10; // in seconds -const unsigned int SMSG_RETENTION = 60 * 60 * 48; // in seconds -const unsigned int SMSG_SEND_DELAY = 2; // in seconds, SecureMsgSendData will delay this long between firing -const unsigned int SMSG_THREAD_DELAY = 30; -const unsigned int SMSG_THREAD_LOG_GAP = 6; - -const unsigned int SMSG_TIME_LEEWAY = 60; -const unsigned int SMSG_TIME_IGNORE = 90; // seconds that a peer is ignored for if they fail to deliver messages for a smsgWant - - -const unsigned int SMSG_MAX_MSG_BYTES = 4096; // the user input part -const unsigned int SMSG_MAX_AMSG_BYTES = 512; // the user input part (ANON) - -// max size of payload worst case compression -const unsigned int SMSG_MAX_MSG_WORST = LZ4_COMPRESSBOUND(SMSG_MAX_MSG_BYTES+SMSG_PL_HDR_LEN); - -#define SMSG_MASK_UNREAD (1 << 0) - -extern bool fSecMsgEnabled; - -class SecMsgStored; - -// Inbox db changed, called with lock cs_smsgDB held. -extern boost::signals2::signal NotifySecMsgInboxChanged; - -// Outbox db changed, called with lock cs_smsgDB held. -extern boost::signals2::signal NotifySecMsgOutboxChanged; - -// Wallet Unlocked, called after all messages received while locked have been processed. -extern boost::signals2::signal NotifySecMsgWalletUnlocked; - -class SecMsgBucket; -class SecMsgAddress; -class SecMsgOptions; - -extern std::map smsgBuckets; -extern std::vector smsgAddresses; -extern SecMsgOptions smsgOptions; - -extern CCriticalSection cs_smsg; // all except inbox and outbox -extern CCriticalSection cs_smsgDB; - -#pragma pack(push, 1) -class SecureMessage -{ -public: - SecureMessage() - { - nPayload = 0; - pPayload = NULL; - paid = false; - }; - - ~SecureMessage() - { - if (pPayload) - delete[] pPayload; - pPayload = NULL; - }; - - uint8_t hash[4]; - uint8_t version[2]; - uint8_t flags; - int64_t timestamp; - uint8_t iv[16]; - uint8_t cpkR[33]; - uint8_t mac[32]; - uint8_t nonce[4]; - uint32_t nPayload; - uint8_t* pPayload; - bool paid; - -}; -#pragma pack(pop) - -class MessageData -{ -// -- Decrypted SecureMessage data -public: - int64_t timestamp; - std::string sToAddress; - std::string sFromAddress; - std::vector vchMessage; // null terminated plaintext -}; - -class SecMsgToken -{ -public: - SecMsgToken(int64_t ts, uint8_t* p, int np, long int o) - { - timestamp = ts; - - if (np < 8) // payload will always be > 8, just make sure - memset(sample, 0, 8); - else - memcpy(sample, p, 8); - offset = o; - }; - - SecMsgToken() {}; - - ~SecMsgToken() {}; - - bool operator <(const SecMsgToken& y) const - { - // pack and memcmp from timesent? - if (timestamp == y.timestamp) - return memcmp(sample, y.sample, 8) < 0; - return timestamp < y.timestamp; - } - - int64_t timestamp; // doesn't need to be full 64 bytes? - uint8_t sample[8]; // first 8 bytes of payload - a hash - int64_t offset; // offset -}; - -class SecMsgBucket -{ -public: - SecMsgBucket() - { - timeChanged = 0; - hash = 0; - nLockCount = 0; - nLockPeerId = 0; - }; - ~SecMsgBucket() {}; - - void hashBucket(); - - int64_t timeChanged; - uint32_t hash; // token set should get ordered the same on each node - uint32_t nLockCount; // set when smsgWant first sent, unset at end of smsgMsg, ticks down in ThreadSecureMsg() - NodeId nLockPeerId; // id of peer that bucket is locked for - std::set setTokens; - -}; - -// -- get at the data -class CBitcoinAddress_B : public CBitcoinAddress -{ -public: - uint8_t getVersion() - { - // TODO: fix - if (vchVersion.size() > 0) - return vchVersion[0]; - return 0; - } -}; - -class CKeyID_B : public CKeyID -{ -public: - uint32_t* GetPPN() - { - return pn; - } -}; - -class SecMsgAddress -{ -public: - SecMsgAddress() {}; - SecMsgAddress(std::string sAddr, bool receiveOn, bool receiveAnon) - { - sAddress = sAddr; - fReceiveEnabled = receiveOn; - fReceiveAnon = receiveAnon; - }; - - std::string sAddress; - bool fReceiveEnabled; - bool fReceiveAnon; - - IMPLEMENT_SERIALIZE - ( - READWRITE(this->sAddress); - READWRITE(this->fReceiveEnabled); - READWRITE(this->fReceiveAnon); - ); -}; - -// Secure Message Options -class SecMsgOptions -{ -public: - SecMsgOptions() - { - // -- default options - fNewAddressRecv = true; - fNewAddressAnon = true; - fScanIncoming = true; - } - - bool fNewAddressRecv; - bool fNewAddressAnon; - bool fScanIncoming; -}; // Secure Message Crypter class SecMsgCrypter @@ -225,14 +21,13 @@ class SecMsgCrypter bool fKeySet; public: - SecMsgCrypter() + SecMsgCrypter() : fKeySet(false) { // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap) // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process. LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey); LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV); - fKeySet = false; } ~SecMsgCrypter() @@ -252,115 +47,5 @@ class SecMsgCrypter bool Decrypt(uint8_t* chCiphertext, uint32_t nCipher, std::vector& vchPlaintext); }; -// Secure Message storage -class SecMsgStored -{ -public: - int64_t timeReceived; - char status; // read etc - uint16_t folderId; - std::string sAddrTo; // when in owned addr, when sent remote addr - std::string sAddrOutbox; // owned address this copy was encrypted with - std::vector vchMessage; // message header + encryped payload - - IMPLEMENT_SERIALIZE - ( - READWRITE(this->timeReceived); - READWRITE(this->status); - READWRITE(this->folderId); - READWRITE(this->sAddrTo); - READWRITE(this->sAddrOutbox); - READWRITE(this->vchMessage); - ); -}; - -class SecMsgDB -{ -public: - SecMsgDB() - { - activeBatch = NULL; - }; - - ~SecMsgDB() - { - // -- deletes only data scoped to this SecMsgDB object. - if (activeBatch) - delete activeBatch; - }; - - bool Open(const char* pszMode="r+"); - - bool ScanBatch(const CDataStream& key, std::string* value, bool* deleted) const; - - bool TxnBegin(); - bool TxnCommit(); - bool TxnAbort(); - - bool ReadPK(CKeyID& addr, CPubKey& pubkey); - bool WritePK(CKeyID& addr, CPubKey& pubkey); - bool ExistsPK(CKeyID& addr); - - bool NextSmesg(leveldb::Iterator* it, std::string& prefix, uint8_t* vchKey, SecMsgStored& smsgStored); - bool NextSmesgKey(leveldb::Iterator* it, std::string& prefix, uint8_t* vchKey); - bool ReadSmesg(uint8_t* chKey, SecMsgStored& smsgStored); - bool WriteSmesg(uint8_t* chKey, SecMsgStored& smsgStored); - bool ExistsSmesg(uint8_t* chKey); - bool EraseSmesg(uint8_t* chKey); - - leveldb::DB *pdb; // points to the global instance - leveldb::WriteBatch *activeBatch; - -}; - -int SecureMsgBuildBucketSet(); -int SecureMsgAddWalletAddresses(); - -int SecureMsgReadIni(); -int SecureMsgWriteIni(); - -bool SecureMsgStart(bool fDontStart, bool fScanChain); -bool SecureMsgShutdown(); - -bool SecureMsgEnable(); -bool SecureMsgDisable(); - -bool SecureMsgReceiveData(CNode* pfrom, std::string strCommand, CDataStream& vRecv); -bool SecureMsgSendData(CNode* pto, bool fSendTrickle); - -bool SecureMsgScanBlock(CBlock& block); -bool ScanChainForPublicKeys(CBlockIndex* pindexStart); -bool SecureMsgScanBlockChain(); -bool SecureMsgScanBuckets(); - -int SecureMsgWalletUnlocked(); -int SecureMsgWalletKeyChanged(std::string sAddress, std::string sLabel, ChangeType mode); - -int SecureMsgScanMessage(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, bool reportToGui); - -int SecureMsgGetStoredKey(CKeyID& ckid, CPubKey& cpkOut); -int SecureMsgGetLocalKey(CKeyID& ckid, CPubKey& cpkOut); -int SecureMsgGetLocalPublicKey(std::string& strAddress, std::string& strPublicKey); - -int SecureMsgAddAddress(std::string& address, std::string& publicKey); - -int SecureMsgRetrieve(SecMsgToken &token, std::vector& vchData); - -int SecureMsgReceive(CNode* pfrom, std::vector& vchData); - -int SecureMsgStoreUnscanned(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload); -int SecureMsgStore(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, bool fUpdateBucket); -int SecureMsgStore(SecureMessage& smsg, bool fUpdateBucket); - -int SecureMsgSend(std::string &addressFrom, std::string &addressTo, std::string &message, std::string &sError); - -int SecureMsgValidate(uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload); -int SecureMsgSetHash (uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload); - -int SecureMsgEncrypt(SecureMessage &smsg, const std::string &addressFrom, const std::string &addressTo, const std::string &message); - -int SecureMsgDecrypt(bool fTestOnly, std::string &address, uint8_t *pHeader, uint8_t *pPayload, uint32_t nPayload, MessageData &msg); -int SecureMsgDecrypt(bool fTestOnly, std::string &address, SecureMessage &smsg, MessageData &msg); - #endif // SEC_MESSAGE_H diff --git a/src/shadowcoind.cpp b/src/spectrecoind.cpp similarity index 80% rename from src/shadowcoind.cpp rename to src/spectrecoind.cpp index 651c809ce2..4bf8e19a4b 100644 --- a/src/shadowcoind.cpp +++ b/src/spectrecoind.cpp @@ -1,15 +1,22 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "rpcserver.h" #include "rpcclient.h" #include "init.h" #include +#include #include "protocol.h" +#ifdef _MSC_BUILD +#include "win/unistd.h" +#endif void ThreadCli() @@ -18,35 +25,35 @@ void ThreadCli() // TODO: // unbuffered terminal input on linux // format help text - + char buffer[4096]; size_t n; fd_set rfds; struct timeval tv; - - printf("Shadow CLI ready:\n> "); + + printf("Spectre CLI ready:\n> "); fflush(stdout); - + for (;;) { boost::this_thread::interruption_point(); - + // - must be set every iteration FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); tv.tv_sec = 0; tv.tv_usec = 200000; - - if (select(1, &rfds, NULL, NULL, &tv) < 1) // read blocks thread from interrupt + + if (select(1, &rfds, nullptr, nullptr, &tv) < 1) // read blocks thread from interrupt continue; - + if ((n = read(STDIN_FILENO, buffer, sizeof(buffer))) < 1) continue; - + buffer[n] = '\0'; for ( ; n > 0 && (buffer[n-1] == '\n' || buffer[n-1] == '\r'); --n) buffer[n-1] = '\0'; - + if (strcmp(buffer, "stop") == 0 || strcmp(buffer, "exit") == 0 || strcmp(buffer, "quit") == 0 @@ -55,15 +62,15 @@ void ThreadCli() puts("Exiting..."); break; }; - - + + std::string strMethod; std::vector strParams; char *p; if ((p = strchr(buffer, ' '))) { strMethod = std::string(buffer, p); - + char *pPS = p+1; char *pPE = p+1; while (*pPS @@ -77,22 +84,22 @@ void ThreadCli() { strMethod = std::string(buffer); }; - + std::string strReply; JSONRequest jreq; - + try { json_spirit::Array params = RPCConvertValues(strMethod, strParams); json_spirit::Value result = tableRPC.execute(strMethod, params); - + strReply = json_spirit::write_string(result, true); - + ReplaceStrInPlace(strReply, "\\n", "\n"); // format help msg - - if (write(STDOUT_FILENO, strReply.data(), strReply.length()) != (uint32_t) strReply.length()) + + if (write(STDOUT_FILENO, strReply.data(), strReply.length()) != static_cast(strReply.length())) throw std::runtime_error("write failed."); - + printf("\n> "); fflush(stdout); } catch (json_spirit::Object& objError) @@ -107,28 +114,28 @@ void ThreadCli() }; fflush(stdout); }; - + StartShutdown(); }; void WaitForShutdown(boost::thread_group* threadGroup) { bool fShutdown = ShutdownRequested(); - + if (!fDaemon && GetBoolArg("-cli", false)) { threadGroup->create_thread(boost::bind(&TraceThread, "cli", &ThreadCli)); }; - + // Tell the main threads to shutdown. while (!fShutdown) { MilliSleep(200); fShutdown = ShutdownRequested(); }; - - LogPrintf("ShadowCoin shutdown.\n\n"); - + + LogPrintf("Alias shutdown.\n\n"); + if (threadGroup) { threadGroup->interrupt_all(); @@ -143,7 +150,7 @@ void WaitForShutdown(boost::thread_group* threadGroup) bool AppInit(int argc, char* argv[]) { boost::thread_group threadGroup; - + bool fRet = false; try { @@ -152,23 +159,23 @@ bool AppInit(int argc, char* argv[]) // // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main() ParseParameters(argc, argv); - if (!boost::filesystem::is_directory(GetDataDir(false))) + if (!fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified directory does not exist\n"); Shutdown(); }; - + ReadConfigFile(mapArgs, mapMultiArgs); - - if (mapArgs.count("-?") || mapArgs.count("--help")) + + if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help")) { // First part of help message is specific to bitcoind / RPC client - std::string strUsage = _("ShadowCoin version") + " " + FormatFullVersion() + "\n\n" + + std::string strUsage = _("Alias version") + " " + FormatFullVersion() + "\n\n" + _("Usage:") + "\n" + - " shadowcoind [options] " + "\n" + - " shadowcoind [options] [params] " + _("Send command to -server or shadowcoind") + "\n" + - " shadowcoind [options] help " + _("List commands") + "\n" + - " shadowcoind [options] help " + _("Get help for a command") + "\n"; + " aliaswalletd [options] " + "\n" + + " aliaswalletd [options] [params] " + _("Send command to -server or aliaswalletd") + "\n" + + " aliaswalletd [options] help " + _("List commands") + "\n" + + " aliaswalletd [options] help " + _("Get help for a command") + "\n"; strUsage += "\n" + HelpMessage(); @@ -178,7 +185,7 @@ bool AppInit(int argc, char* argv[]) // Command-line RPC for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "shadowcoin:")) + if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "spectrecoin:")) fCommandLine = true; if (fCommandLine) @@ -188,11 +195,11 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: invalid combination of -regtest and -testnet.\n"); return false; }; - + int ret = CommandLineRPC(argc, argv); exit(ret); }; - + #if !defined(WIN32) fDaemon = GetBoolArg("-daemon", false); if (fDaemon) @@ -204,32 +211,32 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); return false; }; - + if (pid > 0) // Parent process, pid is child process id { CreatePidFile(GetPidFile(), pid); return true; }; - + // Child process falls through to rest of initialization - - + + pid_t sid = setsid(); if (sid < 0) fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); }; #endif - + if (GetBoolArg("-cli", false)) printf("Starting...\n"); - + fRet = AppInit2(threadGroup); } catch (std::exception& e) { PrintException(&e, "AppInit()"); } catch (...) { - PrintException(NULL, "AppInit()"); + PrintException(nullptr, "AppInit()"); }; if (!fRet) @@ -250,16 +257,21 @@ bool AppInit(int argc, char* argv[]) extern void noui_connect(); int main(int argc, char* argv[]) { +#ifndef WIN32 + if (BlockSignals() != 0) + return 1; +#endif + bool fRet = false; fHaveGUI = false; - - // Connect shadowcoind signal handlers + + // Connect spectrecoind signal handlers noui_connect(); - + fRet = AppInit(argc, argv); - + if (fRet && fDaemon) return 0; - + return (fRet ? 0 : 1); }; diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000000..1157ac4a34 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,286 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +TEMPLATE = app +TARGET = Alias +CONFIG += c++1z + +DEFINES += DEBUGGER_CONNECTED +DEFINES += HAVE_BUILD_INFO +#DEFINES += TEST_TOR + +QT += testlib widgets quick quickwidgets webview webchannel websockets svg + +RC_FILE = src.rc + +CONFIG(release, debug|release) { + message( "release" ) + DESTDIR = $$PWD/bin +} +CONFIG(debug, debug|release) { + message( "debug" ) + DESTDIR = $$PWD/bin/debug +} + +macx { + message(Mac build) + include(osx.pri) +} win32 { + message(Win build) + include(win.pri) +} + +HEADERS += \ + $$PWD/json/json_spirit.h \ + $$PWD/json/json_spirit_error_position.h \ + $$PWD/json/json_spirit_reader.h \ + $$PWD/json/json_spirit_reader_template.h \ + $$PWD/json/json_spirit_stream_reader.h \ + $$PWD/json/json_spirit_utils.h \ + $$PWD/json/json_spirit_value.h \ + $$PWD/json/json_spirit_writer.h \ + $$PWD/json/json_spirit_writer_template.h \ + $$PWD/lz4/lz4.h \ + $$PWD/qt/test/uritests.h \ + $$PWD/qt/aboutdialog.h \ + $$PWD/qt/addresstablemodel.h \ + $$PWD/qt/askpassphrasedialog.h \ + $$PWD/qt/bitcoinaddressvalidator.h \ + $$PWD/qt/bitcoinamountfield.h \ + $$PWD/qt/bitcoinunits.h \ + $$PWD/qt/bridgetranslations.h \ + $$PWD/qt/clientmodel.h \ + $$PWD/qt/coincontroldialog.h \ + $$PWD/qt/coincontroltreewidget.h \ + $$PWD/qt/csvmodelwriter.h \ + $$PWD/qt/editaddressdialog.h \ + $$PWD/qt/guiconstants.h \ + $$PWD/qt/guiutil.h \ + $$PWD/qt/monitoreddatamapper.h \ + $$PWD/qt/notificator.h \ + $$PWD/qt/optionsmodel.h \ + $$PWD/qt/paymentserver.h \ + $$PWD/qt/peertablemodel.h \ + $$PWD/qt/qvalidatedlineedit.h \ + $$PWD/qt/qvaluecombobox.h \ + $$PWD/qt/rpcconsole.h \ + $$PWD/qt/scicon.h \ + $$PWD/qt/spectrebridge.h \ + $$PWD/qt/spectregui.h \ + $$PWD/qt/trafficgraphwidget.h \ + $$PWD/qt/transactiondesc.h \ + $$PWD/qt/transactionrecord.h \ + $$PWD/qt/transactiontablemodel.h \ + $$PWD/qt/walletmodel.h \ + $$PWD/qt/winshutdownmonitor.h \ + $$PWD/qt/setupwalletwizard.h \ + $$PWD/qt/websockettransport.h \ + $$PWD/qt/websocketclientwrapper.h \ + $$PWD/wordlists/chinese_simplified.h \ + $$PWD/wordlists/chinese_traditional.h \ + $$PWD/wordlists/english.h \ + $$PWD/wordlists/french.h \ + $$PWD/wordlists/japanese.h \ + $$PWD/wordlists/spanish.h \ + $$PWD/xxhash/xxhash.h \ + $$PWD/alert.h \ + $$PWD/allocators.h \ + $$PWD/anonymize.h \ + $$PWD/base58.h \ + $$PWD/bignum.h \ + $$PWD/bloom.h \ + $$PWD/chainparams.h \ + $$PWD/chainparamsseeds.h \ + $$PWD/checkpoints.h \ + $$PWD/clientversion.h \ + $$PWD/coincontrol.h \ + $$PWD/compat.h \ + $$PWD/core.h \ + $$PWD/crypter.h \ + $$PWD/currency.h \ + $$PWD/db.h \ + $$PWD/eckey.h \ + $$PWD/extkey.h \ + $$PWD/hash.h \ + $$PWD/init.h \ + $$PWD/kernel.h \ + $$PWD/key.h \ + $$PWD/keystore.h \ + $$PWD/main.h \ + $$PWD/miner.h \ + $$PWD/mruset.h \ + $$PWD/net.h \ + $$PWD/netbase.h \ + $$PWD/pbkdf2.h \ + $$PWD/protocol.h \ + $$PWD/ringsig.h \ + $$PWD/rpcclient.h \ + $$PWD/rpcprotocol.h \ + $$PWD/rpcserver.h \ + $$PWD/script.h \ + $$PWD/scrypt.h \ + $$PWD/serialize.h \ + $$PWD/smessage.h \ + $$PWD/state.h \ + $$PWD/stealth.h \ + $$PWD/strlcpy.h \ + $$PWD/sync.h \ + $$PWD/threadsafety.h \ + $$PWD/tinyformat.h \ + $$PWD/txdb-leveldb.h \ + $$PWD/txdb.h \ + $$PWD/txmempool.h \ + $$PWD/types.h \ + $$PWD/ui_interface.h \ + $$PWD/uint256.h \ + $$PWD/util.h \ + $$PWD/version.h \ + $$PWD/wallet.h \ + $$PWD/walletdb.h \ + $$PWD/addrman.h \ + $$PWD/shutdown.h + +SOURCES += \ + $$PWD/json/json_spirit_reader.cpp \ + $$PWD/json/json_spirit_value.cpp \ + $$PWD/json/json_spirit_writer.cpp \ +# $$PWD/qt/test/test_main.cpp \ + $$PWD/qt/test/uritests.cpp \ + $$PWD/qt/aboutdialog.cpp \ + $$PWD/qt/addresstablemodel.cpp \ + $$PWD/qt/askpassphrasedialog.cpp \ + $$PWD/qt/bitcoinaddressvalidator.cpp \ + $$PWD/qt/bitcoinamountfield.cpp \ + $$PWD/qt/bitcoinstrings.cpp \ + $$PWD/qt/bitcoinunits.cpp \ + $$PWD/qt/clientmodel.cpp \ + $$PWD/qt/coincontroldialog.cpp \ + $$PWD/qt/coincontroltreewidget.cpp \ + $$PWD/qt/csvmodelwriter.cpp \ + $$PWD/qt/editaddressdialog.cpp \ + $$PWD/qt/guiutil.cpp \ + $$PWD/qt/monitoreddatamapper.cpp \ + $$PWD/qt/notificator.cpp \ + $$PWD/qt/optionsmodel.cpp \ + $$PWD/qt/paymentserver.cpp \ + $$PWD/qt/peertablemodel.cpp \ + $$PWD/qt/qvalidatedlineedit.cpp \ + $$PWD/qt/qvaluecombobox.cpp \ + $$PWD/qt/rpcconsole.cpp \ + $$PWD/qt/scicon.cpp \ + $$PWD/qt/spectre.cpp \ + $$PWD/qt/spectrebridge.cpp \ + $$PWD/qt/spectregui.cpp \ + $$PWD/qt/trafficgraphwidget.cpp \ + $$PWD/qt/transactiondesc.cpp \ + $$PWD/qt/transactionrecord.cpp \ + $$PWD/qt/transactiontablemodel.cpp \ + $$PWD/qt/walletmodel.cpp \ + $$PWD/qt/winshutdownmonitor.cpp \ + $$PWD/qt/setupwalletwizard.cpp \ + $$PWD/qt/websockettransport.cpp \ + $$PWD/qt/websocketclientwrapper.cpp \ +# $$PWD/test/other/DoS_tests.cpp \ +# $$PWD/test/other/miner_tests.cpp \ +# $$PWD/test/other/transaction_tests.cpp \ +# $$PWD/test/accounting_tests.cpp \ +# $$PWD/test/allocator_tests.cpp \ +# $$PWD/test/base32_tests.cpp \ +# $$PWD/test/base58_tests.cpp \ +# $$PWD/test/base64_tests.cpp \ +# $$PWD/test/basic_tests.cpp \ +# $$PWD/test/bignum_tests.cpp \ +# $$PWD/test/bip32_tests.cpp \ +# $$PWD/test/Checkpoints_tests.cpp \ +# $$PWD/test/extkey_tests.cpp \ +# $$PWD/test/getarg_tests.cpp \ +# $$PWD/test/hash_tests.cpp \ +# $$PWD/test/hmac_tests.cpp \ +# $$PWD/test/key_tests.cpp \ +# $$PWD/test/mnemonic_tests.cpp \ +# $$PWD/test/mruset_tests.cpp \ +# $$PWD/test/multisig_tests.cpp \ +# $$PWD/test/netbase_tests.cpp \ +# $$PWD/test/ringsig_tests.cpp \ +# $$PWD/test/rpc_tests.cpp \ +# $$PWD/test/script_P2SH_tests.cpp \ +# $$PWD/test/script_tests.cpp \ +# $$PWD/test/sigopcount_tests.cpp \ +# $$PWD/test/stealth_tests.cpp \ +# $$PWD/test/test_shadow.cpp \ +# $$PWD/test/uint160_tests.cpp \ +# $$PWD/test/uint256_tests.cpp \ +# $$PWD/test/util_tests.cpp \ +# $$PWD/test/wallet_tests.cpp \ + $$PWD/alert.cpp \ + $$PWD/anonymize.cpp \ + $$PWD/bloom.cpp \ + $$PWD/chainparams.cpp \ + $$PWD/checkpoints.cpp \ + $$PWD/core.cpp \ + $$PWD/crypter.cpp \ + $$PWD/db.cpp \ + $$PWD/eckey.cpp \ + $$PWD/extkey.cpp \ + $$PWD/hash.cpp \ + $$PWD/init.cpp \ + $$PWD/kernel.cpp \ + $$PWD/key.cpp \ + $$PWD/keystore.cpp \ + $$PWD/main.cpp \ + $$PWD/miner.cpp \ + $$PWD/net.cpp \ + $$PWD/netbase.cpp \ + $$PWD/noui.cpp \ + $$PWD/pbkdf2.cpp \ + $$PWD/protocol.cpp \ + $$PWD/ringsig.cpp \ + $$PWD/rpcblockchain.cpp \ + $$PWD/rpcclient.cpp \ + $$PWD/rpcdump.cpp \ + $$PWD/rpcextkey.cpp \ + $$PWD/rpcmining.cpp \ + $$PWD/rpcmnemonic.cpp \ + $$PWD/rpcnet.cpp \ + $$PWD/rpcprotocol.cpp \ + $$PWD/rpcrawtransaction.cpp \ + $$PWD/rpcserver.cpp \ + $$PWD/rpcwallet.cpp \ + $$PWD/script.cpp \ + $$PWD/scrypt.cpp \ + $$PWD/smessage.cpp \ +# $$PWD/spectrecoind.cpp \ + $$PWD/state.cpp \ + $$PWD/stealth.cpp \ + $$PWD/sync.cpp \ + $$PWD/txdb-leveldb.cpp \ + $$PWD/txmempool.cpp \ + $$PWD/util.cpp \ + $$PWD/version.cpp \ + $$PWD/wallet.cpp \ + $$PWD/walletdb.cpp \ + $$PWD/lz4/lz4.c \ + $$PWD/xxhash/xxhash.c \ + $$PWD/addrman.cpp \ + $$PWD/shutdown.cpp + + +#levelDB additional headers +#INCLUDEPATH += $$PWD/../leveldb/helpers +#find . -type d +INCLUDEPATH += $$PWD $$PWD/obj $$PWD/test $$PWD/test/other $$PWD/test/data $$PWD/wordlists $$PWD/qt $$PWD/qt/res $$PWD/qt/res/css $$PWD/qt/res/css/fonts $$PWD/qt/res/images $$PWD/qt/res/icons $$PWD/qt/res/assets $$PWD/qt/res/assets/css $$PWD/qt/res/assets/plugins $$PWD/qt/res/assets/plugins/md5 $$PWD/qt/res/assets/plugins/identicon $$PWD/qt/res/assets/plugins/bootstrapv3 $$PWD/qt/res/assets/plugins/bootstrapv3/css $$PWD/qt/res/assets/plugins/bootstrapv3/js $$PWD/qt/res/assets/plugins/bootstrapv3/fonts $$PWD/qt/res/assets/plugins/framework $$PWD/qt/res/assets/plugins/markdown $$PWD/qt/res/assets/plugins/shajs $$PWD/qt/res/assets/plugins/pnglib $$PWD/qt/res/assets/plugins/iscroll $$PWD/qt/res/assets/plugins/jquery $$PWD/qt/res/assets/plugins/classie $$PWD/qt/res/assets/plugins/pace $$PWD/qt/res/assets/plugins/contextMenu $$PWD/qt/res/assets/plugins/jquery-scrollbar $$PWD/qt/res/assets/plugins/jdenticon $$PWD/qt/res/assets/plugins/qrcode $$PWD/qt/res/assets/plugins/emojione $$PWD/qt/res/assets/plugins/emojione/assets $$PWD/qt/res/assets/plugins/emojione/assets/svg $$PWD/qt/res/assets/plugins/emojione/assets/css $$PWD/qt/res/assets/plugins/jquery-transit $$PWD/qt/res/assets/plugins/footable $$PWD/qt/res/assets/plugins/jquery-ui $$PWD/qt/res/assets/plugins/jquery-ui/images $$PWD/qt/res/assets/js $$PWD/qt/res/assets/js/pages $$PWD/qt/res/assets/img $$PWD/qt/res/assets/img/progress $$PWD/qt/res/assets/icons $$PWD/qt/res/assets/fonts $$PWD/qt/res/assets/fonts/Framework-icon $$PWD/qt/res/assets/fonts/FontAwesome $$PWD/qt/res/assets/fonts/Montserrat $$PWD/qt/res/assets/fonts/Footable $$PWD/qt/res/src $$PWD/qt/locale $$PWD/qt/forms $$PWD/qt/test $$PWD/lz4 $$PWD/json $$PWD/xxhash $$PWD/obj-test + + +FORMS += \ + $$PWD/qt/forms/aboutdialog.ui \ + $$PWD/qt/forms/askpassphrasedialog.ui \ + $$PWD/qt/forms/coincontroldialog.ui \ + $$PWD/qt/forms/editaddressdialog.ui \ + $$PWD/qt/forms/rpcconsole.ui \ + $$PWD/qt/forms/transactiondescdialog.ui + +RESOURCES += \ + ../spectre.qrc diff --git a/src/src.rc b/src/src.rc new file mode 100644 index 0000000000..5bb21955f3 --- /dev/null +++ b/src/src.rc @@ -0,0 +1,88 @@ +// Microsoft Visual C++ generated resource script. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-License-Identifier: MIT +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "qt/res/icons/alias-app.ico" + + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,0 + PRODUCTVERSION 0,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "\0" + VALUE "FileVersion", "0.0.0.0\0" + VALUE "LegalCopyright", "\0" + VALUE "OriginalFilename", "Aliaswallet.exe\0" + VALUE "ProductName", "Alias\0" + VALUE "ProductVersion", "0.0.0.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END + END +/* End of Version info */ + diff --git a/src/state.cpp b/src/state.cpp index 47e289fa07..fe1582ea18 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -1,33 +1,45 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "state.h" +namespace alias { + +static NodeSettings g_node_settings; +static DebugFlags g_debug_flags; +static RuntimeState g_runtime_state; + +NodeSettings& GetNodeSettings() { return g_node_settings; } +DebugFlags& GetDebugFlags() { return g_debug_flags; } +RuntimeState& GetRuntimeState() { return g_runtime_state; } + +} // namespace alias + +// Legacy global variables - these wrap the new structures for backward compatibility int nNodeMode = NT_FULL; int nNodeState = NS_STARTUP; int nMaxThinPeers = 8; int nBloomFilterElements = 1536; -int nMinStakeInterval = 0; // in seconds, min time between successful stakes -int nThinIndexWindow = 4096; // no. of block headers to keep in memory - -// -- services provided by local node, initialise to all on -uint64_t nLocalServices = 0 | NODE_NETWORK | THIN_SUPPORT | THIN_STEALTH | SMSG_RELAY; -uint32_t nLocalRequirements = 0 | NODE_NETWORK; +int nMinStakeInterval = 0; +int nStakingDonation = 0; +int nThinIndexWindow = 4096; +uint64_t nLocalServices = NODE_NETWORK | THIN_SUPPORT | THIN_STEALTH | SMSG_RELAY; +uint32_t nLocalRequirements = NODE_NETWORK; bool fTestNet = false; bool fDebug = false; bool fDebugNet = false; -bool fDebugSmsg = false; bool fDebugChain = false; bool fDebugRingSig = false; bool fDebugPoS = false; -bool fNoSmsg = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; -//bool fShutdown = false; bool fDaemon = false; bool fServer = false; bool fCommandLine = false; @@ -35,28 +47,35 @@ std::string strMiscWarning; bool fNoListen = false; bool fLogTimestamps = false; bool fReopenDebugLog = false; -bool fThinFullIndex = false; // when in thin mode don't keep all headers in memory +bool fThinFullIndex = false; bool fReindexing = false; bool fHaveGUI = false; -volatile bool fIsStaking = false; // looks at stake weight also +volatile bool fIsStaking = false; +volatile bool fIsStakingEnabled = false; bool fMakeExtKeyInitials = false; -volatile bool fPassGuiAddresses = false; // force the gui to process new addresses, gui doesn't update addresses when syncing +volatile bool fPassGuiAddresses = false; + +bool fConfChange = false; +bool fEnforceCanonical = false; +bool fUseFastIndex = false; +unsigned int nNodeLifespan = 0; +unsigned int nDerivationMethodIndex = 0; +unsigned int nMinerSleep = 0; +unsigned int nBlockMaxSize = 0; +unsigned int nBlockPrioritySize = 0; +unsigned int nBlockMinSize = 0; -bool fConfChange; -bool fEnforceCanonical; -bool fUseFastIndex; -unsigned int nNodeLifespan; -unsigned int nDerivationMethodIndex; -unsigned int nMinerSleep; -unsigned int nBlockMaxSize; -unsigned int nBlockPrioritySize; -unsigned int nBlockMinSize; -int64_t nMinTxFee = MIN_TX_FEE; +int64_t nMinTxFee = 10000; +int64_t nMinRelayTxFee = nMinTxFee; +int64_t nStakeReward = 2 * alias::COIN; +int64_t nAnonStakeReward = 3 * alias::COIN; unsigned int nStakeSplitAge = 1 * 24 * 60 * 60; -int64_t nStakeCombineThreshold = 1000 * COIN; +int64_t nStakeCombineThreshold = 1000 * alias::COIN; int64_t nStakeSplitThreshold = 2 * nStakeCombineThreshold; +int64_t nMaxAnonOutput = 1000 * alias::COIN; +int64_t nMaxAnonStakeOutput = nMaxAnonOutput; uint32_t nExtKeyLookAhead = 10; diff --git a/src/state.h b/src/state.h index ab9677f761..c572fbf9e6 100644 --- a/src/state.h +++ b/src/state.h @@ -1,45 +1,43 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. - -#ifndef COIN_STATE_H -#define COIN_STATE_H - -#include +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_STATE_H +#define ALIAS_STATE_H + +#include +#include #include +#include + #include "sync.h" -enum eNodeType -{ - NT_FULL = 1, - NT_THIN, - NT_UNKNOWN // end marker -}; +namespace alias { -enum eNodeState -{ - NS_STARTUP = 1, - NS_GET_HEADERS, - NS_GET_FILTERED_BLOCKS, - NS_READY, - - NS_UNKNOWN // end marker +enum class NodeType : int { + Full = 1, + Thin, + Unknown }; -enum eBlockFlags -{ - BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block - BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier - BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier +enum class NodeState : int { + Startup = 1, + GetHeaders, + GetFilteredBlocks, + Ready, + Unknown }; +enum BlockFlags : uint32_t { + BLOCK_PROOF_OF_STAKE = (1 << 0), + BLOCK_STAKE_ENTROPY = (1 << 1), + BLOCK_STAKE_MODIFIER = (1 << 2), +}; -/* nServices flags - top 32 bits of CNode::nServices are used to mark services required -*/ - -enum -{ +enum ServiceFlags : uint64_t { NODE_NETWORK = (1 << 0), THIN_SUPPORT = (1 << 1), THIN_STAKE = (1 << 2), // deprecated @@ -47,51 +45,154 @@ enum SMSG_RELAY = (1 << 4), }; -const int64_t GENESIS_BLOCK_TIME = 1405769613; +constexpr int64_t GENESIS_BLOCK_TIME = 1479594600; +constexpr int64_t COIN = 100000000; +constexpr int64_t CENT = 1000000; +constexpr int64_t COIN_YEAR_REWARD = 5 * CENT; +constexpr int64_t MBLK_RECEIVE_TIMEOUT = 60; +constexpr int UNSPENT_ANON_BALANCE_MIN = 100; +constexpr int UNSPENT_ANON_BALANCE_MAX = 200; +constexpr int UNSPENT_ANON_SELECT_MIN = 20; +constexpr int TRY_STAKE_MEMPOOL_TIMEOUT = 5 * 60; +constexpr int TRY_STAKE_MEMPOOL_MAX_ASK = 16; + +struct NodeSettings { + int nMaxThinPeers{8}; + int nBloomFilterElements{1536}; + int nMinStakeInterval{0}; + int nStakingDonation{0}; + int nThinIndexWindow{4096}; + + uint64_t nLocalServices{NODE_NETWORK | THIN_SUPPORT | THIN_STEALTH | SMSG_RELAY}; + uint32_t nLocalRequirements{NODE_NETWORK}; + + unsigned int nNodeLifespan{0}; + unsigned int nDerivationMethodIndex{0}; + unsigned int nMinerSleep{0}; + unsigned int nBlockMaxSize{0}; + unsigned int nBlockPrioritySize{0}; + unsigned int nBlockMinSize{0}; + + int64_t nMinTxFee{10000}; + int64_t nMinRelayTxFee{10000}; + int64_t nStakeReward{2 * COIN}; + int64_t nAnonStakeReward{3 * COIN}; + + unsigned int nStakeSplitAge{24 * 60 * 60}; + int64_t nStakeCombineThreshold{1000 * COIN}; + int64_t nStakeSplitThreshold{2000 * COIN}; + int64_t nMaxAnonOutput{1000 * COIN}; + int64_t nMaxAnonStakeOutput{1000 * COIN}; + + uint32_t nExtKeyLookAhead{10}; +}; + +struct DebugFlags { + std::atomic fDebug{false}; + std::atomic fDebugNet{false}; + std::atomic fDebugChain{false}; + std::atomic fDebugRingSig{false}; + std::atomic fDebugPoS{false}; + std::atomic fPrintToConsole{false}; + std::atomic fPrintToDebugLog{true}; + std::atomic fLogTimestamps{false}; + std::atomic fReopenDebugLog{false}; +}; + +struct RuntimeState { + std::atomic nNodeMode{static_cast(NodeType::Full)}; + std::atomic nNodeState{static_cast(NodeState::Startup)}; + std::atomic fTestNet{false}; + std::atomic fDaemon{false}; + std::atomic fServer{false}; + std::atomic fCommandLine{false}; + std::atomic fNoListen{false}; + std::atomic fThinFullIndex{false}; + std::atomic fReindexing{false}; + std::atomic fHaveGUI{false}; + std::atomic fIsStaking{false}; + std::atomic fIsStakingEnabled{false}; + std::atomic fMakeExtKeyInitials{false}; + std::atomic fPassGuiAddresses{false}; + std::atomic fConfChange{false}; + std::atomic fEnforceCanonical{false}; + std::atomic nTimeLastMblkRecv{0}; + std::string strMiscWarning; +}; + +NodeSettings& GetNodeSettings(); +DebugFlags& GetDebugFlags(); +RuntimeState& GetRuntimeState(); + +inline const char* GetNodeStateName(NodeState state) { + switch (state) { + case NodeState::Startup: return "Startup"; + case NodeState::GetHeaders: return "GetHeaders"; + case NodeState::GetFilteredBlocks: return "GetFilteredBlocks"; + case NodeState::Ready: return "Ready"; + default: return "Unknown"; + } +} + +} // namespace alias + +// Legacy compatibility - gradually migrate away from these +enum eNodeType { + NT_FULL = static_cast(alias::NodeType::Full), + NT_THIN = static_cast(alias::NodeType::Thin), + NT_UNKNOWN = static_cast(alias::NodeType::Unknown) +}; -static const int64_t COIN = 100000000; -static const int64_t CENT = 1000000; +enum eNodeState { + NS_STARTUP = static_cast(alias::NodeState::Startup), + NS_GET_HEADERS = static_cast(alias::NodeState::GetHeaders), + NS_GET_FILTERED_BLOCKS = static_cast(alias::NodeState::GetFilteredBlocks), + NS_READY = static_cast(alias::NodeState::Ready), + NS_UNKNOWN = static_cast(alias::NodeState::Unknown) +}; + +enum eBlockFlags { + BLOCK_PROOF_OF_STAKE = alias::BLOCK_PROOF_OF_STAKE, + BLOCK_STAKE_ENTROPY = alias::BLOCK_STAKE_ENTROPY, + BLOCK_STAKE_MODIFIER = alias::BLOCK_STAKE_MODIFIER, +}; -/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ -static const int64_t MIN_TX_FEE = 10000; -static const int64_t MIN_TX_FEE_ANON = 1000000; -/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */ -static const int64_t MIN_RELAY_TX_FEE = MIN_TX_FEE; -static const int64_t COIN_YEAR_REWARD = 2 * CENT; // 2% per year +enum { + NODE_NETWORK = alias::NODE_NETWORK, + THIN_SUPPORT = alias::THIN_SUPPORT, + THIN_STAKE = alias::THIN_STAKE, + THIN_STEALTH = alias::THIN_STEALTH, + SMSG_RELAY = alias::SMSG_RELAY, +}; -static const int64_t MBLK_RECEIVE_TIMEOUT = 60; // seconds +constexpr int64_t GENESIS_BLOCK_TIME = alias::GENESIS_BLOCK_TIME; +static const int64_t COIN = alias::COIN; +static const int64_t CENT = alias::CENT; +static const int64_t COIN_YEAR_REWARD = alias::COIN_YEAR_REWARD; +static const int64_t MBLK_RECEIVE_TIMEOUT = alias::MBLK_RECEIVE_TIMEOUT; +static const int UNSPENT_ANON_BALANCE_MIN = alias::UNSPENT_ANON_BALANCE_MIN; +static const int UNSPENT_ANON_BALANCE_MAX = alias::UNSPENT_ANON_BALANCE_MAX; +static const int UNSPENT_ANON_SELECT_MIN = alias::UNSPENT_ANON_SELECT_MIN; +static const int nTryStakeMempoolTimeout = alias::TRY_STAKE_MEMPOOL_TIMEOUT; +static const int nTryStakeMempoolMaxAsk = alias::TRY_STAKE_MEMPOOL_MAX_ASK; extern int nNodeMode; extern int nNodeState; - extern int nMaxThinPeers; extern int nBloomFilterElements; - - extern int nMinStakeInterval; - +extern int nStakingDonation; extern int nThinIndexWindow; - -static const int nTryStakeMempoolTimeout = 5 * 60; // seconds -static const int nTryStakeMempoolMaxAsk = 16; - extern uint64_t nLocalServices; extern uint32_t nLocalRequirements; - - - - extern bool fTestNet; extern bool fDebug; extern bool fDebugNet; -extern bool fDebugSmsg; extern bool fDebugChain; extern bool fDebugRingSig; extern bool fDebugPoS; -extern bool fNoSmsg; extern bool fPrintToConsole; extern bool fPrintToDebugLog; -//extern bool fShutdown; extern bool fDaemon; extern bool fServer; extern bool fCommandLine; @@ -103,9 +204,9 @@ extern bool fThinFullIndex; extern bool fReindexing; extern bool fHaveGUI; extern volatile bool fIsStaking; +extern volatile bool fIsStakingEnabled; extern bool fMakeExtKeyInitials; extern volatile bool fPassGuiAddresses; - extern bool fConfChange; extern bool fEnforceCanonical; extern unsigned int nNodeLifespan; @@ -115,15 +216,20 @@ extern unsigned int nBlockMaxSize; extern unsigned int nBlockPrioritySize; extern unsigned int nBlockMinSize; extern int64_t nMinTxFee; - +extern int64_t nMinRelayTxFee; +extern int64_t nStakeReward; +extern int64_t nAnonStakeReward; extern unsigned int nStakeSplitAge; -extern int nStakeMinConfirmations; extern int64_t nStakeSplitThreshold; extern int64_t nStakeCombineThreshold; - +extern int64_t nMaxAnonOutput; +extern int64_t nMaxAnonStakeOutput; extern uint32_t nExtKeyLookAhead; extern int64_t nTimeLastMblkRecv; +inline const char* GetNodeStateName(int state) { + return alias::GetNodeStateName(static_cast(state)); +} -#endif /* COIN_STATE_H */ +#endif // ALIAS_STATE_H diff --git a/src/stealth.cpp b/src/stealth.cpp index eddb5d2c76..7a5dffe4e1 100644 --- a/src/stealth.cpp +++ b/src/stealth.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include "stealth.h" #include "base58.h" @@ -15,50 +18,56 @@ bool CStealthAddress::SetEncoded(const std::string& encodedAddress) { + if (encodedAddress.length() < 76) + { + //LogPrintf("SetEncoded address to short, quick fail.\n"); + return false; + }; + data_chunk raw; - + if (!DecodeBase58(encodedAddress, raw)) { if (fDebug) LogPrintf("CStealthAddress::SetEncoded DecodeBase58 falied.\n"); return false; }; - + if (!VerifyChecksum(raw)) { if (fDebug) LogPrintf("CStealthAddress::SetEncoded verify_checksum falied.\n"); return false; }; - + if (raw.size() < 1 + 1 + 33 + 1 + 33 + 1 + 1 + 4) { if (fDebug) LogPrintf("CStealthAddress::SetEncoded() too few bytes provided.\n"); return false; }; - - + + uint8_t* p = &raw[0]; uint8_t version = *p++; - + if (version != Params().Base58Prefix(CChainParams::STEALTH_ADDRESS)[0]) { LogPrintf("CStealthAddress::SetEncoded version mismatch 0x%x != 0x%x.\n", version, Params().Base58Prefix(CChainParams::STEALTH_ADDRESS)[0]); return false; }; - + options = *p++; - + scan_pubkey.resize(33); memcpy(&scan_pubkey[0], p, 33); p += 33; //uint8_t spend_pubkeys = *p++; p++; - + spend_pubkey.resize(33); memcpy(&spend_pubkey[0], p, 33); - + return true; }; @@ -66,20 +75,20 @@ std::string CStealthAddress::Encoded() const { // https://wiki.unsystem.net/index.php/DarkWallet/Stealth#Address_format // [version] [options] [scan_key] [N] ... [Nsigs] [prefix_length] ... - + data_chunk raw; raw = Params().Base58Prefix(CChainParams::STEALTH_ADDRESS); - + raw.push_back(options); - + raw.insert(raw.end(), scan_pubkey.begin(), scan_pubkey.end()); raw.push_back(1); // number of spend pubkeys raw.insert(raw.end(), spend_pubkey.begin(), spend_pubkey.end()); raw.push_back(0); // number of signatures raw.push_back(0); // ? - + AppendChecksum(raw); - + return EncodeBase58(raw); }; @@ -94,9 +103,9 @@ int CStealthAddress::SetScanPubKey(CPubKey pk) int GenerateRandomSecret(ec_secret& out) { RandAddSeedPerfmon(); - + uint256 test; - + int i; // -- check max, try max 32 times for (i = 0; i < 32; ++i) @@ -109,10 +118,10 @@ int GenerateRandomSecret(ec_secret& out) break; }; }; - + if (i > 31) return errorN(1, "%s: Failed to generate a valid key.", __func__); - + return 0; }; @@ -120,9 +129,9 @@ int SecretToPublicKey(const ec_secret& secret, ec_point& out) { // -- public key = private * G int rv = 0; - + EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); - + if (!ecgrp) return errorN(1, "%s: EC_GROUP_new_by_curve_name failed.", __func__); @@ -132,13 +141,13 @@ int SecretToPublicKey(const ec_secret& secret, ec_point& out) EC_GROUP_free(ecgrp); return errorN(1, "%s: BN_bin2bn failed.", __func__); }; - + EC_POINT* pub = EC_POINT_new(ecgrp); - - - EC_POINT_mul(ecgrp, pub, bnIn, NULL, NULL, NULL); - - BIGNUM* bnOut = EC_POINT_point2bn(ecgrp, pub, POINT_CONVERSION_COMPRESSED, BN_new(), NULL); + + + EC_POINT_mul(ecgrp, pub, bnIn, nullptr, nullptr, nullptr); + + BIGNUM* bnOut = EC_POINT_point2bn(ecgrp, pub, POINT_CONVERSION_COMPRESSED, BN_new(), nullptr); if (!bnOut) { LogPrintf("%s: point2bn failed.\n", __func__); @@ -152,14 +161,14 @@ int SecretToPublicKey(const ec_secret& secret, ec_point& out) LogPrintf("%s: bnOut incorrect length.\n", __func__); rv = 1; }; - + BN_free(bnOut); }; - + EC_POINT_free(pub); BN_free(bnIn); EC_GROUP_free(ecgrp); - + return rv; }; @@ -167,14 +176,14 @@ int SecretToPublicKey(const ec_secret& secret, ec_point& out) int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, ec_secret& sharedSOut, ec_point& pkOut) { /* - + send: secret = ephem_secret, pubkey = scan_pubkey - + receive: secret = scan_secret, pubkey = ephem_pubkey c = H(dP) - + Q = public scan key (EC point, 33 bytes) d = private scan key (integer, 32 bytes) R = public spend key @@ -182,86 +191,86 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, Q = dG R = fG - + Sender (has Q and R, not d or f): - + P = eG c = H(eQ) = H(dP) R' = R + cG - - + + Recipient gets R' and P - + test 0 and infinity? */ - + int rv = 0; std::vector vchOutQ; - - BN_CTX* bnCtx = NULL; - BIGNUM* bnEphem = NULL; - BIGNUM* bnQ = NULL; - EC_POINT* Q = NULL; - BIGNUM* bnOutQ = NULL; - BIGNUM* bnc = NULL; - EC_POINT* C = NULL; - BIGNUM* bnR = NULL; - EC_POINT* R = NULL; - EC_POINT* Rout = NULL; - BIGNUM* bnOutR = NULL; - + + BN_CTX* bnCtx = nullptr; + BIGNUM* bnEphem = nullptr; + BIGNUM* bnQ = nullptr; + EC_POINT* Q = nullptr; + BIGNUM* bnOutQ = nullptr; + BIGNUM* bnc = nullptr; + EC_POINT* C = nullptr; + BIGNUM* bnR = nullptr; + EC_POINT* R = nullptr; + EC_POINT* Rout = nullptr; + BIGNUM* bnOutR = nullptr; + EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); - + if (!ecgrp) return errorN(1, "%s: EC_GROUP_new_by_curve_name failed.", __func__); - + if (!(bnCtx = BN_CTX_new())) { LogPrintf("%s: BN_CTX_new failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnEphem = BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: bnEphem BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnQ = BN_bin2bn(&pubkey[0], pubkey.size(), BN_new()))) { LogPrintf("%s: bnEphem bnQ failed.\n", __func__); rv = 1; goto End; }; - - if (!(Q = EC_POINT_bn2point(ecgrp, bnQ, NULL, bnCtx))) + + if (!(Q = EC_POINT_bn2point(ecgrp, bnQ, nullptr, bnCtx))) { LogPrintf("%s: Q EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - + // -- eQ // EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); - // EC_POINT_mul calculates the value generator * n + q * m and stores the result in r. The value n may be NULL in which case the result is just q * m. - if (!EC_POINT_mul(ecgrp, Q, NULL, Q, bnEphem, bnCtx)) + // EC_POINT_mul calculates the value generator * n + q * m and stores the result in r. The value n may be NULL in which case the result is just q * m. + if (!EC_POINT_mul(ecgrp, Q, nullptr, Q, bnEphem, bnCtx)) { LogPrintf("%s: eQ EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOutQ = EC_POINT_point2bn(ecgrp, Q, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { LogPrintf("%s: Q EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - + + vchOutQ.resize(EC_COMPRESSED_SIZE); if (BN_num_bytes(bnOutQ) != (int) EC_COMPRESSED_SIZE || BN_bn2bin(bnOutQ, &vchOutQ[0]) != (int) EC_COMPRESSED_SIZE) @@ -270,16 +279,16 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, rv = 1; goto End; }; - + SHA256(&vchOutQ[0], vchOutQ.size(), &sharedSOut.e[0]); - + if (!(bnc = BN_bin2bn(&sharedSOut.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + // -- cG if (!(C = EC_POINT_new(ecgrp))) { @@ -287,58 +296,58 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, rv = 1; goto End; }; - - if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) + + if (!EC_POINT_mul(ecgrp, C, bnc, nullptr, nullptr, bnCtx)) { LogPrintf("%s: C EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnR = BN_bin2bn(&pkSpend[0], pkSpend.size(), BN_new()))) { LogPrintf("%s: bnR BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - - - if (!(R = EC_POINT_bn2point(ecgrp, bnR, NULL, bnCtx))) + + + if (!(R = EC_POINT_bn2point(ecgrp, bnR, nullptr, bnCtx))) { LogPrintf("%s: R EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) + + if (!EC_POINT_mul(ecgrp, C, bnc, nullptr, nullptr, bnCtx)) { LogPrintf("%s: C EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(Rout = EC_POINT_new(ecgrp))) { LogPrintf("%s: Rout EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; - + if (!EC_POINT_add(ecgrp, Rout, R, C, bnCtx)) { LogPrintf("%s: Rout EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOutR = EC_POINT_point2bn(ecgrp, Rout, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { LogPrintf("%s: Rout EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - + + pkOut.resize(EC_COMPRESSED_SIZE); if (BN_num_bytes(bnOutR) != (int) EC_COMPRESSED_SIZE || BN_bn2bin(bnOutR, &pkOut[0]) != (int) EC_COMPRESSED_SIZE) @@ -347,7 +356,7 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, rv = 1; goto End; }; - + End: if (bnOutR) BN_free(bnOutR); if (Rout) EC_POINT_free(Rout); @@ -361,7 +370,7 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, if (bnEphem) BN_free(bnEphem); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); - + return rv; }; @@ -369,74 +378,74 @@ int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut) { /* - + c = H(dP) R' = R + cG [without decrypting wallet] = (f + c)G [after decryption of wallet] Remember: mod curve.order, pad with 0x00s where necessary? */ - + int rv = 0; std::vector vchOutP; - - BN_CTX* bnCtx = NULL; - BIGNUM* bnScanSecret = NULL; - BIGNUM* bnP = NULL; - EC_POINT* P = NULL; - BIGNUM* bnOutP = NULL; - BIGNUM* bnc = NULL; - BIGNUM* bnOrder = NULL; - BIGNUM* bnSpend = NULL; - + + BN_CTX* bnCtx = nullptr; + BIGNUM* bnScanSecret = nullptr; + BIGNUM* bnP = nullptr; + EC_POINT* P = nullptr; + BIGNUM* bnOutP = nullptr; + BIGNUM* bnc = nullptr; + BIGNUM* bnOrder = nullptr; + BIGNUM* bnSpend = nullptr; + EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); - + if (!ecgrp) return errorN(1, "%s: EC_GROUP_new_by_curve_name failed.", __func__); - + if (!(bnCtx = BN_CTX_new())) { LogPrintf("%s: BN_CTX_new failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnScanSecret = BN_bin2bn(&scanSecret.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: bnScanSecret BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnP = BN_bin2bn(&ephemPubkey[0], ephemPubkey.size(), BN_new()))) { LogPrintf("%s: bnP BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - - if (!(P = EC_POINT_bn2point(ecgrp, bnP, NULL, bnCtx))) + + if (!(P = EC_POINT_bn2point(ecgrp, bnP, nullptr, bnCtx))) { LogPrintf("%s: P EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - + // -- dP - if (!EC_POINT_mul(ecgrp, P, NULL, P, bnScanSecret, bnCtx)) + if (!EC_POINT_mul(ecgrp, P, nullptr, P, bnScanSecret, bnCtx)) { LogPrintf("%s: dP EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOutP = EC_POINT_point2bn(ecgrp, P, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { LogPrintf("%s: P EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - + + vchOutP.resize(EC_COMPRESSED_SIZE); if (BN_num_bytes(bnOutP) != (int) EC_COMPRESSED_SIZE || BN_bn2bin(bnOutP, &vchOutP[0]) != (int) EC_COMPRESSED_SIZE) @@ -445,18 +454,18 @@ int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& rv = 1; goto End; }; - + uint8_t hash1[32]; SHA256(&vchOutP[0], vchOutP.size(), (uint8_t*)hash1); - - + + if (!(bnc = BN_bin2bn(&hash1[0], 32, BN_new()))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOrder = BN_new()) || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx)) { @@ -464,14 +473,14 @@ int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& rv = 1; goto End; }; - + if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: bnSpend BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + //if (!BN_add(r, a, b)) return 0; //return BN_nnmod(r, r, m, ctx); if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx)) @@ -480,14 +489,14 @@ int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& rv = 1; goto End; }; - + if (BN_is_zero(bnSpend)) // possible? { LogPrintf("%s: bnSpend is zero.\n", __func__); rv = 1; goto End; }; - + int nBytes; memset(&secretOut.e[0], 0, EC_SECRET_SIZE); if ((nBytes = BN_num_bytes(bnSpend)) > (int)EC_SECRET_SIZE @@ -497,7 +506,7 @@ int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& rv = 1; goto End; }; - + End: if (bnSpend) BN_free(bnSpend); if (bnOrder) BN_free(bnOrder); @@ -508,7 +517,7 @@ int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& if (bnScanSecret) BN_free(bnScanSecret); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); - + return rv; }; @@ -517,31 +526,31 @@ int StealthSharedToSecretSpend(const ec_secret& sharedS, const ec_secret& spendS { int rv = 0; std::vector vchOutP; - - BN_CTX* bnCtx = NULL; - BIGNUM* bnc = NULL; - BIGNUM* bnOrder = NULL; - BIGNUM* bnSpend = NULL; - + + BN_CTX* bnCtx = nullptr; + BIGNUM* bnc = nullptr; + BIGNUM* bnOrder = nullptr; + BIGNUM* bnSpend = nullptr; + EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); - + if (!ecgrp) return errorN(1, "%s: EC_GROUP_new_by_curve_name failed.", __func__); - + if (!(bnCtx = BN_CTX_new())) { LogPrintf("%s: BN_CTX_new failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnc = BN_bin2bn(&sharedS.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOrder = BN_new()) || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx)) { @@ -549,14 +558,14 @@ int StealthSharedToSecretSpend(const ec_secret& sharedS, const ec_secret& spendS rv = 1; goto End; }; - + if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: bnSpend BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + //if (!BN_add(r, a, b)) return 0; //return BN_nnmod(r, r, m, ctx); if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx)) @@ -565,14 +574,14 @@ int StealthSharedToSecretSpend(const ec_secret& sharedS, const ec_secret& spendS rv = 1; goto End; }; - + if (BN_is_zero(bnSpend)) // possible? { LogPrintf("%s: bnSpend is zero.\n", __func__); rv = 1; goto End; }; - + int nBytes; memset(&secretOut.e[0], 0, EC_SECRET_SIZE); if ((nBytes = BN_num_bytes(bnSpend)) > (int)EC_SECRET_SIZE @@ -582,14 +591,14 @@ int StealthSharedToSecretSpend(const ec_secret& sharedS, const ec_secret& spendS rv = 1; goto End; }; - + End: if (bnSpend) BN_free(bnSpend); if (bnOrder) BN_free(bnOrder); if (bnc) BN_free(bnc); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); - + return rv; }; @@ -597,34 +606,34 @@ int StealthSharedToPublicKey(const ec_point& pkSpend, const ec_secret &sharedS, { int rv = 0; std::vector vchOutQ; - - BN_CTX *bnCtx = NULL; - BIGNUM *bnc = NULL; - EC_POINT *C = NULL; - BIGNUM *bnR = NULL; - EC_POINT *R = NULL; - EC_POINT *Rout = NULL; - BIGNUM *bnOutR = NULL; - + + BN_CTX *bnCtx = nullptr; + BIGNUM *bnc = nullptr; + EC_POINT *C = nullptr; + BIGNUM *bnR = nullptr; + EC_POINT *R = nullptr; + EC_POINT *Rout = nullptr; + BIGNUM *bnOutR = nullptr; + EC_GROUP *ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1); - + if (!ecgrp) return errorN(1, "%s: EC_GROUP_new_by_curve_name failed.", __func__); - + if (!(bnCtx = BN_CTX_new())) { LogPrintf("%s: BN_CTX_new failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnc = BN_bin2bn(&sharedS.e[0], EC_SECRET_SIZE, BN_new()))) { LogPrintf("%s: BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - + // -- cG if (!(C = EC_POINT_new(ecgrp))) { @@ -632,58 +641,58 @@ int StealthSharedToPublicKey(const ec_point& pkSpend, const ec_secret &sharedS, rv = 1; goto End; }; - - if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) + + if (!EC_POINT_mul(ecgrp, C, bnc, nullptr, nullptr, bnCtx)) { LogPrintf("%s: C EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnR = BN_bin2bn(&pkSpend[0], pkSpend.size(), BN_new()))) { LogPrintf("%s: bnR BN_bin2bn failed.\n", __func__); rv = 1; goto End; }; - - - if (!(R = EC_POINT_bn2point(ecgrp, bnR, NULL, bnCtx))) + + + if (!(R = EC_POINT_bn2point(ecgrp, bnR, nullptr, bnCtx))) { LogPrintf("%s: R EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx)) + + if (!EC_POINT_mul(ecgrp, C, bnc, nullptr, nullptr, bnCtx)) { LogPrintf("%s: C EC_POINT_mul failed.\n", __func__); rv = 1; goto End; }; - + if (!(Rout = EC_POINT_new(ecgrp))) { LogPrintf("%s: Rout EC_POINT_new failed.\n", __func__); rv = 1; goto End; }; - + if (!EC_POINT_add(ecgrp, Rout, R, C, bnCtx)) { LogPrintf("%s: Rout EC_POINT_add failed.\n", __func__); rv = 1; goto End; }; - + if (!(bnOutR = EC_POINT_point2bn(ecgrp, Rout, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx))) { LogPrintf("%s: Rout EC_POINT_bn2point failed.\n", __func__); rv = 1; goto End; }; - - + + pkOut.resize(EC_COMPRESSED_SIZE); if (BN_num_bytes(bnOutR) != (int) EC_COMPRESSED_SIZE || BN_bn2bin(bnOutR, &pkOut[0]) != (int) EC_COMPRESSED_SIZE) @@ -692,7 +701,7 @@ int StealthSharedToPublicKey(const ec_point& pkSpend, const ec_secret &sharedS, rv = 1; goto End; }; - + End: if (bnOutR) BN_free(bnOutR); if (Rout) EC_POINT_free(Rout); @@ -702,41 +711,47 @@ int StealthSharedToPublicKey(const ec_point& pkSpend, const ec_secret &sharedS, if (bnc) BN_free(bnc); if (bnCtx) BN_CTX_free(bnCtx); EC_GROUP_free(ecgrp); - + return rv; }; bool IsStealthAddress(const std::string& encodedAddress) { + if (encodedAddress.length() < 76) + { + //LogPrintf("IsStealthAddress address to short, quick fail.\n"); + return false; + }; + data_chunk raw; - + if (!DecodeBase58(encodedAddress, raw)) { //LogPrintf("IsStealthAddress DecodeBase58 falied.\n"); return false; }; - + if (!VerifyChecksum(raw)) { //LogPrintf("IsStealthAddress verify_checksum falied.\n"); return false; }; - + if (raw.size() < 1 + 1 + 33 + 1 + 33 + 1 + 1 + 4) { //LogPrintf("IsStealthAddress too few bytes provided.\n"); return false; }; - - + + uint8_t* p = &raw[0]; uint8_t version = *p++; - + if (version != Params().Base58Prefix(CChainParams::STEALTH_ADDRESS)[0]) { //LogPrintf("IsStealthAddress version mismatch 0x%x != 0x%x.\n", version, stealth_version_byte); return false; }; - + return true; }; diff --git a/src/stealth.h b/src/stealth.h index 33bc9d3669..2c7ec91025 100644 --- a/src/stealth.h +++ b/src/stealth.h @@ -1,12 +1,15 @@ -// Copyright (c) 2014 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. - -#ifndef SHADOW_STEALTH_H -#define SHADOW_STEALTH_H - -#include -#include +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT + +#ifndef SPECTRE_STEALTH_H +#define SPECTRE_STEALTH_H + +#include +#include #include #include @@ -32,49 +35,48 @@ const uint256 MIN_SECRET(16000); // increase? min valid key is 1 class CStealthAddress { public: - CStealthAddress() + CStealthAddress() : options(0) { - options = 0; }; - + uint8_t options; ec_point scan_pubkey; ec_point spend_pubkey; //std::vector spend_pubkeys; size_t number_signatures; stealth_prefix prefix; - + mutable std::string label; data_chunk scan_secret; data_chunk spend_secret; - + bool SetEncoded(const std::string& encodedAddress); std::string Encoded() const; - + int SetScanPubKey(CPubKey pk); - - + + bool operator <(const CStealthAddress& y) const { return memcmp(&scan_pubkey[0], &y.scan_pubkey[0], EC_COMPRESSED_SIZE) < 0; }; - + bool operator ==(const CStealthAddress& y) const { return memcmp(&scan_pubkey[0], &y.scan_pubkey[0], EC_COMPRESSED_SIZE) == 0; }; - + IMPLEMENT_SERIALIZE ( READWRITE(this->options); READWRITE(this->scan_pubkey); READWRITE(this->spend_pubkey); READWRITE(this->label); - + READWRITE(this->scan_secret); READWRITE(this->spend_secret); ); - + }; int GenerateRandomSecret(ec_secret& out); @@ -90,5 +92,5 @@ int StealthSharedToPublicKey(const ec_point& pkSpend, const ec_secret &sharedS, bool IsStealthAddress(const std::string& encodedAddress); -#endif // SHADOW_STEALTH_H +#endif // SPECTRE_STEALTH_H diff --git a/src/strlcpy.h b/src/strlcpy.h index 2cc786e953..fbd0a530a1 100644 --- a/src/strlcpy.h +++ b/src/strlcpy.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 1998 Todd C. Miller +// +// SPDX-License-Identifier: ISC + /* * Copyright (c) 1998 Todd C. Miller * diff --git a/src/sync.cpp b/src/sync.cpp index 5751051675..0844e36848 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2011-2012 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "sync.h" @@ -9,7 +12,6 @@ #include -#include #include #ifdef DEBUG_LOCKCONTENTION @@ -64,7 +66,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, { LogPrintf("POTENTIAL DEADLOCK DETECTED\n"); LogPrintf("Previous lock order was:\n"); - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) { + for (const auto& i : s2) { if (i.first == mismatch.first) LogPrintf(" (1)"); if (i.first == mismatch.second) @@ -72,7 +74,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, LogPrintf(" %s\n", i.second.ToString()); } LogPrintf("Current lock order is:\n"); - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) { + for (const auto& i : s1) { if (i.first == mismatch.first) LogPrintf(" (1)"); if (i.first == mismatch.second) @@ -83,9 +85,9 @@ static void potential_deadlock_detected(const std::pair& mismatch, static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) { - if (lockstack.get() == NULL) + if (lockstack.get() == nullptr) lockstack.reset(new LockStack); - + if (IsLogOpen()) LogPrint("lock", "Locking: %s\n", locklocation.ToString()); dd_mutex.lock(); @@ -93,7 +95,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) (*lockstack).push_back(std::make_pair(c, locklocation)); if (!fTry) { - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) { + for (const auto& i : *lockstack) { if (i.first == c) break; @@ -136,14 +138,14 @@ void LeaveCritical() std::string LocksHeld() { std::string result; - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + for (const auto& i : *lockstack) result += i.second.ToString() + std::string("\n"); return result; } void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) { - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + for (const auto& i : *lockstack) if (i.first == cs) return; fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); diff --git a/src/sync.h b/src/sync.h index 27e80e813b..d32edff186 100644 --- a/src/sync.h +++ b/src/sync.h @@ -1,119 +1,76 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT -#ifndef BITCOIN_SYNC_H -#define BITCOIN_SYNC_H +#ifndef ALIAS_SYNC_H +#define ALIAS_SYNC_H #include "threadsafety.h" -#include -#include -#include -#include +#include +#include +#include +#include - -//////////////////////////////////////////////// -// // -// THE SIMPLE DEFINITON, EXCLUDING DEBUG CODE // -// // -//////////////////////////////////////////////// - -/* - - - -CCriticalSection mutex; - boost::recursive_mutex mutex; - -LOCK(mutex); - boost::unique_lock criticalblock(mutex); - -LOCK2(mutex1, mutex2); - boost::unique_lock criticalblock1(mutex1); - boost::unique_lock criticalblock2(mutex2); - -TRY_LOCK(mutex, name); - boost::unique_lock name(mutex, boost::try_to_lock_t); - -ENTER_CRITICAL_SECTION(mutex); // no RAII - mutex.lock(); - -LEAVE_CRITICAL_SECTION(mutex); // no RAII - mutex.unlock(); - - - - */ - - -/////////////////////////////// -// // -// THE ACTUAL IMPLEMENTATION // -// // -/////////////////////////////// - -// Template mixin that adds -Wthread-safety locking annotations to a -// subset of the mutex API. template -class LOCKABLE AnnotatedMixin : public PARENT -{ +class LOCKABLE AnnotatedMixin : public PARENT { public: - void lock() EXCLUSIVE_LOCK_FUNCTION() - { + void lock() EXCLUSIVE_LOCK_FUNCTION() { PARENT::lock(); } - void unlock() UNLOCK_FUNCTION() - { + void unlock() UNLOCK_FUNCTION() { PARENT::unlock(); } - bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) - { + bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) { return PARENT::try_lock(); } }; -/** Wrapped boost mutex: supports recursive locking, but no waiting */ -// TODO: We should move away from using the recursive lock by default. -typedef AnnotatedMixin CCriticalSection; +using RecursiveMutex = AnnotatedMixin; +using Mutex = AnnotatedMixin; -/** Wrapped boost mutex: supports waiting but not recursive locking */ -typedef AnnotatedMixin CWaitableCriticalSection; - -/** Just a typedef for boost::condition_variable, can be wrapped later if desired */ -typedef boost::condition_variable CConditionVariable; +using CCriticalSection = RecursiveMutex; +using CWaitableCriticalSection = Mutex; +using CConditionVariable = std::condition_variable; +using GlobalMutex = Mutex; #ifdef DEBUG_LOCKORDER void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false); void LeaveCritical(); std::string LocksHeld(); void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); +void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs); +void DeleteLock(void* cs); +bool LockStackEmpty(); #else -void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) -{ -} -void static inline LeaveCritical() {} -void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} +inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {} +inline void LeaveCritical() {} +inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} +inline void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {} +inline void DeleteLock(void* cs) {} +inline bool LockStackEmpty() { return true; } #endif + #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) +#define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs) #ifdef DEBUG_LOCKCONTENTION void PrintLockContention(const char* pszName, const char* pszFile, int nLine); #endif -/** Wrapper around boost::unique_lock */ -template -class CMutexLock -{ +template +class SCOPED_LOCKABLE UniqueLock { private: - boost::unique_lock lock; + std::unique_lock lock; - void Enter(const char* pszName, const char* pszFile, int nLine) - { - EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex())); + void Enter(const char* pszName, const char* pszFile, int nLine) { + EnterCritical(pszName, pszFile, nLine, static_cast(lock.mutex())); #ifdef DEBUG_LOCKCONTENTION if (!lock.try_lock()) { PrintLockContention(pszName, pszFile, nLine); @@ -124,52 +81,62 @@ class CMutexLock #endif } - bool TryEnter(const char* pszName, const char* pszFile, int nLine) - { - EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); + bool TryEnter(const char* pszName, const char* pszFile, int nLine) { + EnterCritical(pszName, pszFile, nLine, static_cast(lock.mutex()), true); lock.try_lock(); - if (!lock.owns_lock()) + if (!lock.owns_lock()) { LeaveCritical(); + } return lock.owns_lock(); } public: - CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock) - { - if (fTry) + UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) + : lock(mutexIn, std::defer_lock) { + if (fTry) { TryEnter(pszName, pszFile, nLine); - else + } else { Enter(pszName, pszFile, nLine); + } } - CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) - { + UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { if (!pmutexIn) return; - lock = boost::unique_lock(*pmutexIn, boost::defer_lock); - if (fTry) + lock = std::unique_lock(*pmutexIn, std::defer_lock); + if (fTry) { TryEnter(pszName, pszFile, nLine); - else + } else { Enter(pszName, pszFile, nLine); + } } - ~CMutexLock() - { - if (lock.owns_lock()) + ~UniqueLock() UNLOCK_FUNCTION() { + if (lock.owns_lock()) { LeaveCritical(); + } } - operator bool() - { + operator bool() const { return lock.owns_lock(); } }; -typedef CMutexLock CCriticalBlock; +template +using DebugLock = UniqueLock; + +using CMutexLock = UniqueLock; +using CCriticalBlock = CMutexLock; + +#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(cs, #cs, __FILE__, __LINE__) +#define LOCK2(cs1, cs2) \ + UniqueLock UNIQUE_NAME(criticalblock1)(cs1, #cs1, __FILE__, __LINE__); \ + UniqueLock UNIQUE_NAME(criticalblock2)(cs2, #cs2, __FILE__, __LINE__) +#define TRY_LOCK(cs, name) UniqueLock name(cs, #cs, __FILE__, __LINE__, true) +#define WAIT_LOCK(cs, name) UniqueLock name(cs, #cs, __FILE__, __LINE__) -#define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__) -#define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__) -#define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true) +#define UNIQUE_NAME_HELPER(name, line) name##line +#define UNIQUE_NAME(name) UNIQUE_NAME_HELPER(name, __LINE__) #define ENTER_CRITICAL_SECTION(cs) \ { \ @@ -183,103 +150,89 @@ typedef CMutexLock CCriticalBlock; LeaveCritical(); \ } -class CSemaphore -{ +class CSemaphore { private: - boost::condition_variable condition; - boost::mutex mutex; + std::condition_variable condition; + std::mutex mutex; int value; public: - CSemaphore(int init) : value(init) {} + explicit CSemaphore(int init) : value(init) {} - void wait() - { - boost::unique_lock lock(mutex); - while (value < 1) { - condition.wait(lock); - } + void wait() { + std::unique_lock lock(mutex); + condition.wait(lock, [this] { return value >= 1; }); value--; } - bool try_wait() - { - boost::unique_lock lock(mutex); + bool try_wait() { + std::unique_lock lock(mutex); if (value < 1) return false; value--; return true; } - void post() - { + void post() { { - boost::unique_lock lock(mutex); + std::unique_lock lock(mutex); value++; } condition.notify_one(); } }; -/** RAII-style semaphore lock */ -class CSemaphoreGrant -{ +class CSemaphoreGrant { private: - CSemaphore* sem; - bool fHaveGrant; + CSemaphore* sem{nullptr}; + bool fHaveGrant{false}; public: - void Acquire() - { + void Acquire() { if (fHaveGrant) return; sem->wait(); fHaveGrant = true; } - void Release() - { + void Release() { if (!fHaveGrant) return; sem->post(); fHaveGrant = false; } - bool TryAcquire() - { + bool TryAcquire() { if (!fHaveGrant && sem->try_wait()) fHaveGrant = true; return fHaveGrant; } - void MoveTo(CSemaphoreGrant& grant) - { + void MoveTo(CSemaphoreGrant& grant) { grant.Release(); grant.sem = sem; grant.fHaveGrant = fHaveGrant; - sem = NULL; + sem = nullptr; fHaveGrant = false; } - CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {} + CSemaphoreGrant() = default; - CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false) - { - if (fTry) + explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false) { + if (fTry) { TryAcquire(); - else + } else { Acquire(); + } } - ~CSemaphoreGrant() - { + ~CSemaphoreGrant() { Release(); } - operator bool() - { + operator bool() const { return fHaveGrant; } }; -#endif // BITCOIN_SYNC_H +#endif // ALIAS_SYNC_H diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt new file mode 100644 index 0000000000..bd8bea97d2 --- /dev/null +++ b/src/test/CMakeLists.txt @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(Spectre + PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/accounting_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/allocator_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/base32_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/base58_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/base64_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/basic_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/bignum_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/bip32_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Checkpoints_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/extkey_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/getarg_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/hash_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/hmac_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/key_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/mnemonic_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/mruset_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/multisig_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/netbase_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/ringsig_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/rpc_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/script_P2SH_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/script_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/sigopcount_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/smsg_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/stealth_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/test_shadow.cpp" + "${CMAKE_CURRENT_LIST_DIR}/uint160_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/uint256_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/util_tests.cpp" + "${CMAKE_CURRENT_LIST_DIR}/wallet_tests.cpp" + ) diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index 9058487914..d05d8fe8a1 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers // +// SPDX-License-Identifier: MIT + // Unit tests for block-chain checkpoints // #include // for 'map_list_of()' #include -#include #include "../checkpoints.h" #include "../util.h" diff --git a/src/test/README b/src/test/README index 77f7faa815..b9cc9746ae 100644 --- a/src/test/README +++ b/src/test/README @@ -1,3 +1,8 @@ +SPDX-FileCopyrightText: © 2025 ALIAS Developers +SPDX-FileCopyrightText: © 2020 Alias Developers +SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +SPDX-License-Identifier: MIT + The sources in this directory are unit test cases. Boost includes a unit testing framework, and since bitcoin already uses boost, it makes sense to simply use this framework rather than require developers to diff --git a/src/test/accounting_tests.cpp b/src/test/accounting_tests.cpp index 6f8f410481..e4858b03aa 100644 --- a/src/test/accounting_tests.cpp +++ b/src/test/accounting_tests.cpp @@ -1,6 +1,10 @@ -#include +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT -#include +#include #include @@ -18,7 +22,7 @@ GetResults(CWalletDB& walletdb, std::map& results) results.clear(); BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK); walletdb.ListAccountCreditDebit("", aes); - BOOST_FOREACH(CAccountingEntry& ae, aes) + for (CAccountingEntry& ae : aes) { results[ae.nOrderPos] = ae; } diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp index d5cb8e8101..5ed2474126 100644 --- a/src/test/allocator_tests.cpp +++ b/src/test/allocator_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "init.h" diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index fdf3285913..f6b110de52 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "util.h" diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 79c4569547..cc7b5fb5ad 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2011-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2011 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "base58.h" @@ -11,7 +14,6 @@ #include "state.h" #include "chainparams.h" -#include #include #include "json/json_spirit_reader_template.h" #include "json/json_spirit_utils.h" @@ -27,7 +29,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58) { Array tests = read_json("base58_encode_decode.json"); - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); std::string strTest = write_string(tv, false); @@ -50,7 +52,7 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) Array tests = read_json("base58_encode_decode.json"); std::vector result; - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); std::string strTest = write_string(tv, false); @@ -130,7 +132,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) // Save global state bool fTestNet_stored = fTestNet; - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); std::string strTest = write_string(tv, false); @@ -192,7 +194,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) // Save global state bool fTestNet_stored = fTestNet; - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); std::string strTest = write_string(tv, false); @@ -266,7 +268,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid) CBitcoinSecret secret; CBitcoinAddress addr; - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); std::string strTest = write_string(tv, false); diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index c5a053e2eb..f2b965ae92 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "main.h" diff --git a/src/test/basic_tests.cpp b/src/test/basic_tests.cpp index 54f1804992..a7a1d752a0 100644 --- a/src/test/basic_tests.cpp +++ b/src/test/basic_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index b161f2cabb..21ec38a18b 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 79f4149e8f..c128cd1a75 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2013 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2013 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include @@ -36,44 +39,44 @@ struct TestVector { TestVector test1 = TestVector("000102030405060708090a0b0c0d0e0f") - ("sdcpmphCJNSUos9rNrtJLHBihz4Gtqa7LMjjAGt4SH5a4tQH9ykYb3cNnp8VvGGAYtfH7phiveYFfYKjQGNNNj6aKTYTW1ztB9buBzJXsCCKg7hY", - "sdcvmnKmFxG9k6UnN54BRiwaq8PwLWAgSN7FaQmbitre71x318T8NPjZLCYsGTVcZq1HqLCmtataXdcxjR4T9rrZdCpHom1HAucKgENFhTARR3qu", + ("specpmphCJNSUos9rNrtJLHBihz4Gtqa7LMjjAGt4SH5a4tQH9ykYb3cNnp8VvGGAYtfH7phiveYFfYKjQGNNNj6aKTYTW1ztB9buBzJXsCCKg7hY", + "specvmnKmFxG9k6UnN54BRiwaq8PwLWAgSN7FaQmbitre71x318T8NPjZLCYsGTVcZq1HqLCmtataXdcxjR4T9rrZdCpHom1HAucKgENFhTARR3qu", 0x80000000) - ("sdcpmpjTiN9nGxQyN1VS3UwbLs6P1APfgjpDAxVVLFAxBrbUSM2qmTquswGrL3XjFdyBepv1VWmo6GxoVEmLWg8JhXRvEDdgS4uoQWEfRVoaXBqn", - "sdcvmnN2fwyTDBjuMDfK8vhTU1S3SpzEnkBjb6P2crx2Dz9EHVjRYoy6RKhDgEkxuEifo3FfaxBuQ1yoc8pUsWSqoztNKpsxK9a2ZwNtYtF4VFaT", + ("specpmpjTiN9nGxQyN1VS3UwbLs6P1APfgjpDAxVVLFAxBrbUSM2qmTquswGrL3XjFdyBepv1VWmo6GxoVEmLWg8JhXRvEDdgS4uoQWEfRVoaXBqn", + "specvmnN2fwyTDBjuMDfK8vhTU1S3SpzEnkBjb6P2crx2Dz9EHVjRYoy6RKhDgEkxuEifo3FfaxBuQ1yoc8pUsWSqoztNKpsxK9a2ZwNtYtF4VFaT", 1) - ("sdcpmpmdqZwLAM7rRqwUVDCVDTqGfDmenjqwTtpAAqSizoEGeaaLuBeLBtqkZTcBq3utznddYJCFCPZHxq55L9TUbD5kAWqXHYYog8yCCnnzVCUb", - "sdcvmnQCo9m16aSnR47MaexMLcAw6tNDtkDTt2hhTTDo2vn2VjGvgXmWjHG7uep9xqeSqVLRGm1Vq6gm2Gm16dndnn3rmLev3DKoRcBCvRBBcr6u", + ("specpmpmdqZwLAM7rRqwUVDCVDTqGfDmenjqwTtpAAqSizoEGeaaLuBeLBtqkZTcBq3utznddYJCFCPZHxq55L9TUbD5kAWqXHYYog8yCCnnzVCUb", + "specvmnQCo9m16aSnR47MaexMLcAw6tNDtkDTt2hhTTDo2vn2VjGvgXmWjHG7uep9xqeSqVLRGm1Vq6gm2Gm16dndnn3rmLev3DKoRcBCvRBBcr6u", 0x80000002) - ("sdcpmppF7cUA23zhqi7GaTntapqJoSvXK1PXTEMPr5n29y6e5zRY1zQAcoHJV1dNfVnLK99jGuaDomVrwHQDcrZ28GXu16jVRdVsMrf7Lt3e2p74", - "sdcvmnSp5CHpxHKdpvH9fuYkhyAyF7X6R1m3sNEw8hZ6C6ePw987oLXMABhfqCrNaosxKzoSfMUSkX6avVxjrDoYyu9JRhGUbNG3NDSx93nffRrZ", + ("specpmppF7cUA23zhqi7GaTntapqJoSvXK1PXTEMPr5n29y6e5zRY1zQAcoHJV1dNfVnLK99jGuaDomVrwHQDcrZ28GXu16jVRdVsMrf7Lt3e2p74", + "specvmnSp5CHpxHKdpvH9fuYkhyAyF7X6R1m3sNEw8hZ6C6ePw987oLXMABhfqCrNaosxKzoSfMUSkX6avVxjrDoYyu9JRhGUbNG3NDSx93nffRrZ", 2) - ("sdcpmprUWSuGyEUNpnakJA46fiLU7Xjp3dyqefqH9LjYdHYChMXAP4AryzrmQgxN3uaV3cTrT3ahkpEm3qpZcwrTKz8NG1X3cTgmBsM2C2fbX7jP", - "sdcvmnV3U2iwuToJozkdPboxnrg8ZCLP9eMN4oipRxWcfR5xYWDkAQJ3XPH8ktAn3GYMm4baMyPgKRv35y9eJRE6L6XtU6WZgvLs5NRRJZK86GzL", + ("specpmprUWSuGyEUNpnakJA46fiLU7Xjp3dyqefqH9LjYdHYChMXAP4AryzrmQgxN3uaV3cTrT3ahkpEm3qpZcwrTKz8NG1X3cTgmBsM2C2fbX7jP", + "specvmnV3U2iwuToJozkdPboxnrg8ZCLP9eMN4oipRxWcfR5xYWDkAQJ3XPH8ktAn3GYMm4baMyPgKRv35y9eJRE6L6XtU6WZgvLs5NRRJZK86GzL", 1000000000) - ("sdcpmptCGvatDMbm2JvXkGbfQ23U7KyPMTUegU5fhb1vmVcbC4eZmab7eFxvUKnGzkqZm6A8zYvdZMSTeSExe3hxAqPXNt4ThGALpgJe7GmrkQ3d", - "sdcvmnWmEWQZ9avh1X6QqiMXXAP8YzZxTTrB6byCzCnzodAM3DM9YviJBePHpX2ZFBTUqfzyckkfGGxaCyKefxJ74DVY1S1Kv3FcnekyfJPP6sPi", + ("specpmptCGvatDMbm2JvXkGbfQ23U7KyPMTUegU5fhb1vmVcbC4eZmab7eFxvUKnGzkqZm6A8zYvdZMSTeSExe3hxAqPXNt4ThGALpgJe7GmrkQ3d", + "specvmnWmEWQZ9avh1X6QqiMXXAP8YzZxTTrB6byCzCnzodAM3DM9YviJBePHpX2ZFBTUqfzyckkfGGxaCyKefxJ74DVY1S1Kv3FcnekyfJPP6sPi", 0); TestVector test2 = TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542") - ("sdcpmphCJNSUos9rNrVofPLnzSFzf5mFm3MyyxTrAa2JtrnQ2GjZnDm9jF2fWcNFXbue5jFxiZCupwQEezA6brHVUbTTSsw5dz6PrJgCyU7FQ7E2", - "sdcvmnKmFxG9k6UnN4fgkq6f7abf6kMps3jWQ6MPTBoNvzL9sRS9ZZtLGdT2roZPd1WqvaFXKLB2yuizvWbBFuGxKpBcaDRMR3xEQocsvp83bv6g", + ("specpmphCJNSUos9rNrVofPLnzSFzf5mFm3MyyxTrAa2JtrnQ2GjZnDm9jF2fWcNFXbue5jFxiZCupwQEezA6brHVUbTTSsw5dz6PrJgCyU7FQ7E2", + "specvmnKmFxG9k6UnN4fgkq6f7abf6kMps3jWQ6MPTBoNvzL9sRS9ZZtLGdT2roZPd1WqvaFXKLB2yuizvWbBFuGxKpBcaDRMR3xEQocsvp83bv6g", 0) - ("sdcpmpkU3eAAmMAgTNmPxX8AsW4QBSj11kLUGWdbXjqLLwCFyxi1ko2VoPsEmBqDRPzeWwaStRRuaLV5d9KXHjSBtw47j9ypJtSYESAKduHfhAwT", - "sdcvmnP31DyqhaVcSawH3xt2zeQ4d7Ka7khzgeX8pMcQP4k1q7QbY99gLnHc7P4fReagkyum9EBSiLtR3s6p5TZTNkQmyDbmUSSQ9w2nVBRAQusZ", + ("specpmpkU3eAAmMAgTNmPxX8AsW4QBSj11kLUGWdbXjqLLwCFyxi1ko2VoPsEmBqDRPzeWwaStRRuaLV5d9KXHjSBtw47j9ypJtSYESAKduHfhAwT", + "specvmnP31DyqhaVcSawH3xt2zeQ4d7Ka7khzgeX8pMcQP4k1q7QbY99gLnHc7P4fReagkyum9EBSiLtR3s6p5TZTNkQmyDbmUSSQ9w2nVBRAQusZ", 0xFFFFFFFF) - ("sdcpmpmd6tmCHj4rZYdc8waAWyQ5jqUDvHpdxbng4fEF7aw2NR1FDQuv7bw2MoDTY9jFcj6NS5GmBdhWDozPdWLg1fCaMh4SNFAoFJYbEk8qTdBJ", - "sdcvmnQC4UasDxPnYkoVEPL2e7jkBW4o2JCANjgDMH1K9iUnDZhpzm36ezMPhzR9QNqREt9631CeMPtvAJLYrBw4WKiDXeKzpCx8Qip81wnR9zqt", + ("specpmpmd6tmCHj4rZYdc8waAWyQ5jqUDvHpdxbng4fEF7aw2NR1FDQuv7bw2MoDTY9jFcj6NS5GmBdhWDozPdWLg1fCaMh4SNFAoFJYbEk8qTdBJ", + "specvmnQC4UasDxPnYkoVEPL2e7jkBW4o2JCANjgDMH1K9iUnDZhpzm36ezMPhzR9QNqREt9631CeMPtvAJLYrBw4WKiDXeKzpCx8Qip81wnR9zqt", 1) - ("sdcpmppS5JnBDti9keFHH1EK5wM1yB16RQ1ZDvEAvWHuStpNp5q7NiRSpVqQje1efwbwuKGpyuurRGpp3tneeRF6xvY3GHLeDTiETEKGBzYUstev", - "sdcvmnT12tbrA835jrRANSzBD5ggQqbfXQP5e47iD84yV2N8fEXhA4YdMtFn5qDM2QYcwC6SjkVijoSbNd3L1EpatLC2pn6Xd446oCcYkRQz9q1Q", + ("specpmppS5JnBDti9keFHH1EK5wM1yB16RQ1ZDvEAvWHuStpNp5q7NiRSpVqQje1efwbwuKGpyuurRGpp3tneeRF6xvY3GHLeDTiETEKGBzYUstev", + "specvmnT12tbrA835jrRANSzBD5ggQqbfXQP5e47iD84yV2N8fEXhA4YdMtFn5qDM2QYcwC6SjkVijoSbNd3L1EpatLC2pn6Xd446oCcYkRQz9q1Q", 0xFFFFFFFE) - ("sdcpmpqc7Dk7aW77TwCWsji8dJriA5jZnSzBiwvtp31brjae4YBSJp6Nq2MmqGfnB8yUMGiUciQv8KS8uYRp378DUdtjiZExi21Ks6YLmXVBrpCw", - "sdcvmnUB4oZnWjS3T9NPyBTzkTCNbkL8tTMi95pS6enfts8Pugt26ADZNQn9BTv5R2y1DjfjS4KVjBpAxSARNkmVP22hzc34wCG8RYCZGVG3ZpQr", + ("specpmpqc7Dk7aW77TwCWsji8dJriA5jZnSzBiwvtp31brjae4YBSJp6Nq2MmqGfnB8yUMGiUciQv8KS8uYRp378DUdtjiZExi21Ks6YLmXVBrpCw", + "specvmnUB4oZnWjS3T9NPyBTzkTCNbkL8tTMi95pS6enfts8Pugt26ADZNQn9BTv5R2y1DjfjS4KVjBpAxSARNkmVP22hzc34wCG8RYCZGVG3ZpQr", 2) - ("sdcpmpry9BBL62HRhgThmTnGKHc68Uo6thK6oc6WhSnxMNNVecNmsyjJbCviqM4rTGYq3nmgqzLRYD99u2rsXwDuNx9bJCQnnxNcbmqXxC9nTA4W", - "sdcvmnVY6m112FcMgtdaruY8SRwka9PfzhgdDjz3z4a2PVvFVm5MfKrV8bM6BYKkRBz6HmybAM58Ydv1eUiJtV5rc51SiQtaSFgG9EZtpZrEG3j9", + ("specpmpry9BBL62HRhgThmTnGKHc68Uo6thK6oc6WhSnxMNNVecNmsyjJbCviqM4rTGYq3nmgqzLRYD99u2rsXwDuNx9bJCQnnxNcbmqXxC9nTA4W", + "specvmnVY6m112FcMgtdaruY8SRwka9PfzhgdDjz3z4a2PVvFVm5MfKrV8bM6BYKkRBz6HmybAM58Ydv1eUiJtV5rc51SiQtaSFgG9EZtpZrEG3j9", 0); void RunTest(const TestVector &test) { @@ -82,7 +85,7 @@ void RunTest(const TestVector &test) { CExtPubKey pubkey; key.SetMaster(&seed[0], seed.size()); pubkey = key.Neutered(); - BOOST_FOREACH(const TestDerivation &derive, test.vDerive) { + for (const TestDerivation& derive : test.vDerive) { unsigned char data[74]; key.Encode(data); pubkey.Encode(data); diff --git a/src/test/data/bip39_vectors.json b/src/test/data/bip39_vectors.json index 8b7c71994a..b48a3a0e73 100644 --- a/src/test/data/bip39_vectors.json +++ b/src/test/data/bip39_vectors.json @@ -153,7 +153,7 @@ "80808080808080808080808080808080", "そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら あまど おおう あかちゃん", "メートルガバヴァぱばぐゞちぢ十人十色", - "e51736736ebdf77eda23fa17e31475fa1d9509c78f1deb6b4aacfbd760a7e2ad769c714352c95143b5c1241985bcb407df36d64e75dd5a2b78ca5d2ba82a3544", + "e36657736ebdf77eda23fa17e31475fa1d9509c78f1deb6b4aacfbd760a7e2ad769c714352c95143b5c1241985bcb407df36d64e75dd5a2b78ca5d2ba82a3544", "xprv9s21ZrQH143K2aDKfG8hpfvRXzANmyBQWoqoUXWaSwVZcKtnmX5xTVkkHAdD9yykuuBcagjCFK6iLcBdHHxXC1g3TT9xHSu4PW6SRf3KvVy" ], [ diff --git a/src/test/extkey_tests.cpp b/src/test/extkey_tests.cpp index 4f449d9b0b..1c1adc4d08 100644 --- a/src/test/extkey_tests.cpp +++ b/src/test/extkey_tests.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2015 The ShadowCoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include @@ -24,7 +27,7 @@ #include -// test_shadow --log_level=all --run_test=bip32_tests,extkey_tests +// test_spectre --log_level=all --run_test=bip32_tests,extkey_tests namespace ba = boost::assign; @@ -76,51 +79,51 @@ PassTest passTests[] = { PassTest("m/4/0b001/0xFe/3/0b010/0b010h", 0, { 0, 4, 1, 254, 3, 2, 2147483650 }), PassTest("m/2147483647h", 0, { 0, 4294967295 }), PassTest("0800/0xFh", 0, { 800, 2147483663 }), - + }; void RunPathTest() { int rv; - + std::vector vPath; std::vector vExpect; std::string sTest; - + int al = sizeof(failTests)/sizeof(FailTest); - - BOOST_MESSAGE("Running " << al << " tests expected to fail."); - + + BOOST_TEST_MESSAGE("Running " << al << " tests expected to fail."); + for (int i = 0; i < al; ++i) { FailTest &ft = failTests[i]; - BOOST_MESSAGE("Fail test " << i << ", path '" << ft.sTest << "', expect return " << ft.rv); + BOOST_TEST_MESSAGE("Fail test " << i << ", path '" << ft.sTest << "', expect return " << ft.rv); rv = ExtractExtKeyPath(ft.sTest, vPath); BOOST_CHECK(rv == ft.rv); //BOOST_CHECK_MESSAGE(rv != ft.rv, "rv " << rv); }; - + char tooMuchData[513]; memset(tooMuchData, '/', 512); tooMuchData[512] = '\0'; sTest = std::string(tooMuchData); - BOOST_MESSAGE("Testing Path 'tooMuchData'"); + BOOST_TEST_MESSAGE("Testing Path 'tooMuchData'"); rv = ExtractExtKeyPath(sTest, vPath); BOOST_CHECK(rv == 2); - - + + al = sizeof(passTests)/sizeof(PassTest); - - BOOST_MESSAGE("Running " << al << " tests expected to pass."); - + + BOOST_TEST_MESSAGE("Running " << al << " tests expected to pass."); + std::stringstream ss, ssE; for (int i = 0; i < al; ++i) { PassTest &pt = passTests[i]; - BOOST_MESSAGE("Pass test " << i << ", path '" << pt.sTest << "', expect return " << pt.rv); + BOOST_TEST_MESSAGE("Pass test " << i << ", path '" << pt.sTest << "', expect return " << pt.rv); rv = ExtractExtKeyPath(pt.sTest, vPath); - + ss.str(""); for (std::vector::iterator it = vPath.begin(); it != vPath.end(); ++it) { @@ -128,8 +131,8 @@ void RunPathTest() if (it != vPath.end()-1) ss << ", "; }; - BOOST_MESSAGE("vPath " << ss.str()); - + BOOST_TEST_MESSAGE("vPath " << ss.str()); + ssE.str(""); for (std::vector::iterator it = pt.vExpect.begin(); it != pt.vExpect.end(); ++it) { @@ -137,14 +140,14 @@ void RunPathTest() if (it != pt.vExpect.end()-1) ssE << ", "; }; - BOOST_MESSAGE("vExpect " << ssE.str()); - + BOOST_TEST_MESSAGE("vExpect " << ssE.str()); + BOOST_CHECK(rv == pt.rv); BOOST_CHECK(vPath == pt.vExpect); }; - + //for (std::vector::iterator it = vPath.begin(); it != vPath.end(); ++it) - // BOOST_MESSAGE("vPath " << *it); + // BOOST_TEST_MESSAGE("vPath " << *it); } @@ -152,7 +155,7 @@ class DeriveTestData { public: DeriveTestData(uint32_t _nDerives, std::string _vKey58, std::string _pKey58) : nDerives(_nDerives), vKey58(_vKey58), pKey58(_pKey58) { }; - + uint32_t nDerives; std::string vKey58; std::string pKey58; @@ -164,35 +167,35 @@ void RunDeriveTest(std::vector &vData) CBitcoinExtKey extKey58; CExtKey evkeyM; CExtPubKey epkeyM; - + for (uint32_t k = 0; k < vData.size(); ++k) { DeriveTestData &dt = vData[k]; - + if (dt.nDerives == 0) { // - set master - + BOOST_CHECK(0 == (rv = extKey58.Set58(dt.vKey58.c_str()))); BOOST_CHECK(0 == (rv += abs(strcmp(extKey58.ToString().c_str(), dt.vKey58.c_str())))); - + evkeyM = extKey58.GetKey(); BOOST_CHECK(0 == (rv += abs(strcmp(CBitcoinExtKey(evkeyM).ToString().c_str(), dt.vKey58.c_str())))); epkeyM = evkeyM.Neutered(); - + BOOST_CHECK(0 == (rv += abs(strcmp(CBitcoinExtPubKey(epkeyM).ToString().c_str(), dt.pKey58.c_str())))); - + BOOST_CHECK(CBitcoinExtPubKey(epkeyM).ToString().c_str()); - + if (rv != 0) { - BOOST_MESSAGE("Set master failed, aborting test."); + BOOST_TEST_MESSAGE("Set master failed, aborting test."); break; } continue; }; - - + + CExtKey evkey[2], evkeyOut; CExtPubKey epkeyOut; evkey[0] = evkeyM; @@ -203,17 +206,17 @@ void RunDeriveTest(std::vector &vData) } BOOST_CHECK(dt.nDerives == (uint32_t)rv); evkeyOut = evkey[dt.nDerives % 2]; - + BOOST_CHECK(CBitcoinExtKey(evkeyOut).ToString().c_str()); - BOOST_MESSAGE("evkeyOut.nDepth " << (int)evkeyOut.nDepth); + BOOST_TEST_MESSAGE("evkeyOut.nDepth " << (int)evkeyOut.nDepth); BOOST_CHECK(evkeyOut.nDepth == dt.nDerives % 256); - + BOOST_CHECK(0 == strcmp(CBitcoinExtKey(evkeyOut).ToString().c_str(), dt.vKey58.c_str())); - + epkeyOut = evkeyOut.Neutered(); BOOST_CHECK(0 == strcmp(CBitcoinExtPubKey(epkeyOut).ToString().c_str(), dt.pKey58.c_str())); }; - + } void RunDeriveTests() @@ -221,63 +224,63 @@ void RunDeriveTests() /* Must be able to derive deeper than the arbitrary ndepth field (255) */ - + std::vector vMainNetPairs = { DeriveTestData(0, - std::string("sdcvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2"), - std::string("sdcpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J")), + std::string("specvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2"), + std::string("specpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J")), DeriveTestData(1, - std::string("sdcvmnMjfkum2tHDUJ9dJVLw6pitrnbvAHwQrxoukwSxU1zm9H3iEsx2a9R8J1ZncvjwZFdYd9QN33zUX7WvqEUzXUWKumZYnAB4Vgo4zD8jsyYq"), - std::string("sdcpmpjAiB666exHV5ykD3b4ygPER81M4HZtSpvNUKftRtT1J8M8TXpr2kzkwpJr3awQ1XaEYVSC1FTVEAxJV3rah692fvg9MpKNpwsRVfTnZVvh")), - + std::string("specvmnMjfkum2tHDUJ9dJVLw6pitrnbvAHwQrxoukwSxU1zm9H3iEsx2a9R8J1ZncvjwZFdYd9QN33zUX7WvqEUzXUWKumZYnAB4Vgo4zD8jsyYq"), + std::string("specpmpjAiB666exHV5ykD3b4ygPER81M4HZtSpvNUKftRtT1J8M8TXpr2kzkwpJr3awQ1XaEYVSC1FTVEAxJV3rah692fvg9MpKNpwsRVfTnZVvh")), + DeriveTestData(350, - std::string("sdcvmqPip8zYeR3ofPsSajfM5QtRqa8iZk6Z2bskpAJ7fiysxCAdqkG7fYHzNc5zReSHpYZgxtJ5GKTvcRqZW6a8rhurBuXCTqXfANNy5p7qTemf"), - std::string("sdcpmsm9rZAsiBisgBhZVHuUxGYmPuY9Tjj2cTzDXYX3dbS873U44Q8w89sd2QriazFKyFGwTTcizkeNvaksc2gLpTVmpzcGxmBGeSNbRwykttFP")), + std::string("specvmqPip8zYeR3ofPsSajfM5QtRqa8iZk6Z2bskpAJ7fiysxCAdqkG7fYHzNc5zReSHpYZgxtJ5GKTvcRqZW6a8rhurBuXCTqXfANNy5p7qTemf"), + std::string("specpmsm9rZAsiBisgBhZVHuUxGYmPuY9Tjj2cTzDXYX3dbS873U44Q8w89sd2QriazFKyFGwTTcizkeNvaksc2gLpTVmpzcGxmBGeSNbRwykttFP")), }; - + std::vector vTestNetPairs = { DeriveTestData(0, - std::string("SDCVTZWtnQrSZ1LBHScXxi5amgw4Q1zGaRuAy5S12NAttbx3Bmsm1jDYh1B5P5qTPZaWpUZZ5mmubGTYjXPB1cQ9btJmhDoBLHZnwAGUBVH42gB3"), - std::string("SDCPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp")), + std::string("SPECVTZWtnQrSZ1LBHScXxi5amgw4Q1zGaRuAy5S12NAttbx3Bmsm1jDYh1B5P5qTPZaWpUZZ5mmubGTYjXPB1cQ9btJmhDoBLHZnwAGUBVH42gB3"), + std::string("SPECPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp")), DeriveTestData(1, - std::string("SDCVTZYsCDW3qo8cPgpBvNxbkUPwK83wki5ZpBgTJpu5ZQ6Fnh4uj8BxMWiZf6Agi2YiCYojfB5rveT5AkGxsrFzdEg44Hyv8HhFsM1ZgN1keP5r"), - std::string("SDCPTTcbYtmsZFoZ2ofMW9ac3HnZVSThCwqaLqiEqizNqQcEXagQKhDGUVbtva3q1AcbjQHRSudnnUAqdaPPfPz5Vmva7v8yhvfe1wE5CW1VbMPQ")), - + std::string("SPECVTZYsCDW3qo8cPgpBvNxbkUPwK83wki5ZpBgTJpu5ZQ6Fnh4uj8BxMWiZf6Agi2YiCYojfB5rveT5AkGxsrFzdEg44Hyv8HhFsM1ZgN1keP5r"), + std::string("SPECPTTcbYtmsZFoZ2ofMW9ac3HnZVSThCwqaLqiEqizNqQcEXagQKhDGUVbtva3q1AcbjQHRSudnnUAqdaPPfPz5Vmva7v8yhvfe1wE5CW1VbMPQ")), + DeriveTestData(350, - std::string("SDCVTcarLbaqTKuCanY1CdH1j4ZUHuakAAEhypkJN3kEm75NbcBqKzW3SubRjggtWkF4Tqjszuya9uvXG4bbYiM8xU5aLRwZoy3rY2bTmxwvGxui"), - std::string("SDCPTWeahGrfAna9DuPAnPu21sx6UDzVcPziWUn5twqY37bMLVoKvZXMZtUm1AbhYZvXh7z8MspKmyMjKzBxnNoqd9HKGz57JsXXqRjF8nXws6C5")), + std::string("SPECVTcarLbaqTKuCanY1CdH1j4ZUHuakAAEhypkJN3kEm75NbcBqKzW3SubRjggtWkF4Tqjszuya9uvXG4bbYiM8xU5aLRwZoy3rY2bTmxwvGxui"), + std::string("SPECPTWeahGrfAna9DuPAnPu21sx6UDzVcPziWUn5twqY37bMLVoKvZXMZtUm1AbhYZvXh7z8MspKmyMjKzBxnNoqd9HKGz57JsXXqRjF8nXws6C5")), }; CBitcoinExtKey extKey58; - + // - valid string BOOST_CHECK(0 == extKey58.Set58(vMainNetPairs[0].vKey58.c_str())); BOOST_CHECK(strcmp(extKey58.ToString().c_str(), vMainNetPairs[0].vKey58.c_str()) == 0); // - invalid string BOOST_CHECK(0 != extKey58.Set58(vMainNetPairs[0].vKey58.c_str()+3)); - + RunDeriveTest(vMainNetPairs); - - + + // - fail testnet key on main BOOST_CHECK(0 != extKey58.Set58(vTestNetPairs[0].vKey58.c_str())); - - - - - - + + + + + + // - switch to testnet - BOOST_MESSAGE("Entering Testnet"); + BOOST_TEST_MESSAGE("Entering Testnet"); fTestNet = true; SelectParams(CChainParams::TESTNET); - + // - pass testnet key on testnet BOOST_CHECK(0 == extKey58.Set58(vTestNetPairs[0].vKey58.c_str())); BOOST_CHECK(strcmp(extKey58.ToString().c_str(), vTestNetPairs[0].vKey58.c_str()) == 0); - + RunDeriveTest(vTestNetPairs); - - + + // -return to mainnet fTestNet = false; SelectParams(CChainParams::MAIN); @@ -292,54 +295,54 @@ void RunSerialiseTests() int64_t nTest4_1 = 2189410940l; // 2039 int64_t nTest5 = 4294967298l; // 2106 int64_t nTest8 = -3l; - + BOOST_CHECK(0 == GetNumBytesReqForInt(nTest0)); BOOST_CHECK(4 == GetNumBytesReqForInt(nTest4)); BOOST_CHECK(4 == GetNumBytesReqForInt(nTest4_1)); // expect 4, no sign bit BOOST_CHECK(5 == GetNumBytesReqForInt(nTest5)); BOOST_CHECK(8 == GetNumBytesReqForInt(nTest8)); - - //BOOST_MESSAGE(GetNumBytesReqForInt(nTest5)); - + + //BOOST_TEST_MESSAGE(GetNumBytesReqForInt(nTest5)); + std::vector v; SetCompressedInt64(v, nTest0); GetCompressedInt64(v, (uint64_t&)nTest); BOOST_CHECK(nTest0 == nTest); - + SetCompressedInt64(v, nTest5); GetCompressedInt64(v, (uint64_t&)nTest); BOOST_CHECK(nTest5 == nTest); - + SetCompressedInt64(v, nTest8); GetCompressedInt64(v, (uint64_t&)nTest); BOOST_CHECK(nTest8 == nTest); - - + + CStoredExtKey sk, sk_; CStoredExtKey skInvalid, skInvalid_; - + CExtKey58 eKey58; - BOOST_CHECK(0 == eKey58.Set58("sdcvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2")); - + BOOST_CHECK(0 == eKey58.Set58("specvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2")); + sk.kp = eKey58.GetKey(); sk.sLabel = "sk label"; sk.nGenerated = 5; sk.nHGenerated = 6; sk.mapValue[EKVT_CREATED_AT] = SetCompressedInt64(v, nTest8); - + eKey58.SetKey(sk.kp, CChainParams::EXT_PUBLIC_KEY); - BOOST_CHECK(eKey58.ToString() == "sdcpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J"); - + BOOST_CHECK(eKey58.ToString() == "specpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J"); + eKey58.SetKeyV(sk.kp); - BOOST_CHECK(eKey58.ToString() == "sdcvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2"); - - + BOOST_CHECK(eKey58.ToString() == "specvmnKmFxG9k6UnN3wyLpTv83G1wgYEz1m21rZTUUimoDrYYMrZXUycudse21EZJTmkBBPN3k6Qhfzx5td8xzd9W893YhNozA3bZW3yVLVdrZU2"); + + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << sk << skInvalid; - + ss >> sk_; ss >> skInvalid_; - + BOOST_CHECK(sk.kp == sk_.kp); BOOST_CHECK(1 == sk_.kp.IsValidV()); BOOST_CHECK(1 == sk_.kp.IsValidP()); @@ -347,203 +350,203 @@ void RunSerialiseTests() BOOST_CHECK(sk.nGenerated == sk_.nGenerated); BOOST_CHECK(sk.nHGenerated == sk_.nHGenerated); BOOST_CHECK(nTest8 == GetCompressedInt64(sk_.mapValue[EKVT_CREATED_AT], (uint64_t&)nTest)); - + BOOST_CHECK(0 == skInvalid.kp.IsValidV()); BOOST_CHECK(0 == skInvalid.kp.IsValidP()); - - - + + + // path - + std::vector vPath; - + PushUInt32(vPath, 1); PushUInt32(vPath, 3); PushUInt32(vPath, 2); PushUInt32(vPath, 4294967295); - + std::string sPath; BOOST_CHECK(0 == PathToString(vPath, sPath, 'h')); BOOST_CHECK(sPath == "m/1/3/2/2147483647h"); - + vPath.resize(0); PushUInt32(vPath, 1); PushUInt32(vPath, 4294967294); PushUInt32(vPath, 30); BOOST_CHECK(0 == PathToString(vPath, sPath)); BOOST_CHECK(sPath == "m/1/2147483646'/30"); - - + + // id CBitcoinAddress addr; CKeyID id = sk.GetID(); CKeyID idTest; - - + + BOOST_CHECK(true == addr.Set(id, CChainParams::EXT_KEY_HASH) && addr.IsValid(CChainParams::EXT_KEY_HASH) && addr.GetKeyID(idTest, CChainParams::EXT_KEY_HASH)); - + BOOST_CHECK(id == idTest); BOOST_CHECK_MESSAGE(addr.ToString() == "x9S4Xj1DZwFsdFno1uHknNNGqdMWgXdhX6", addr.ToString()); - - + + // - test DeriveNextKey - + CExtKey ev; CExtPubKey ep; uint32_t nChild=0; - + sk.nGenerated = 0; sk.nHGenerated = 0; BOOST_CHECK(0 == sk.DeriveNextKey(ev, nChild)); BOOST_CHECK_MESSAGE(1 == sk.nGenerated, "nGenerated " << sk.nGenerated); sk.nGenerated = 0; BOOST_CHECK(0 == sk.DeriveNextKey(ep, nChild)); - + BOOST_CHECK(ep.pubkey == ev.key.GetPubKey()); - - + + id = ev.key.GetPubKey().GetID(); addr.Set(id, CChainParams::EXT_KEY_HASH); BOOST_CHECK_MESSAGE(addr.ToString() == "xS8vxP6PVm3ycqm4NqvUkhiDWqeBhhekzn", addr.ToString()); - + sk.nGenerated = 1; BOOST_CHECK(0 == sk.DeriveNextKey(ev, nChild)); id = ev.key.GetPubKey().GetID(); addr.Set(id, CChainParams::EXT_KEY_HASH); BOOST_CHECK_MESSAGE(addr.ToString() == "xRfAtU1u43VJBTt4agxpnPvXjf28hSmwrL", addr.ToString()); - + sk.nHGenerated = 0; BOOST_CHECK(0 == sk.DeriveNextKey(ev, nChild, true)); id = ev.key.GetPubKey().GetID(); addr.Set(id, CChainParams::EXT_KEY_HASH); BOOST_CHECK_MESSAGE(addr.ToString() == "xEcqVH3fRnNZabMHVctAeScJY9ySkg6BSF", addr.ToString()); BOOST_CHECK_MESSAGE(1 == sk.nHGenerated, "nHGenerated " << sk.nHGenerated); - + sk.nHGenerated = 1; BOOST_CHECK(0 == sk.DeriveNextKey(ev, nChild, true)); id = ev.key.GetPubKey().GetID(); addr.Set(id, CChainParams::EXT_KEY_HASH); BOOST_CHECK_MESSAGE(addr.ToString() == "xRfBk2tuann5qTVKyW2HmA9CJZBAE1sRvJ", addr.ToString()); BOOST_CHECK_MESSAGE(2 == sk.nHGenerated, "nHGenerated " << sk.nHGenerated); - + sk.nHGenerated = 1; BOOST_CHECK(0 == sk.DeriveNextKey(ep, nChild, true)); id = ev.key.GetPubKey().GetID(); addr.Set(id, CChainParams::EXT_KEY_HASH); BOOST_CHECK_MESSAGE(addr.ToString() == "xRfBk2tuann5qTVKyW2HmA9CJZBAE1sRvJ", addr.ToString()); BOOST_CHECK(ep.pubkey == ev.key.GetPubKey()); - - - + + + CStoredExtKey skp = sk; skp.kp = skp.kp.Neutered(); - + CKey k; - + sk.nGenerated = 1; BOOST_CHECK(0 == sk.DeriveNextKey(k, nChild, false)); BOOST_CHECK_MESSAGE(nChild == 1, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(k.GetPubKey()) == "0245a12d2ce075d947b6232b3e424ffa5d2208b6ff69800a1f2501ac6392499bf8", "HexStr(k.GetPubKey()) " << HexStr(k.GetPubKey())); - - + + sk.nGenerated = 2; BOOST_CHECK(0 == sk.DeriveNextKey(k, nChild, false)); BOOST_CHECK_MESSAGE(nChild == 2, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(k.GetPubKey()) == "02f430d7efc4d1ecbac888fb49446ec0b13ec4196512be93054a9b5b30df238910", "HexStr(k.GetPubKey()) " << HexStr(k.GetPubKey())); - + sk.nHGenerated = 2; BOOST_CHECK(0 == sk.DeriveNextKey(k, nChild, true)); BOOST_CHECK_MESSAGE(nChild == 2147483650, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(k.GetPubKey()) == "0355825cbaf4365a2f7015d9c9bae4ecaf9b57a05e063237256f1565b20104c183", "HexStr(k.GetPubKey()) " << HexStr(k.GetPubKey())); - + // - can't derive keys from pubkeys skp.nGenerated = 1; BOOST_CHECK(1 == skp.DeriveNextKey(k, nChild, false)); - + skp.nHGenerated = 1; BOOST_CHECK(1 == skp.DeriveNextKey(k, nChild, true)); - - - + + + CPubKey pk; sk.nGenerated = 1; BOOST_CHECK(0 == sk.DeriveNextKey(pk, nChild, false)); BOOST_CHECK_MESSAGE(nChild == 1, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(pk) == "0245a12d2ce075d947b6232b3e424ffa5d2208b6ff69800a1f2501ac6392499bf8", "HexStr(pk) " << HexStr(pk)); - + sk.nHGenerated = 2; BOOST_CHECK(0 == sk.DeriveNextKey(pk, nChild, true)); BOOST_CHECK_MESSAGE(nChild == 2147483650, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(pk) == "0355825cbaf4365a2f7015d9c9bae4ecaf9b57a05e063237256f1565b20104c183", "HexStr(pk) " << HexStr(pk)); - + skp.nGenerated = 2; BOOST_CHECK(0 == skp.DeriveNextKey(pk, nChild, false)); BOOST_CHECK_MESSAGE(nChild == 2, "nChild " << nChild); BOOST_CHECK_MESSAGE(HexStr(pk) == "02f430d7efc4d1ecbac888fb49446ec0b13ec4196512be93054a9b5b30df238910", "HexStr(pk) " << HexStr(pk)); - + // - can't derive hardened pubkeys from pubkeys skp.nHGenerated = 1; BOOST_CHECK(1 == skp.DeriveNextKey(pk, nChild, true)); - - + + // - CBitcoinAddress tests // CBitcoinAddress always deals in public keys - should never expose a secret in an address - + CExtKeyPair kp, kpT; CTxDestination dest; - - BOOST_CHECK(0 == eKey58.Set58("sdcpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J")); + + BOOST_CHECK(0 == eKey58.Set58("specpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J")); kp = eKey58.GetKey(); CBitcoinAddress addrB(kp); BOOST_CHECK(addrB.IsValid() == true); - + BOOST_CHECK(addr.Set(kp) == true); BOOST_CHECK(addr.IsValid() == true); BOOST_CHECK(addr.IsValid(CChainParams::EXT_SECRET_KEY) == false); BOOST_CHECK(addr.IsValid(CChainParams::EXT_PUBLIC_KEY) == true); - BOOST_CHECK(addr.ToString() == "sdcpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J"); + BOOST_CHECK(addr.ToString() == "specpmphCJNSUos9rNqn6FNi3ztvMW1wft1PVbifvBrwhm6JnhD9yk8rSNFTGfozGbmBsr8vZv9mGYSTfmEMpbfTTMb8TQfj7JRABmvBFKgA2xG8J"); dest = addr.Get(); BOOST_CHECK(dest.type() == typeid(CExtKeyPair)); kpT = boost::get(dest); BOOST_CHECK(kpT == kp); - - + + // - switch to testnet - BOOST_MESSAGE("Entering Testnet"); + BOOST_TEST_MESSAGE("Entering Testnet"); fTestNet = true; SelectParams(CChainParams::TESTNET); - + id = sk.GetID(); BOOST_CHECK(true == addr.Set(id, CChainParams::EXT_KEY_HASH) && addr.IsValid(CChainParams::EXT_KEY_HASH) && addr.GetKeyID(idTest, CChainParams::EXT_KEY_HASH)); - + BOOST_CHECK(id == idTest); BOOST_CHECK_MESSAGE(addr.ToString() == "XCUfUzXMYkXYvP9RVtdzibVVpMP2bhfWRQ", addr.ToString()); - - - BOOST_CHECK(0 == eKey58.Set58("SDCPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp")); + + + BOOST_CHECK(0 == eKey58.Set58("SPECPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp")); kp = eKey58.GetKey(); - CBitcoinAddress addrC("SDCVTZWtnQrSZ1LBHScXxi5amgw4Q1zGaRuAy5S12NAttbx3Bmsm1jDYh1B5P5qTPZaWpUZZ5mmubGTYjXPB1cQ9btJmhDoBLHZnwAGUBVH42gB3"); + CBitcoinAddress addrC("SPECVTZWtnQrSZ1LBHScXxi5amgw4Q1zGaRuAy5S12NAttbx3Bmsm1jDYh1B5P5qTPZaWpUZZ5mmubGTYjXPB1cQ9btJmhDoBLHZnwAGUBVH42gB3"); BOOST_CHECK(addrC.IsValid() == true); BOOST_CHECK(addrC.IsValid(CChainParams::EXT_PUBLIC_KEY) == true); - + BOOST_CHECK(addr.Set(kp) == true); BOOST_CHECK(addr.IsValid() == true); BOOST_CHECK(addr.IsValid(CChainParams::EXT_SECRET_KEY) == false); BOOST_CHECK(addr.IsValid(CChainParams::EXT_PUBLIC_KEY) == true); - BOOST_CHECK(addr.ToString() == "SDCPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp"); + BOOST_CHECK(addr.ToString() == "SPECPTTad968GGU17vZThYUhb4WKgaLQ22ffBVjTnZGGCAcU1vfVFcJEroz4QeZjFZLs5a1dkpZxsKfB2Adnun1axAGuzrfBweXWSxuXu2Wj3AaGp"); dest = addr.Get(); BOOST_CHECK(dest.type() == typeid(CExtKeyPair)); kpT = boost::get(dest); BOOST_CHECK(kpT == kp); - + // -return to mainnet fTestNet = false; SelectParams(CChainParams::MAIN); - + } BOOST_AUTO_TEST_SUITE(extkey_tests) diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 78953d296f..d7566129d7 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include -#include #include #include "util.h" @@ -17,7 +22,7 @@ ResetArgs(const std::string& strArg) // Convert to char*: std::vector vecChar; - BOOST_FOREACH(std::string& s, vecArg) + for (std::string& s : vecArg) vecChar.push_back(s.c_str()); ParseParameters(vecChar.size(), &vecChar[0]); diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 28410f0fed..32cd1521ed 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -1,4 +1,8 @@ - +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT #include "hash.h" #include "util.h" diff --git a/src/test/hmac_tests.cpp b/src/test/hmac_tests.cpp index 68868866aa..e8e5e8bc7f 100644 --- a/src/test/hmac_tests.cpp +++ b/src/test/hmac_tests.cpp @@ -1,4 +1,8 @@ - +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT #include "hash.h" #include "util.h" diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index fd709d0382..22a2f92094 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include diff --git a/src/test/mnemonic_tests.cpp b/src/test/mnemonic_tests.cpp index 274008588f..4ce0fd9940 100644 --- a/src/test/mnemonic_tests.cpp +++ b/src/test/mnemonic_tests.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2015 The ShadowCoin developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #include @@ -29,16 +32,15 @@ using namespace json_spirit; Object read_json_object(const std::string &filename) { - namespace fs = boost::filesystem; fs::path testFile = fs::current_path() / "test" / "data" / filename; - + #ifdef TEST_DATA_DIR if (!fs::exists(testFile)) { testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename; } #endif - + std::ifstream ifs(testFile.string().c_str(), std::ifstream::in); Value v; if (!read_stream(ifs, v)) @@ -49,22 +51,22 @@ Object read_json_object(const std::string &filename) BOOST_ERROR("JSON syntax error in " << filename); return Object(); }; - + if (v.type() != obj_type) { BOOST_ERROR(filename << " does not contain a json object"); return Object(); }; - + return v.get_obj(); }; -// test_shadow --log_level=all --run_test=mnemonic_tests +// test_spectre --log_level=all --run_test=mnemonic_tests void TestMnemonic(int nLanguage, const Array &va) { std::string sError; - + std::string sEntropy = va[0].get_str(); std::string sWords = va[1].get_str(); std::string sSeed; @@ -78,43 +80,43 @@ void TestMnemonic(int nLanguage, const Array &va) sPassphrase = "TREZOR"; sSeed = va[2].get_str(); }; - - //BOOST_MESSAGE("sEntropy " << sEntropy); - //BOOST_MESSAGE("sWords " << sWords); - //BOOST_MESSAGE("sSeed " << sSeed); - //BOOST_MESSAGE("sPassphrase " << sPassphrase); - + + //BOOST_TEST_MESSAGE("sEntropy " << sEntropy); + //BOOST_TEST_MESSAGE("sWords " << sWords); + //BOOST_TEST_MESSAGE("sSeed " << sSeed); + //BOOST_TEST_MESSAGE("sPassphrase " << sPassphrase); + std::vector vEntropy = ParseHex(sEntropy); std::vector vEntropyTest; - + std::string sWordsTest; BOOST_CHECK_MESSAGE(0 == MnemonicEncode(nLanguage, vEntropy, sWordsTest, sError), "MnemonicEncode: " << sError); - + BOOST_CHECK(sWords == sWordsTest); - + BOOST_CHECK_MESSAGE(0 == MnemonicDecode(-1, sWords, vEntropyTest, sError), "MnemonicDecode: " << sError); BOOST_CHECK(vEntropy == vEntropyTest); - + std::vector vSeed = ParseHex(sSeed); std::vector vSeedTest; - + BOOST_CHECK(0 == MnemonicToSeed(sWords, sPassphrase, vSeedTest)); BOOST_CHECK(vSeed == vSeedTest); - //BOOST_MESSAGE("vSeedTest " << HexStr(vSeedTest)); - + //BOOST_TEST_MESSAGE("vSeedTest " << HexStr(vSeedTest)); + if (va.size() > 4) { CExtKey58 eKey58; std::string sExtKey = va[4].get_str(); - + CExtKey ekTest; ekTest.SetMaster(&vSeed[0], vSeed.size()); - + eKey58.SetKey(ekTest, CChainParams::EXT_SECRET_KEY_BTC); BOOST_CHECK(eKey58.ToString() == sExtKey); - - //BOOST_MESSAGE("sExtKey " << sExtKey); - //BOOST_MESSAGE("eKey58 " << eKey58.ToString()); + + //BOOST_TEST_MESSAGE("sExtKey " << sExtKey); + //BOOST_TEST_MESSAGE("eKey58 " << eKey58.ToString()); }; }; @@ -125,20 +127,20 @@ void RunMnemonicTests() std::string sWords = "legals winner thank year wave sausage worth useful legal winner thank yellow"; std::string sError; BOOST_CHECK_MESSAGE(3 == MnemonicDecode(-1, sWords, vEntropy, sError), "MnemonicDecode: " << sError); - + sWords = "winner legal thank year wave sausage worth useful legal winner thank yellow"; BOOST_CHECK_MESSAGE(5 == MnemonicDecode(-1, sWords, vEntropy, sError), "MnemonicDecode: " << sError); - + Object vectors = read_json_object("bip39_vectors.json"); - + int nLanguage; for (Object::size_type i = 0; i < vectors.size(); ++i) - { + { const Pair &pair = vectors[i]; const std::string &name = pair.name_; - - BOOST_MESSAGE("Language: " << name); - + + BOOST_TEST_MESSAGE("Language: " << name); + if (name == "english") nLanguage = WLL_ENGLISH; else @@ -146,30 +148,30 @@ void RunMnemonicTests() nLanguage = WLL_JAPANESE; else nLanguage = -1; - + BOOST_CHECK(nLanguage != -1); - + if (pair.value_.type() != array_type) { - BOOST_MESSAGE("Error, not array."); + BOOST_TEST_MESSAGE("Error, not array."); continue; }; - + const Array &array = pair.value_.get_array(); - - BOOST_FOREACH(const Value &v, array) + + for (const Value& v : array) { if (v.type() != array_type) { - BOOST_MESSAGE("Error, not array."); + BOOST_TEST_MESSAGE("Error, not array."); continue; }; - + const Array &va = v.get_array(); if (va.size() < 3 || va.size() > 5) continue; - + TestMnemonic(nLanguage, va); }; }; diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index 64a6678a73..51baf0f5c4 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include using namespace std; diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index c2d8c22034..73c47fbaf6 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -1,4 +1,8 @@ - +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT #include "key.h" #include "keystore.h" @@ -8,7 +12,6 @@ #include "wallet.h" #include -#include #include using namespace std; @@ -27,7 +30,7 @@ sign_multisig(CScript scriptPubKey, vector keys, CTransaction transaction, CScript result; result << OP_0; // CHECKMULTISIG bug workaround - BOOST_FOREACH(const CKey &key, keys) + for (const CKey& key : keys) { vector vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index e5a7562d97..407fb45f18 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include @@ -57,15 +63,15 @@ BOOST_AUTO_TEST_CASE(netbase_splithost) BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80)); BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80)); BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1)); - BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333)); + BOOST_CHECK(TestSplitHost("127.0.0.1:37347", "127.0.0.1", 37347)); BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1)); - BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333)); + BOOST_CHECK(TestSplitHost("[127.0.0.1]:37347", "127.0.0.1", 37347)); BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1)); - BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333)); - BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333)); - BOOST_CHECK(TestSplitHost("::8333", "::8333", -1)); - BOOST_CHECK(TestSplitHost(":8333", "", 8333)); - BOOST_CHECK(TestSplitHost("[]:8333", "", 8333)); + BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:37347", "::ffff:127.0.0.1", 37347)); + BOOST_CHECK(TestSplitHost("[::]:37347", "::", 37347)); + BOOST_CHECK(TestSplitHost("::37347", "::37347", -1)); + BOOST_CHECK(TestSplitHost(":37347", "", 37347)); + BOOST_CHECK(TestSplitHost("[]:37347", "", 37347)); BOOST_CHECK(TestSplitHost("", "", -1)); } @@ -80,10 +86,10 @@ bool static TestParse(string src, string canon) BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) { BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535")); - BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333")); + BOOST_CHECK(TestParse("127.0.0.1:37347", "127.0.0.1:37347")); BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535")); BOOST_CHECK(TestParse("::", "[::]:65535")); - BOOST_CHECK(TestParse("[::]:8333", "[::]:8333")); + BOOST_CHECK(TestParse("[::]:37347", "[::]:37347")); BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535")); BOOST_CHECK(TestParse(":::", "")); } diff --git a/src/test/other/DoS_tests.cpp b/src/test/other/DoS_tests.cpp index 5e3d765636..c81fdea3d0 100644 --- a/src/test/other/DoS_tests.cpp +++ b/src/test/other/DoS_tests.cpp @@ -1,4 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers // +// SPDX-License-Identifier: MIT + // Unit tests for denial-of-service detection/prevention code // #include @@ -6,7 +11,6 @@ #include // for 'map_list_of()' #include #include -#include #include "main.h" #include "wallet.h" @@ -15,17 +19,18 @@ #include +#define int64 int64_t + // Tests this internal-to-main.cpp method: -extern bool AddOrphanTx(const CDataStream& vMsg); extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans); -extern std::map mapOrphanTransactions; -extern std::map > mapOrphanTransactionsByPrev; +extern std::map mapOrphanTransactions; +extern std::map > mapOrphanTransactionsByPrev; CService ip(uint32_t i) { struct in_addr s; s.s_addr = i; - return CService(CNetAddr(s), GetDefaultPort()); + return CService(CNetAddr(s), Params().GetDefaultPort()); } BOOST_AUTO_TEST_SUITE(DoS_tests) @@ -108,7 +113,7 @@ unsigned int ComputeMaxBits(CBigNum bnTargetLimit, unsigned int nBase, int64_t n // unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) { - return ComputeMaxBits(bnProofOfWorkLimit, nBase, nTime); + return ComputeMaxBits(Params().BnProofOfWorkLimit(), nBase, nTime); } // @@ -117,7 +122,7 @@ unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime) // unsigned int ComputeMinStake(unsigned int nBase, int64_t nTime, unsigned int nBlockTime) { - return ComputeMaxBits(bnProofOfStakeLimit, nBase, nTime); + return ComputeMaxBits(Params().BnProofOfStakeLimit(), nBase, nTime); } static bool CheckNBits(unsigned int nbits1, int64 time1, unsigned int nbits2, int64 time2)\ @@ -148,9 +153,9 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits) // Make sure CheckNBits considers every combination of block-chain-lock-in-points // "sane": - BOOST_FOREACH(const BlockData::value_type& i, chainData) + for (const auto& i : chainData) { - BOOST_FOREACH(const BlockData::value_type& j, chainData) + for (const auto& j : chainData) { BOOST_CHECK(CheckNBits(i.second, i.first, j.second, j.first)); } @@ -172,13 +177,11 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits) CTransaction RandomOrphan() { - std::map::iterator it; + std::map::iterator it; it = mapOrphanTransactions.lower_bound(GetRandHash()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); - const CDataStream* pvMsg = it->second; - CTransaction tx; - CDataStream(*pvMsg) >> tx; + const CTransaction tx = it->second; return tx; } @@ -203,7 +206,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CDataStream ds(SER_DISK, CLIENT_VERSION); ds << tx; - AddOrphanTx(ds); + AddOrphanTx(tx); } // ... and 50 that depend on other orphans: @@ -222,7 +225,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CDataStream ds(SER_DISK, CLIENT_VERSION); ds << tx; - AddOrphanTx(ds); + AddOrphanTx(tx); } // This really-big orphan should be ignored: @@ -248,7 +251,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CDataStream ds(SER_DISK, CLIENT_VERSION); ds << tx; - BOOST_CHECK(!AddOrphanTx(ds)); + BOOST_CHECK(!AddOrphanTx(tx)); } // Test LimitOrphanTxSize() function: @@ -286,7 +289,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig) CDataStream ds(SER_DISK, CLIENT_VERSION); ds << tx; - AddOrphanTx(ds); + AddOrphanTx(tx); } // Create a transaction that depends on orphans: diff --git a/src/test/other/miner_tests.cpp b/src/test/other/miner_tests.cpp index 4558a76a28..d29b7dffe6 100644 --- a/src/test/other/miner_tests.cpp +++ b/src/test/other/miner_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "init.h" @@ -5,6 +11,7 @@ #include "uint256.h" #include "util.h" #include "wallet.h" +#include "miner.h" extern void SHA256Transform(void* pstate, void* pinput, const void* pinit); @@ -53,9 +60,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) CTransaction tx; CScript script; uint256 hash; + int64_t *nFees; // Simple block creation, nothing special yet: - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); +// CreateNewBlock(CWallet *pwallet, bool fProofOfStake, int64_t *pFees) + BOOST_CHECK(pindexBest != nullptr); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); // We can't make transactions until we have inputs // Therefore, load 100 blocks :) @@ -72,13 +82,15 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) txFirst.push_back(new CTransaction(pblock->vtx[0])); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->nNonce = blockinfo[i].nonce; - assert(ProcessBlock(NULL, pblock)); + uint256 hashBlock = pblock->GetHash(); + + assert(ProcessBlock(nullptr, pblock, hashBlock)); pblock->hashPrevBlock = pblock->GetHash(); } delete pblock; // Just to make sure we can still make simple blocks - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); // block sigops > limit: 1000 CHECKMULTISIG + 1 tx.vin.resize(1); @@ -95,7 +107,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, tx); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); @@ -115,14 +127,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, tx); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); // orphan in mempool hash = tx.GetHash(); mempool.addUnchecked(hash, tx); - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); @@ -140,7 +152,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 5900000000LL; hash = tx.GetHash(); mempool.addUnchecked(hash, tx); - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); @@ -151,7 +163,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); mempool.addUnchecked(hash, tx); - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); @@ -169,7 +181,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= 1000000; hash = tx.GetHash(); mempool.addUnchecked(hash,tx); - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); @@ -183,17 +195,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, tx); - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; mempool.clear(); // subsidy changing int nHeight = pindexBest->nHeight; pindexBest->nHeight = 209999; - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; pindexBest->nHeight = 210000; - BOOST_CHECK(pblock = CreateNewBlock(reservekey)); + BOOST_CHECK(pblock = CreateNewBlock(pwalletMain, true, nFees)); delete pblock; pindexBest->nHeight = nHeight; } diff --git a/src/test/other/transaction_tests.cpp b/src/test/other/transaction_tests.cpp index c230458866..122ecb3d12 100644 --- a/src/test/other/transaction_tests.cpp +++ b/src/test/other/transaction_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include #include @@ -24,7 +30,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) // ... where all scripts are stringified scripts. Array tests = read_json("tx_valid.json"); - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); string strTest = write_string(tv, false); @@ -39,7 +45,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) map mapprevOutScriptPubKeys; Array inputs = test[0].get_array(); bool fValid = true; - BOOST_FOREACH(Value& input, inputs) + for (Value& input : inputs) { if (input.type() != array_type) { @@ -91,7 +97,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) // ... where all scripts are stringified scripts. Array tests = read_json("tx_invalid.json"); - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); string strTest = write_string(tv, false); @@ -106,7 +112,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) map mapprevOutScriptPubKeys; Array inputs = test[0].get_array(); bool fValid = true; - BOOST_FOREACH(Value& input, inputs) + for (Value& input : inputs) { if (input.type() != array_type) { diff --git a/src/test/ringsig_tests.cpp b/src/test/ringsig_tests.cpp index f9a65dcf61..9fb2eff0ee 100644 --- a/src/test/ringsig_tests.cpp +++ b/src/test/ringsig_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include @@ -16,7 +22,7 @@ using namespace boost::chrono; -// test_shadow --log_level=all --run_test=ringsig_tests +// test_spectre --log_level=all --run_test=ringsig_tests clock_t totalGenerate; clock_t totalVerify; @@ -28,11 +34,11 @@ void testRingSigs(int nRingSize) uint8_t *pSigc = (uint8_t*) malloc(sizeof(uint8_t) * EC_SECRET_SIZE * nRingSize); uint8_t *pSigr = (uint8_t*) malloc(sizeof(uint8_t) * EC_SECRET_SIZE * nRingSize); - BOOST_REQUIRE(NULL != pPubkeys); - BOOST_REQUIRE(NULL != pSigc); - BOOST_REQUIRE(NULL != pSigr); + BOOST_REQUIRE(nullptr != pPubkeys); + BOOST_REQUIRE(nullptr != pSigc); + BOOST_REQUIRE(nullptr != pSigr); - CKey key[nRingSize]; + CKey *key = new CKey[nRingSize]; for (int i = 0; i < nRingSize; ++i) { key[i].MakeNewKey(true); @@ -44,11 +50,11 @@ void testRingSigs(int nRingSize) uint256 preimage; BOOST_CHECK(1 == RAND_bytes((uint8_t*) preimage.begin(), 32)); - //BOOST_MESSAGE("Txn preimage: " << HexStr(preimage)); + //BOOST_TEST_MESSAGE("Txn preimage: " << HexStr(preimage)); - //BOOST_MESSAGE("nRingSize: " << nRingSize); + //BOOST_TEST_MESSAGE("nRingSize: " << nRingSize); int iSender = GetRandInt(nRingSize); - //BOOST_MESSAGE("sender: " << iSender); + //BOOST_TEST_MESSAGE("sender: " << iSender); ec_secret sSpend; ec_point pkSpend; @@ -72,7 +78,7 @@ void testRingSigs(int nRingSize) int sigSize = EC_COMPRESSED_SIZE + EC_SECRET_SIZE + (EC_SECRET_SIZE + EC_SECRET_SIZE + EC_COMPRESSED_SIZE) * nRingSize; - BOOST_MESSAGE("nRingSize " << nRingSize << ", sigSize: " << bytesReadable(sigSize)); + BOOST_TEST_MESSAGE("nRingSize " << nRingSize << ", sigSize: " << bytesReadable(sigSize)); if (pPubkeys) free(pPubkeys); @@ -87,10 +93,10 @@ void testRingSigABs(int nRingSize) uint8_t *pPubkeys = (uint8_t*) malloc(sizeof(uint8_t) * EC_COMPRESSED_SIZE * nRingSize); uint8_t *pSigS = (uint8_t*) malloc(sizeof(uint8_t) * EC_SECRET_SIZE * nRingSize); - BOOST_CHECK(NULL != pPubkeys); - BOOST_CHECK(NULL != pSigS); + BOOST_CHECK(nullptr != pPubkeys); + BOOST_CHECK(nullptr != pSigS); - CKey key[nRingSize]; + CKey *key = new CKey[nRingSize]; for (int i = 0; i < nRingSize; ++i) { key[i].MakeNewKey(true); @@ -102,10 +108,10 @@ void testRingSigABs(int nRingSize) uint256 preimage; BOOST_CHECK(1 == RAND_bytes((uint8_t*) preimage.begin(), 32)); - //BOOST_MESSAGE("Txn preimage: " << HexStr(preimage)); + //BOOST_TEST_MESSAGE("Txn preimage: " << HexStr(preimage)); int iSender = GetRandInt(nRingSize); - //BOOST_MESSAGE("sender: " << iSender); + //BOOST_TEST_MESSAGE("sender: " << iSender); ec_point pSigC; @@ -131,7 +137,7 @@ void testRingSigABs(int nRingSize) int sigSize = EC_COMPRESSED_SIZE + EC_SECRET_SIZE + EC_SECRET_SIZE + (EC_SECRET_SIZE + EC_COMPRESSED_SIZE) * nRingSize; - BOOST_MESSAGE("nRingSize " << nRingSize << ", sigSize: " << bytesReadable(sigSize)); + BOOST_TEST_MESSAGE("nRingSize " << nRingSize << ", sigSize: " << bytesReadable(sigSize)); if (pPubkeys) free(pPubkeys); @@ -148,33 +154,33 @@ BOOST_AUTO_TEST_CASE(ringsig) BOOST_REQUIRE(0 == initialiseRingSigs()); - BOOST_MESSAGE("testRingSigs"); + BOOST_TEST_MESSAGE("testRingSigs"); for (int k = 1; k < 6; ++k) { - //BOOST_MESSAGE("ringSize " << (k % 126 + 2)); + //BOOST_TEST_MESSAGE("ringSize " << (k % 126 + 2)); testRingSigs(k % 126); }; - BOOST_MESSAGE("ringSize " << 199); + BOOST_TEST_MESSAGE("ringSize " << 199); testRingSigs(199); - BOOST_MESSAGE("totalGenerate " << (double(totalGenerate) / CLOCKS_PER_SEC)); - BOOST_MESSAGE("totalVerify " << (double(totalVerify) / CLOCKS_PER_SEC)); + BOOST_TEST_MESSAGE("totalGenerate " << (double(totalGenerate) / CLOCKS_PER_SEC)); + BOOST_TEST_MESSAGE("totalVerify " << (double(totalVerify) / CLOCKS_PER_SEC)); totalGenerate = 0; totalVerify = 0; - BOOST_MESSAGE("testRingSigABs"); + BOOST_TEST_MESSAGE("testRingSigABs"); for (int k = 2; k < 6; ++k) { - BOOST_MESSAGE("ringSize " << (k % 126)); + BOOST_TEST_MESSAGE("ringSize " << (k % 126)); testRingSigABs(k % 126); }; - BOOST_MESSAGE("ringSize " << 199); + BOOST_TEST_MESSAGE("ringSize " << 199); testRingSigABs(199); - BOOST_MESSAGE("totalGenerate " << (double(totalGenerate) / CLOCKS_PER_SEC)); - BOOST_MESSAGE("totalVerify " << (double(totalVerify) / CLOCKS_PER_SEC)); + BOOST_TEST_MESSAGE("totalGenerate " << (double(totalGenerate) / CLOCKS_PER_SEC)); + BOOST_TEST_MESSAGE("totalVerify " << (double(totalVerify) / CLOCKS_PER_SEC)); BOOST_CHECK(0 == finaliseRingSigs()); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 059f2f2311..6131a791d7 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -1,6 +1,9 @@ -// Copyright (c) 2012-2013 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2012 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "rpcserver.h" #include "rpcclient.h" @@ -15,7 +18,7 @@ using namespace std; using namespace json_spirit; Array -createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL) +createArgs(int nRequired, const char* address1=nullptr, const char* address2=nullptr) { Array result; result.push_back(nRequired); @@ -106,7 +109,7 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign) std::string stestA = std::string("signrawtransaction ")+notsigned+" "+prevout+" "+"["+privkey1+","+privkey2+"]"; r = CallRPC(stestA); - //BOOST_MESSAGE("CallRPC %s\n", stestA.c_str()); + //BOOST_TEST_MESSAGE("CallRPC %s\n", stestA.c_str()); BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true); std::string stestB = std::string("signrawtransaction ")+notsigned+" "+prevout+" "+"["+privkey1+"]"; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 8582ea6607..2a0c90ba75 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -1,9 +1,14 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include #include #include #include -#include #include "../main.h" #include "../script.h" @@ -20,7 +25,7 @@ extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsig static std::vector Serialize(const CScript& s) { - std::vector sSerialized(s); + std::vector sSerialized((std::vector) s); return sSerialized; } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 90a9c1dbc9..537f4db346 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include #include @@ -5,9 +11,9 @@ #include #include #include -#include #include #include +#include "util/fs.h" #include "json/json_spirit_reader_template.h" #include "json/json_spirit_writer_template.h" #include "json/json_spirit_utils.h" @@ -49,7 +55,7 @@ ParseScript(string s) vector words; split(words, s, is_any_of(" \t\n"), token_compress_on); - BOOST_FOREACH(string w, words) + for (const std::string& w : words) { if (all(w, is_digit()) || (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) @@ -89,8 +95,12 @@ ParseScript(string s) Array read_json(const std::string& filename) { - namespace fs = boost::filesystem; fs::path testFile = fs::current_path() / "test" / "data" / filename; +#ifdef CURRENT_PATH + std::stringstream ss; + ss << CURRENT_PATH << "/test/data/" << filename; + testFile = ss.str(); +#endif #ifdef TEST_DATA_DIR if (!fs::exists(testFile)) @@ -129,7 +139,7 @@ BOOST_AUTO_TEST_CASE(script_valid) // scripts. Array tests = read_json("script_valid.json"); - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); string strTest = write_string(tv, false); @@ -153,7 +163,7 @@ BOOST_AUTO_TEST_CASE(script_invalid) // Scripts that should evaluate as invalid Array tests = read_json("script_invalid.json"); - BOOST_FOREACH(Value& tv, tests) + for (Value& tv : tests) { Array test = tv.get_array(); string strTest = write_string(tv, false); @@ -212,7 +222,7 @@ sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transac // and vice-versa) // result << OP_0; - BOOST_FOREACH(CKey key, keys) + for (const CKey& key : keys) { vector vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index 4d40ef844b..994bb45e1b 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -1,6 +1,11 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include -#include #include "script.h" #include "key.h" diff --git a/src/test/smsg_tests.cpp b/src/test/smsg_tests.cpp deleted file mode 100644 index f8624ac6e6..0000000000 --- a/src/test/smsg_tests.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include - -#include - -#include "smessage.h" -#include "init.h" // for pwalletMain - -// test_shadow --log_level=all --run_test=smsg_tests - -BOOST_AUTO_TEST_SUITE(smsg_tests) - -BOOST_AUTO_TEST_CASE(smsg_test) -{ - - const std::string sTestMessage = - "Shadow is a STATE OF THE ART, Proof of Stake crypto currency, utilizing cutting edge technology, " - "such as instant p2p encrypted messaging (ShadowChat), and anonymous dual-key stealth addresses (ShadowSend). " - "Initial distribution was done using Proof of Work and Proof of Stake."; - - fSecMsgEnabled = true; - int rv; - int nKeys = 4; - CWallet keystore; - CKey keyOwn[nKeys]; - for (int i = 0; i < nKeys; i++) - { - keyOwn[i].MakeNewKey(true); - LOCK(keystore.cs_wallet); - keystore.AddKey(keyOwn[i]); - }; - - CKey keyRemote[nKeys]; - for (int i = 0; i < nKeys; i++) - { - keyRemote[i].MakeNewKey(true); - LOCK(keystore.cs_wallet); - keystore.AddKey(keyRemote[i]); // need pubkey - }; - - CWallet *pwalletMainOld = pwalletMain; - UnregisterWallet(pwalletMain); - pwalletMain = &keystore; - RegisterWallet(&keystore); - - for (int i = 0; i < nKeys; i++) - { - SecureMessage smsg; - MessageData msg; - CKeyID kFrom = keyOwn[i].GetPubKey().GetID(); - CKeyID kTo = keyRemote[i].GetPubKey().GetID(); - CKeyID kFail = keyRemote[(i+1) % nKeys].GetPubKey().GetID(); - CBitcoinAddress addrFrom(kFrom); - CBitcoinAddress addrTo(kTo); - CBitcoinAddress addrFail(kFail); - std::string sAddrFrom = addrFrom.ToString(); - std::string sAddrTo = addrFrom.ToString(); - std::string sAddrFail = addrFail.ToString(); - - BOOST_MESSAGE("sAddrFrom " << sAddrFrom); - BOOST_MESSAGE("sAddrTo " << sAddrTo); - - BOOST_CHECK_MESSAGE(0 == (rv = SecureMsgEncrypt(smsg, sAddrFrom, sAddrTo, sTestMessage)), "SecureMsgEncrypt " << rv); - - BOOST_CHECK_MESSAGE(0 == (rv = SecureMsgSetHash((uint8_t*)&smsg, ((uint8_t*)&smsg) + SMSG_HDR_LEN, smsg.nPayload)), "SecureMsgSetHash " << rv); - - BOOST_CHECK_MESSAGE(0 == (rv = SecureMsgValidate((uint8_t*)&smsg, ((uint8_t*)&smsg) + SMSG_HDR_LEN, smsg.nPayload)), "SecureMsgValidate " << rv); - - BOOST_CHECK_MESSAGE(0 == (rv = SecureMsgDecrypt(false, sAddrTo, smsg, msg)), "SecureMsgDecrypt " << rv); - - BOOST_CHECK(msg.vchMessage.size()-1 == sTestMessage.size() - && 0 == memcmp(&msg.vchMessage[0], sTestMessage.data(), msg.vchMessage.size()-1)); - - - BOOST_CHECK_MESSAGE(1 == (rv = SecureMsgDecrypt(false, sAddrFail, smsg, msg)), "SecureMsgDecrypt " << rv); - }; - - - UnregisterWallet(&keystore); - pwalletMain = pwalletMainOld; - RegisterWallet(pwalletMain); - fSecMsgEnabled = false; -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/stealth_tests.cpp b/src/test/stealth_tests.cpp index 1e3a75b55a..250caebbf9 100644 --- a/src/test/stealth_tests.cpp +++ b/src/test/stealth_tests.cpp @@ -1,10 +1,16 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include #include "stealth.h" -// test_shadow --log_level=all --run_test=stealth_tests +// test_spectre --log_level=all --run_test=stealth_tests BOOST_AUTO_TEST_SUITE(stealth_tests) diff --git a/src/test/test_shadow.cpp b/src/test/test_shadow.cpp index 291f532cf9..cf5f2d3778 100644 --- a/src/test/test_shadow.cpp +++ b/src/test/test_shadow.cpp @@ -1,6 +1,12 @@ -#define BOOST_TEST_MODULE Shadow Test Suite +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + +#define BOOST_TEST_MODULE Spectre Test Suite #include -#include +#include "util/fs.h" #include "state.h" #include "db.h" @@ -14,16 +20,16 @@ CClientUIInterface uiInterface; extern bool fPrintToConsole; extern void noui_connect(); -boost::filesystem::path pathTemp; +fs::path pathTemp; struct TestingSetup { TestingSetup() { //fPrintToDebugLog = false; // don't want to write to debug.log file - //pathTemp = GetTempPath() / strprintf("test_shadow_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); - pathTemp = GetTempPath() / "test_shadow"; + //pathTemp = GetTempPath() / strprintf("test_spectre_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + pathTemp = GetTempPath() / "test_spectre"; //printf("pathTemp %s\n", pathTemp.string().c_str()); - boost::filesystem::create_directories(pathTemp); + fs::create_directories(pathTemp); mapArgs["-datadir"] = pathTemp.string(); fDebug = true; @@ -43,7 +49,7 @@ struct TestingSetup { ~TestingSetup() { delete pwalletMain; - pwalletMain = NULL; + pwalletMain = nullptr; bitdb.Flush(true); } }; diff --git a/src/test/uint160_tests.cpp b/src/test/uint160_tests.cpp index 3d0b4a1145..653e3f4760 100644 --- a/src/test/uint160_tests.cpp +++ b/src/test/uint160_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "uint256.h" diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index cd2a3efebd..112b766b43 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "uint256.h" diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 3e62fd578e..33c879512e 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -1,6 +1,11 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include -#include #include "main.h" #include "wallet.h" diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index e11802f891..1e5fce5d9f 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "main.h" @@ -47,7 +53,7 @@ static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, in static void empty_wallet(void) { - BOOST_FOREACH(COutput output, vCoins) + for (const COutput& output : vCoins) delete output.tx; vCoins.clear(); } @@ -64,7 +70,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests) if (!pwallet) { - BOOST_MESSAGE("new wallet failed."); + BOOST_TEST_MESSAGE("new wallet failed."); return; } diff --git a/src/tests.pro b/src/tests.pro new file mode 100644 index 0000000000..2934e1ed77 --- /dev/null +++ b/src/tests.pro @@ -0,0 +1,281 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +TEMPLATE = app +TARGET = spectre_tests +CONFIG += c++14 + +DEFINES += DEBUGGER_CONNECTED +#DEFINES += TEST_TOR +DEFINES += SPECTRE_QT_TEST +DEFINES += CURRENT_PATH=\\\"$$PWD\\\" +DEFINES += BOOST_TEST_DYN_LINK + +QT += testlib webenginewidgets webchannel + +RC_FILE = src.rc + +CONFIG(release, debug|release) { + message( "release" ) + DESTDIR = $$PWD/bin +} +CONFIG(debug, debug|release) { + message( "debug" ) + DESTDIR = $$PWD/bin/debug +} + +macx { + message(Mac build) + include(osx.pri) +} win32 { + message(Win build) + include(win.pri) +} + +HEADERS += \ + $$PWD/json/json_spirit.h \ + $$PWD/json/json_spirit_error_position.h \ + $$PWD/json/json_spirit_reader.h \ + $$PWD/json/json_spirit_reader_template.h \ + $$PWD/json/json_spirit_stream_reader.h \ + $$PWD/json/json_spirit_utils.h \ + $$PWD/json/json_spirit_value.h \ + $$PWD/json/json_spirit_writer.h \ + $$PWD/json/json_spirit_writer_template.h \ + $$PWD/lz4/lz4.h \ + $$PWD/qt/test/uritests.h \ + $$PWD/qt/aboutdialog.h \ + $$PWD/qt/addresstablemodel.h \ + $$PWD/qt/askpassphrasedialog.h \ + $$PWD/qt/bitcoinaddressvalidator.h \ + $$PWD/qt/bitcoinamountfield.h \ + $$PWD/qt/bitcoinunits.h \ + $$PWD/qt/bridgetranslations.h \ + $$PWD/qt/clientmodel.h \ + $$PWD/qt/coincontroldialog.h \ + $$PWD/qt/coincontroltreewidget.h \ + $$PWD/qt/csvmodelwriter.h \ + $$PWD/qt/editaddressdialog.h \ + $$PWD/qt/guiconstants.h \ + $$PWD/qt/guiutil.h \ + $$PWD/qt/messagemodel.h \ + $$PWD/qt/monitoreddatamapper.h \ + $$PWD/qt/notificator.h \ + $$PWD/qt/optionsmodel.h \ + $$PWD/qt/paymentserver.h \ + $$PWD/qt/peertablemodel.h \ + $$PWD/qt/qvalidatedlineedit.h \ + $$PWD/qt/qvaluecombobox.h \ + $$PWD/qt/rpcconsole.h \ + $$PWD/qt/scicon.h \ + $$PWD/qt/spectrebridge.h \ + $$PWD/qt/spectregui.h \ + $$PWD/qt/trafficgraphwidget.h \ + $$PWD/qt/transactiondesc.h \ + $$PWD/qt/transactionrecord.h \ + $$PWD/qt/transactiontablemodel.h \ + $$PWD/qt/walletmodel.h \ + $$PWD/wordlists/chinese_simplified.h \ + $$PWD/wordlists/chinese_traditional.h \ + $$PWD/wordlists/english.h \ + $$PWD/wordlists/french.h \ + $$PWD/wordlists/japanese.h \ + $$PWD/wordlists/spanish.h \ + $$PWD/xxhash/xxhash.h \ + $$PWD/alert.h \ + $$PWD/allocators.h \ + $$PWD/anonymize.h \ + $$PWD/base58.h \ + $$PWD/bignum.h \ + $$PWD/bloom.h \ + $$PWD/chainparams.h \ + $$PWD/chainparamsseeds.h \ + $$PWD/checkpoints.h \ + $$PWD/clientversion.h \ + $$PWD/coincontrol.h \ + $$PWD/compat.h \ + $$PWD/core.h \ + $$PWD/crypter.h \ + $$PWD/db.h \ + $$PWD/eckey.h \ + $$PWD/extkey.h \ + $$PWD/hash.h \ + $$PWD/init.h \ + $$PWD/kernel.h \ + $$PWD/key.h \ + $$PWD/keystore.h \ + $$PWD/main.h \ + $$PWD/miner.h \ + $$PWD/mruset.h \ + $$PWD/net.h \ + $$PWD/netbase.h \ + $$PWD/pbkdf2.h \ + $$PWD/protocol.h \ + $$PWD/ringsig.h \ + $$PWD/rpcclient.h \ + $$PWD/rpcprotocol.h \ + $$PWD/rpcserver.h \ + $$PWD/script.h \ + $$PWD/scrypt.h \ + $$PWD/serialize.h \ + $$PWD/smessage.h \ + $$PWD/state.h \ + $$PWD/stealth.h \ + $$PWD/strlcpy.h \ + $$PWD/sync.h \ + $$PWD/threadsafety.h \ + $$PWD/tinyformat.h \ + $$PWD/txdb-leveldb.h \ + $$PWD/txdb.h \ + $$PWD/txmempool.h \ + $$PWD/types.h \ + $$PWD/ui_interface.h \ + $$PWD/uint256.h \ + $$PWD/util.h \ + $$PWD/version.h \ + $$PWD/wallet.h \ + $$PWD/walletdb.h \ + $$PWD/addrman.h \ + +SOURCES += \ + $$PWD/json/json_spirit_reader.cpp \ + $$PWD/json/json_spirit_value.cpp \ + $$PWD/json/json_spirit_writer.cpp \ + $$PWD/qt/test/test_main.cpp \ + $$PWD/qt/test/uritests.cpp \ + $$PWD/qt/aboutdialog.cpp \ + $$PWD/qt/addresstablemodel.cpp \ + $$PWD/qt/askpassphrasedialog.cpp \ + $$PWD/qt/bitcoinaddressvalidator.cpp \ + $$PWD/qt/bitcoinamountfield.cpp \ + $$PWD/qt/bitcoinstrings.cpp \ + $$PWD/qt/bitcoinunits.cpp \ + $$PWD/qt/clientmodel.cpp \ + $$PWD/qt/coincontroldialog.cpp \ + $$PWD/qt/coincontroltreewidget.cpp \ + $$PWD/qt/csvmodelwriter.cpp \ + $$PWD/qt/editaddressdialog.cpp \ + $$PWD/qt/guiutil.cpp \ + $$PWD/qt/messagemodel.cpp \ + $$PWD/qt/monitoreddatamapper.cpp \ + $$PWD/qt/notificator.cpp \ + $$PWD/qt/optionsmodel.cpp \ + $$PWD/qt/paymentserver.cpp \ + $$PWD/qt/peertablemodel.cpp \ + $$PWD/qt/qvalidatedlineedit.cpp \ + $$PWD/qt/qvaluecombobox.cpp \ + $$PWD/qt/rpcconsole.cpp \ + $$PWD/qt/scicon.cpp \ + $$PWD/qt/spectre.cpp \ + $$PWD/qt/spectrebridge.cpp \ + $$PWD/qt/spectregui.cpp \ + $$PWD/qt/trafficgraphwidget.cpp \ + $$PWD/qt/transactiondesc.cpp \ + $$PWD/qt/transactionrecord.cpp \ + $$PWD/qt/transactiontablemodel.cpp \ + $$PWD/qt/walletmodel.cpp \ + $$PWD/test/other/DoS_tests.cpp \ +# $$PWD/test/other/miner_tests.cpp \ + $$PWD/test/other/transaction_tests.cpp \ + $$PWD/test/accounting_tests.cpp \ + $$PWD/test/allocator_tests.cpp \ + $$PWD/test/base32_tests.cpp \ + $$PWD/test/base58_tests.cpp \ + $$PWD/test/base64_tests.cpp \ + $$PWD/test/basic_tests.cpp \ + $$PWD/test/bignum_tests.cpp \ + $$PWD/test/bip32_tests.cpp \ + $$PWD/test/Checkpoints_tests.cpp \ + $$PWD/test/extkey_tests.cpp \ + $$PWD/test/getarg_tests.cpp \ + $$PWD/test/hash_tests.cpp \ + $$PWD/test/hmac_tests.cpp \ + $$PWD/test/key_tests.cpp \ + $$PWD/test/mnemonic_tests.cpp \ + $$PWD/test/mruset_tests.cpp \ + $$PWD/test/multisig_tests.cpp \ + $$PWD/test/netbase_tests.cpp \ + $$PWD/test/ringsig_tests.cpp \ + $$PWD/test/rpc_tests.cpp \ + $$PWD/test/script_P2SH_tests.cpp \ + $$PWD/test/script_tests.cpp \ + $$PWD/test/sigopcount_tests.cpp \ + $$PWD/test/smsg_tests.cpp \ + $$PWD/test/stealth_tests.cpp \ +# $$PWD/test/test_shadow.cpp \ + $$PWD/test/uint160_tests.cpp \ + $$PWD/test/uint256_tests.cpp \ + $$PWD/test/util_tests.cpp \ + $$PWD/test/wallet_tests.cpp \ + $$PWD/alert.cpp \ + $$PWD/anonymize.cpp \ + $$PWD/bloom.cpp \ + $$PWD/chainparams.cpp \ + $$PWD/checkpoints.cpp \ + $$PWD/core.cpp \ + $$PWD/crypter.cpp \ + $$PWD/db.cpp \ + $$PWD/eckey.cpp \ + $$PWD/extkey.cpp \ + $$PWD/hash.cpp \ + $$PWD/init.cpp \ + $$PWD/kernel.cpp \ + $$PWD/key.cpp \ + $$PWD/keystore.cpp \ + $$PWD/main.cpp \ + $$PWD/miner.cpp \ + $$PWD/net.cpp \ + $$PWD/netbase.cpp \ + $$PWD/noui.cpp \ + $$PWD/pbkdf2.cpp \ + $$PWD/protocol.cpp \ + $$PWD/ringsig.cpp \ + $$PWD/rpcblockchain.cpp \ + $$PWD/rpcclient.cpp \ + $$PWD/rpcdump.cpp \ + $$PWD/rpcextkey.cpp \ + $$PWD/rpcmining.cpp \ + $$PWD/rpcmnemonic.cpp \ + $$PWD/rpcnet.cpp \ + $$PWD/rpcprotocol.cpp \ + $$PWD/rpcrawtransaction.cpp \ + $$PWD/rpcserver.cpp \ + $$PWD/rpcsmessage.cpp \ + $$PWD/rpcwallet.cpp \ + $$PWD/script.cpp \ + $$PWD/scrypt.cpp \ + $$PWD/smessage.cpp \ +# $$PWD/spectrecoind.cpp \ + $$PWD/state.cpp \ + $$PWD/stealth.cpp \ + $$PWD/sync.cpp \ + $$PWD/txdb-leveldb.cpp \ + $$PWD/txmempool.cpp \ + $$PWD/util.cpp \ + $$PWD/version.cpp \ + $$PWD/wallet.cpp \ + $$PWD/walletdb.cpp \ + $$PWD/lz4/lz4.c \ + $$PWD/xxhash/xxhash.c \ + $$PWD/addrman.cpp \ + + +#levelDB additional headers +INCLUDEPATH += $$PWD/../leveldb/helpers +#find . -type d +INCLUDEPATH += $$PWD $$PWD/obj $$PWD/test $$PWD/test/other $$PWD/test/data $$PWD/wordlists $$PWD/qt $$PWD/qt/res $$PWD/qt/res/css $$PWD/qt/res/css/fonts $$PWD/qt/res/images $$PWD/qt/res/images/avatars $$PWD/qt/res/icons $$PWD/qt/res/assets $$PWD/qt/res/assets/css $$PWD/qt/res/assets/plugins $$PWD/qt/res/assets/plugins/md5 $$PWD/qt/res/assets/plugins/identicon $$PWD/qt/res/assets/plugins/bootstrapv3 $$PWD/qt/res/assets/plugins/bootstrapv3/css $$PWD/qt/res/assets/plugins/bootstrapv3/js $$PWD/qt/res/assets/plugins/bootstrapv3/fonts $$PWD/qt/res/assets/plugins/framework $$PWD/qt/res/assets/plugins/markdown $$PWD/qt/res/assets/plugins/shajs $$PWD/qt/res/assets/plugins/pnglib $$PWD/qt/res/assets/plugins/iscroll $$PWD/qt/res/assets/plugins/jquery $$PWD/qt/res/assets/plugins/classie $$PWD/qt/res/assets/plugins/pace $$PWD/qt/res/assets/plugins/contextMenu $$PWD/qt/res/assets/plugins/jquery-scrollbar $$PWD/qt/res/assets/plugins/jdenticon $$PWD/qt/res/assets/plugins/qrcode $$PWD/qt/res/assets/plugins/emojione $$PWD/qt/res/assets/plugins/emojione/assets $$PWD/qt/res/assets/plugins/emojione/assets/svg $$PWD/qt/res/assets/plugins/emojione/assets/css $$PWD/qt/res/assets/plugins/jquery-transit $$PWD/qt/res/assets/plugins/footable $$PWD/qt/res/assets/plugins/jquery-ui $$PWD/qt/res/assets/plugins/jquery-ui/images $$PWD/qt/res/assets/js $$PWD/qt/res/assets/js/pages $$PWD/qt/res/assets/img $$PWD/qt/res/assets/img/progress $$PWD/qt/res/assets/img/avatars $$PWD/qt/res/assets/icons $$PWD/qt/res/assets/fonts $$PWD/qt/res/assets/fonts/Framework-icon $$PWD/qt/res/assets/fonts/FontAwesome $$PWD/qt/res/assets/fonts/Montserrat $$PWD/qt/res/assets/fonts/Footable $$PWD/qt/res/src $$PWD/qt/locale $$PWD/qt/forms $$PWD/qt/test $$PWD/lz4 $$PWD/json $$PWD/xxhash $$PWD/obj-test + + +FORMS += \ + $$PWD/qt/forms/aboutdialog.ui \ + $$PWD/qt/forms/askpassphrasedialog.ui \ + $$PWD/qt/forms/coincontroldialog.ui \ + $$PWD/qt/forms/editaddressdialog.ui \ + $$PWD/qt/forms/rpcconsole.ui \ + $$PWD/qt/forms/transactiondescdialog.ui + +RESOURCES += \ + ../spectre.qrc diff --git a/src/threadsafety.h b/src/threadsafety.h index 176060ac65..9636e272ef 100644 --- a/src/threadsafety.h +++ b/src/threadsafety.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_THREADSAFETY_H #define BITCOIN_THREADSAFETY_H diff --git a/src/tinyformat.h b/src/tinyformat.h index 73d49a1fe4..0e809a796d 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 2011, Chris Foster [chris42f (at) gmail (d0t) com] +// +// SPDX-License-Identifier: BSL-1.0 + // tinyformat.h // Copyright (C) 2011, Chris Foster [chris42f (at) gmail (d0t) com] // @@ -118,6 +122,7 @@ namespace tfm = tinyformat; //------------------------------------------------------------------------------ // Implementation details. +#undef NDEBUG #include #include #include @@ -783,23 +788,27 @@ inline const char* FormatIterator::streamStateFromFormat(std::ostream& out, break; case 'X': out.setf(std::ios::uppercase); + // fallthrough case 'x': case 'p': out.setf(std::ios::hex, std::ios::basefield); intConversion = true; break; case 'E': out.setf(std::ios::uppercase); + // fallthrough case 'e': out.setf(std::ios::scientific, std::ios::floatfield); out.setf(std::ios::dec, std::ios::basefield); break; case 'F': out.setf(std::ios::uppercase); + // fallthrough case 'f': out.setf(std::ios::fixed, std::ios::floatfield); break; case 'G': out.setf(std::ios::uppercase); + // fallthrough case 'g': out.setf(std::ios::dec, std::ios::basefield); // As in boost::format, let stream decide float format. diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp index b846675451..8481ee5d34 100644 --- a/src/txdb-leveldb.cpp +++ b/src/txdb-leveldb.cpp @@ -1,18 +1,19 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include #include -#include -#include +#include "util/fs.h" #include #include #include -#include #include "kernel.h" #include "checkpoints.h" @@ -21,13 +22,13 @@ #include "main.h" using namespace std; -namespace fs = boost::filesystem; leveldb::DB *txdb; // global pointer for LevelDB object instance -static leveldb::Options GetOptions() { +static leveldb::Options GetOpenOptions() { leveldb::Options options; int nCacheSizeMB = GetArg("-dbcache", 25); + options.create_if_missing = true; options.block_cache = leveldb::NewLRUCache(nCacheSizeMB * 1048576); options.filter_policy = leveldb::NewBloomFilterPolicy(10); return options; @@ -39,9 +40,8 @@ static void init_blockindex(leveldb::Options& options, bool fRemoveOld = false) fs::path directory = GetDataDir() / "txleveldb"; if (fRemoveOld) - fs::remove_all(directory); // remove directory + fs::remove_all(directory); - fs::create_directory(directory); LogPrintf("Opening LevelDB in %s\n", directory.string().c_str()); leveldb::Status status = leveldb::DB::Open(options, directory.string(), &txdb); if (!status.ok()) { @@ -52,22 +52,17 @@ static void init_blockindex(leveldb::Options& options, bool fRemoveOld = false) // CDB subclasses are created and destroyed VERY OFTEN. That's why // we shouldn't treat this as a free operations. CTxDB::CTxDB(const char* pszMode) + : pdb(nullptr), activeBatch(nullptr), fReadOnly(!strchr(pszMode, '+') && !strchr(pszMode, 'w')), nVersion(0) { assert(pszMode); - activeBatch = NULL; - fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); if (txdb) { pdb = txdb; return; } - bool fCreate = strchr(pszMode, 'c'); - - options = GetOptions(); - options.create_if_missing = fCreate; - - init_blockindex(options); // Init directory + openOptions = GetOpenOptions(); + init_blockindex(openOptions); pdb = txdb; LogPrintf("Opened LevelDB successfully\n"); @@ -76,18 +71,25 @@ CTxDB::CTxDB(const char* pszMode) void CTxDB::Close() { delete txdb; - txdb = pdb = NULL; - delete options.filter_policy; - options.filter_policy = NULL; - delete options.block_cache; - options.block_cache = NULL; - + txdb = pdb = nullptr; if (activeBatch) { delete activeBatch; - activeBatch = NULL; - }; + activeBatch = nullptr; + } + + if (openOptions.block_cache) + { + delete openOptions.block_cache; + openOptions.block_cache = nullptr; + } + + if (openOptions.filter_policy) + { + openOptions.filter_policy = nullptr; + } + } bool CTxDB::TxnBegin() @@ -100,9 +102,9 @@ bool CTxDB::TxnBegin() bool CTxDB::TxnCommit() { assert(activeBatch); - leveldb::Status status = pdb->Write(leveldb::WriteOptions(), activeBatch); + leveldb::Status status = pdb->Write(GetWriteOptions(), activeBatch); delete activeBatch; - activeBatch = NULL; + activeBatch = nullptr; if (!status.ok()) { LogPrintf("LevelDB batch commit failure: %s\n", status.ToString()); return false; @@ -119,7 +121,7 @@ class CBatchScanner : public leveldb::WriteBatch::Handler { CBatchScanner() : foundEntry(false) {} - virtual void Put(const leveldb::Slice& key, const leveldb::Slice& value) { + void Put(const leveldb::Slice& key, const leveldb::Slice& value) override { if (key.ToString() == needle) { foundEntry = true; *deleted = false; @@ -127,7 +129,7 @@ class CBatchScanner : public leveldb::WriteBatch::Handler { } } - virtual void Delete(const leveldb::Slice& key) { + void Delete(const leveldb::Slice& key) override { if (key.ToString() == needle) { foundEntry = true; *deleted = true; @@ -184,11 +186,25 @@ int CTxDB::RecreateDB() LogPrintf("Recreating TXDB.\n"); delete txdb; - txdb = pdb = NULL; - delete activeBatch; - activeBatch = NULL; + txdb = pdb = nullptr; + + if (activeBatch) + { + delete activeBatch; + activeBatch = nullptr; + } + + if (openOptions.block_cache) { + delete openOptions.block_cache; + openOptions.block_cache = nullptr; + } - init_blockindex(options, true); // Remove directory and create new database + if (openOptions.filter_policy) { + openOptions.filter_policy = nullptr; + } + + openOptions = GetOpenOptions(); + init_blockindex(openOptions, true); // Remove directory and create new database pdb = txdb; bool fTmp = fReadOnly; @@ -229,12 +245,27 @@ bool CTxDB::EraseAnonOutput(CPubKey& pkCoin) return Erase(make_pair(string("ao"), pkCoin)); }; -bool CTxDB::EraseRange(const std::string &sPrefix, uint32_t &nAffected) +bool CTxDB::WriteCompromisedAnonHeights(std::map>& mapCompromisedHeights) +{ + return Write(string("compromisedanonheights"), mapCompromisedHeights); +}; + +bool CTxDB::ReadCompromisedAnonHeights(std::map>& mapCompromisedHeights) +{ + return Read(string("compromisedanonheights"), mapCompromisedHeights); +}; + +bool CTxDB::EraseCompromisedAnonHeights() +{ + return Erase(string("compromisedanonheights")); +}; + +bool CTxDB::EraseRange(const std::string &sPrefix, uint32_t &nAffected, std::function funcProgress) { TxnBegin(); - leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); + leveldb::Iterator *iterator = pdb->NewIterator(GetReadOptions()); if (!iterator) LogPrintf("EraseRange(%s) - NewIterator failed.\n", sPrefix.c_str()); @@ -253,8 +284,7 @@ bool CTxDB::EraseRange(const std::string &sPrefix, uint32_t &nAffected) iterator->Seek(leveldb::Slice((const char*)data, nLenPrefix+1)); - leveldb::WriteOptions writeOptions; - writeOptions.sync = true; + leveldb::WriteOptions writeOptions = GetWriteOptions(); while (iterator->Valid()) { if (iterator->key().size() < nLenPrefix+1 @@ -266,6 +296,8 @@ bool CTxDB::EraseRange(const std::string &sPrefix, uint32_t &nAffected) if (!s.ok()) LogPrintf("EraseRange(%s) - Delete failed.\n", sPrefix.c_str()); + if (funcProgress && nAffected % 100 == 0) funcProgress(nAffected); + nAffected++; iterator->Next(); }; @@ -388,7 +420,7 @@ bool CTxDB::WriteBestInvalidTrust(CBigNum bnBestInvalidTrust) static CBlockIndex *InsertBlockIndex(uint256 hash) { if (hash == 0) - return NULL; + return nullptr; // Return existing map::iterator mi = mapBlockIndex.find(hash); @@ -405,7 +437,7 @@ static CBlockIndex *InsertBlockIndex(uint256 hash) return pindexNew; } -bool CTxDB::LoadBlockIndex() +bool CTxDB::LoadBlockIndex(std::function funcValidate, std::function funcProgress) { if (nNodeMode != NT_FULL) return 0; @@ -421,16 +453,17 @@ bool CTxDB::LoadBlockIndex() // The block index is an in-memory structure that maps hashes to on-disk // locations where the contents of the block can be found. Here, we scan it // out of the DB and into mapBlockIndex. - leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); + leveldb::Iterator *iterator = pdb->NewIterator(GetReadOptions()); // Seek to start key. CDataStream ssStartKey(SER_DISK, CLIENT_VERSION); ssStartKey << make_pair(string("bidx"), uint256(0)); iterator->Seek(ssStartKey.str()); - int count = 0; + uint32_t count = 0; // Now read each entry. while (iterator->Valid()) { + if (funcProgress && count != 0 && count % 10000 == 0) funcProgress(0, count); count++; boost::this_thread::interruption_point(); // Unpack keys and values. @@ -474,7 +507,7 @@ bool CTxDB::LoadBlockIndex() pindexNew->nNonce = diskindex.nNonce; // Watch for genesis block - if (pindexGenesisBlock == NULL && blockHash == Params().HashGenesisBlock()) + if (pindexGenesisBlock == nullptr && blockHash == Params().HashGenesisBlock()) pindexGenesisBlock = pindexNew; if (!pindexNew->CheckIndex()) { @@ -482,6 +515,9 @@ bool CTxDB::LoadBlockIndex() return error("LoadBlockIndex() : CheckIndex failed at %d", pindexNew->nHeight); } + if (funcValidate && !funcValidate(pindexNew)) + return false; + // NovaCoin: build setStakeSeen if (pindexNew->IsProofOfStake()) setStakeSeen.insert(make_pair(pindexNew->prevoutStake, pindexNew->nStakeTime)); @@ -489,13 +525,14 @@ bool CTxDB::LoadBlockIndex() iterator->Next(); } delete iterator; + if (funcProgress) funcProgress(0, count); boost::this_thread::interruption_point(); // Load hashBestChain pointer to end of best chain if (!ReadHashBestChain(hashBestChain)) { - if (pindexGenesisBlock == NULL) + if (pindexGenesisBlock == nullptr) return true; return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); } @@ -504,18 +541,24 @@ bool CTxDB::LoadBlockIndex() pindexBest = mapBlockIndex[hashBestChain]; nBestHeight = pindexBest->nHeight; + chainActive.SetTip(pindexBest); // Calculate nChainTrust vector > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for (const auto& item : mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(make_pair(pindex->nHeight, pindex)); } sort(vSortedByHeight.begin(), vSortedByHeight.end()); - BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + + count = 0; + for (const auto& item : vSortedByHeight) { + if (funcProgress && count != 0 && count % 100000 == 0) funcProgress(1, count); + count++; + CBlockIndex* pindex = item.second; uint256 blockhash = pindex->GetBlockHash(); @@ -535,6 +578,7 @@ bool CTxDB::LoadBlockIndex() pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + pindex->GetBlockTrust(); } + if (funcProgress) funcProgress(1, count); nBestChainTrust = pindexBest->nChainTrust; @@ -555,13 +599,16 @@ bool CTxDB::LoadBlockIndex() if (nCheckDepth > nBestHeight) nCheckDepth = nBestHeight; LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); - CBlockIndex* pindexFork = NULL; + CBlockIndex* pindexFork = nullptr; map, CBlockIndex*> mapBlockPos; + + if (funcProgress) funcProgress(2, nCheckDepth); for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { boost::this_thread::interruption_point(); if (pindex->nHeight < nBestHeight-nCheckDepth) break; + CBlock block; if (!block.ReadFromDisk(pindex)) return error("LoadBlockIndex() : block.ReadFromDisk failed"); @@ -577,8 +624,7 @@ bool CTxDB::LoadBlockIndex() { pair pos = make_pair(pindex->nFile, pindex->nBlockPos); mapBlockPos[pos] = pindex; - BOOST_FOREACH(const CTransaction &tx, block.vtx) - { + for (const CTransaction& tx : block.vtx) { uint256 hashTx = tx.GetHash(); CTxIndex txindex; if (ReadTxIndex(hashTx, txindex)) @@ -604,7 +650,7 @@ bool CTxDB::LoadBlockIndex() unsigned int nOutput = 0; if (nCheckLevel>3) { - BOOST_FOREACH(const CDiskTxPos &txpos, txindex.vSpent) + for (const CDiskTxPos& txpos : txindex.vSpent) { if (!txpos.IsNull()) { @@ -631,9 +677,10 @@ bool CTxDB::LoadBlockIndex() else { bool fFound = false; - BOOST_FOREACH(const CTxIn &txin, txSpend.vin) + for (const CTxIn& txin : txSpend.vin) { if (txin.prevout.hash == hashTx && txin.prevout.n == nOutput) fFound = true; + } if (!fFound) { LogPrintf("LoadBlockIndex(): *** spending transaction of %s:%i does not spend it\n", hashTx.ToString(), nOutput); @@ -649,7 +696,7 @@ bool CTxDB::LoadBlockIndex() // check level 5: check whether all prevouts are marked spent if (nCheckLevel>4) { - BOOST_FOREACH(const CTxIn &txin, tx.vin) + for (const CTxIn& txin : tx.vin) { CTxIndex txindex; if (ReadTxIndex(txin.prevout.hash, txindex)) @@ -697,7 +744,7 @@ bool CTxDB::LoadBlockThinIndex() CDiskBlockThinIndex diskindex; map::iterator mi; - CBlockThinIndex* pIndexLast = NULL; + CBlockThinIndex* pIndexLast = nullptr; while (hashNext != 0) { @@ -738,7 +785,7 @@ bool CTxDB::LoadBlockThinIndex() // -- genesis block will always be first - if (pindexGenesisBlockThin == NULL) + if (pindexGenesisBlockThin == nullptr) { pindexGenesisBlockThin = pindexNew; pindexRear = pindexGenesisBlockThin; @@ -758,7 +805,7 @@ bool CTxDB::LoadBlockThinIndex() const uint256* pRemHash = pindexRear->phashBlock; pindexRear = pindexRear->pnext; - pindexRear->pprev = NULL; + pindexRear->pprev = nullptr; std::map::iterator mi = mapBlockThinIndex.find(*pRemHash); @@ -776,7 +823,7 @@ bool CTxDB::LoadBlockThinIndex() // -- load hashBestChain pointer to end of best chain if (!ReadHashBestHeaderChain(hashBestChain)) { - if (pindexGenesisBlockThin == NULL) + if (pindexGenesisBlockThin == nullptr) return true; return error("CTxDB::LoadBlockThinIndex() : hashBestChain not loaded"); }; diff --git a/src/txdb-leveldb.h b/src/txdb-leveldb.h index 43dcac1181..1ec95a39bf 100644 --- a/src/txdb-leveldb.h +++ b/src/txdb-leveldb.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2012 The Bitcoin Developers. -// Authored by Google, Inc. -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers. +// SPDX-FileCopyrightText: © Google, Inc. +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_LEVELDB_H #define BITCOIN_LEVELDB_H @@ -64,14 +67,14 @@ class CTxDB void Close(); private: - leveldb::DB *pdb; // Points to the global instance. + leveldb::DB *pdb = nullptr; // Points to the global instance. // A batch stores up writes and deletes for atomic application. When this - // field is non-NULL, writes/deletes go there instead of directly to disk. - leveldb::WriteBatch *activeBatch; - leveldb::Options options; - bool fReadOnly; - int nVersion; + // field is non-nullptr, writes/deletes go there instead of directly to disk. + leveldb::WriteBatch *activeBatch = nullptr; + leveldb::Options openOptions; + bool fReadOnly = false; + int nVersion = 0; protected: // Returns true and sets (value,false) if activeBatch contains the given key @@ -102,7 +105,7 @@ class CTxDB if (readFromDb) { - leveldb::Status status = pdb->Get(leveldb::ReadOptions(), + leveldb::Status status = pdb->Get(GetReadOptions(), ssKey.str(), &strValue); if (!status.ok()) { @@ -144,7 +147,7 @@ class CTxDB return true; }; - leveldb::Status status = pdb->Put(leveldb::WriteOptions(), ssKey.str(), ssValue.str()); + leveldb::Status status = pdb->Put(GetWriteOptions(), ssKey.str(), ssValue.str()); if (!status.ok()) { LogPrintf("LevelDB write failure: %s\n", status.ToString().c_str()); @@ -171,7 +174,7 @@ class CTxDB return true; }; - leveldb::Status status = pdb->Delete(leveldb::WriteOptions(), ssKey.str()); + leveldb::Status status = pdb->Delete(GetWriteOptions(), ssKey.str()); return (status.ok() || status.IsNotFound()); } @@ -192,7 +195,7 @@ class CTxDB } } - leveldb::Status status = pdb->Get(leveldb::ReadOptions(), ssKey.str(), &unused); + leveldb::Status status = pdb->Get(GetReadOptions(), ssKey.str(), &unused); return status.IsNotFound() == false; } @@ -203,7 +206,7 @@ class CTxDB bool TxnAbort() { delete activeBatch; - activeBatch = NULL; + activeBatch = nullptr; return true; } @@ -223,6 +226,18 @@ class CTxDB return Write(std::string("version"), nVersion); } + static leveldb::ReadOptions GetReadOptions() + { + leveldb::ReadOptions readOptions; + return readOptions; + } + + static leveldb::WriteOptions GetWriteOptions() + { + leveldb::WriteOptions writeOptions; + writeOptions.sync = true; + return writeOptions; + } int CheckVersion(); int RecreateDB(); @@ -235,7 +250,11 @@ class CTxDB bool ReadAnonOutput(CPubKey& pkCoin, CAnonOutput& ao); bool EraseAnonOutput(CPubKey& pkCoin); - bool EraseRange(const std::string &sPrefix, uint32_t &nAffected); + bool WriteCompromisedAnonHeights(std::map>& mapCompromisedHeights); + bool ReadCompromisedAnonHeights(std::map>& mapCompromisedHeights); + bool EraseCompromisedAnonHeights(); + + bool EraseRange(const std::string &sPrefix, uint32_t &nAffected, std::function funcProgress = nullptr); bool ReadTxIndex(uint256 hash, CTxIndex& txindex); bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex); @@ -260,7 +279,7 @@ class CTxDB bool WriteSyncCheckpoint(uint256 hashCheckpoint); bool ReadCheckpointPubKey(std::string& strPubKey); bool WriteCheckpointPubKey(const std::string& strPubKey); - bool LoadBlockIndex(); + bool LoadBlockIndex(std::function funcValidate = nullptr, std::function funcProgress = nullptr); bool LoadBlockThinIndex(); private: bool LoadBlockIndexGuts(); diff --git a/src/txdb.h b/src/txdb.h index a8e9f5b585..d9f5d5301e 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_TXDB_H #define BITCOIN_TXDB_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index b2cbb37fdb..c9fb93a4a8 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1,7 +1,10 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT #include "txmempool.h" @@ -41,10 +44,10 @@ bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive) remove(*it->second.ptx, true); }; }; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) mapNextTx.erase(txin.prevout); mapTx.erase(hash); - + if (tx.nVersion == ANON_TXN_VERSION) { // -- remove key images @@ -54,14 +57,14 @@ bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive) if (!txin.IsAnonInput()) continue; - + ec_point vchImage; txin.ExtractKeyImage(vchImage); - + mapKeyImage.erase(vchImage); }; }; - + nTransactionsUpdated++; }; } @@ -72,7 +75,7 @@ bool CTxMemPool::removeConflicts(const CTransaction &tx) { // Remove transactions which depend on inputs of tx, recursively LOCK(cs); - BOOST_FOREACH(const CTxIn &txin, tx.vin) + for (const CTxIn& txin : tx.vin) { std::map::iterator it = mapNextTx.find(txin.prevout); if (it != mapNextTx.end()) @@ -113,3 +116,9 @@ bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const result = i->second; return true; } + +bool CTxMemPool::isSpent(const COutPoint& outpoint) const +{ + LOCK(cs); + return mapNextTx.count(outpoint); +} diff --git a/src/txmempool.h b/src/txmempool.h index 039b294a1c..e190b39495 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -1,7 +1,11 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_TXMEMPOOL_H #define BITCOIN_TXMEMPOOL_H @@ -25,21 +29,20 @@ class CTxMemPool mutable CCriticalSection cs; std::map mapTx; std::map mapNextTx; - + std::map, CKeyImageSpent> mapKeyImage; - - - CTxMemPool() + + + CTxMemPool() : nTransactionsUpdated(0) { - nTransactionsUpdated = 0; }; - + bool addUnchecked(const uint256& hash, CTransaction &tx); bool remove(const CTransaction &tx, bool fRecursive = false); bool removeConflicts(const CTransaction &tx); void clear(); void queryHashes(std::vector& vtxid); - + unsigned int GetTransactionsUpdated() const { LOCK(cs); @@ -65,25 +68,26 @@ class CTxMemPool } bool lookup(uint256 hash, CTransaction& result) const; - + bool isSpent(const COutPoint& outpoint) const; + bool insertKeyImage(const std::vector& vchImage, CKeyImageSpent& kis) { LOCK(cs); - + mapKeyImage[vchImage] = kis; - + return true; } bool lookupKeyImage(const std::vector& vchImage, CKeyImageSpent& result) const { LOCK(cs); - + std::map, CKeyImageSpent>::const_iterator it = mapKeyImage.find(vchImage); if (it == mapKeyImage.end()) return false; - + result = it->second; - + return true; } }; diff --git a/src/types.h b/src/types.h index 785790aac8..0bf10bd5f0 100644 --- a/src/types.h +++ b/src/types.h @@ -1,6 +1,9 @@ -// Copyright (c) 2015 The ShadowCoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file license.txt or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// +// SPDX-License-Identifier: MIT #ifndef TYPES_H #define TYPES_H diff --git a/src/uint256.h b/src/uint256.h index 09e43edbe0..f5ed994a1d 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,7 +1,13 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_UINT256_H #define BITCOIN_UINT256_H @@ -350,7 +356,7 @@ class base_uint { return (unsigned char*)&pn[WIDTH]; } - + const unsigned char* begin() const { return (unsigned char*)&pn[0]; @@ -463,7 +469,7 @@ class uint160 : public base_uint160 else *this = 0; } - + explicit uint160(const unsigned char* p, int len) { if (len == sizeof(pn)) @@ -471,7 +477,7 @@ class uint160 : public base_uint160 else *this = 0; } - + }; inline bool operator==(const uint160& a, uint64_t b) { return (base_uint160)a == b; } @@ -587,7 +593,7 @@ class uint256 : public base_uint256 else *this = 0; } - + explicit uint256(const unsigned char* p, int len) { if (len == sizeof(pn)) diff --git a/src/util.cpp b/src/util.cpp index 3274a999cf..9aa8c39c0a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,7 +1,13 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "util.h" @@ -10,7 +16,7 @@ #include "sync.h" #include "strlcpy.h" #include "version.h" -#include "ui_interface.h" +#include "interface.h" #include #include @@ -19,19 +25,18 @@ // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options // http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION +/* namespace boost { namespace program_options { std::string to_internal(const std::string&); } } - +*/ #include #include -#include -#include -#include #include +#include "util/fs.h" #include #include #include @@ -71,7 +76,7 @@ CMedianFilter vTimeOffsets(200,0); // Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; -void locking_callback(int mode, int i, const char* file, int line) +void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS { if (mode & CRYPTO_LOCK) { ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]); @@ -107,7 +112,7 @@ class CInit // Securely erase the memory used by the PRNG RAND_cleanup(); // Shutdown OpenSSL library multithreading support - CRYPTO_set_locking_callback(NULL); + CRYPTO_set_locking_callback(nullptr); for (int i = 0; i < CRYPTO_num_locks(); i++) delete ppmutexOpenSSL[i]; OPENSSL_free(ppmutexOpenSSL); @@ -144,7 +149,7 @@ void RandAddSeedPerfmon() unsigned char pdata[250000]; memset(pdata, 0, sizeof(pdata)); unsigned long nSize = sizeof(pdata); - long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize); + long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", nullptr, nullptr, pdata, &nSize); RegCloseKey(HKEY_PERFORMANCE_DATA); if (ret == ERROR_SUCCESS) { @@ -187,6 +192,12 @@ uint256 GetRandHash() return hash; } +void GetRandBytes(std::vector& vRandBytes, int nBytes) +{ + vRandBytes.resize(nBytes); + if (1 != RAND_bytes(&vRandBytes[0], nBytes)) + throw std::runtime_error("RAND_bytes failed."); +} // LogPrintf() has been broken a couple of times now // by well-meaning people adding mutexes in the most straightforward way. @@ -200,29 +211,29 @@ uint256 GetRandHash() static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT; // We use boost::call_once() to make sure these are initialized in // in a thread-safe manner the first time it is called: -static FILE* fileout = NULL; -static boost::mutex* mutexDebugLog = NULL; +static FILE* fileout = nullptr; +static boost::mutex* mutexDebugLog = nullptr; static void DebugPrintInit() { - assert(fileout == NULL); - assert(mutexDebugLog == NULL); + assert(fileout == nullptr); + assert(mutexDebugLog == nullptr); - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDataDir() / "debug.log"; fileout = fopen(pathDebug.string().c_str(), "a"); - if (fileout) setbuf(fileout, NULL); // unbuffered + if (fileout) setbuf(fileout, nullptr); // unbuffered mutexDebugLog = new boost::mutex(); } bool IsLogOpen() { - return fileout != NULL; + return fileout != nullptr; } bool LogAcceptCategory(const char* category) { - if (category != NULL) + if (category != nullptr) { if (!fDebug) return false; @@ -232,7 +243,7 @@ bool LogAcceptCategory(const char* category) // where mapMultiArgs might be deleted before another // global destructor calls LogPrint() static boost::thread_specific_ptr > ptrCategory; - if (ptrCategory.get() == NULL) + if (ptrCategory.get() == nullptr) { const vector& categories = mapMultiArgs["-debug"]; ptrCategory.reset(new set(categories.begin(), categories.end())); @@ -261,7 +272,7 @@ int LogPrintStr(const std::string &str) static bool fStartedNewLine = false; boost::call_once(&DebugPrintInit, debugPrintInitFlag); - if (fileout == NULL) + if (fileout == nullptr) return ret; boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); @@ -269,9 +280,9 @@ int LogPrintStr(const std::string &str) // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; - if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) - setbuf(fileout, NULL); // unbuffered + fs::path pathDebug = GetDataDir() / "debug.log"; + if (freopen(pathDebug.string().c_str(),"a",fileout) != nullptr) + setbuf(fileout, nullptr); // unbuffered } // Debug print useful for profiling @@ -284,7 +295,7 @@ int LogPrintStr(const std::string &str) ret = fwrite(str.data(), 1, str.size(), fileout); } - + return ret; } @@ -310,7 +321,7 @@ string vstrprintf(const char *format, va_list ap) delete[] p; limit *= 2; p = new char[limit]; - if (p == NULL) + if (p == nullptr) throw std::bad_alloc(); } string str(p, p+ret); @@ -471,7 +482,7 @@ static const signed char phexdigit[256] = bool IsHex(const string& str) { - BOOST_FOREACH(unsigned char c, str) + for (unsigned char c : str) { if (phexdigit[c] < 0) return false; @@ -552,28 +563,28 @@ void ParseParameters(int argc, const char* const argv[]) } // New 0.6 features: - BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) + for (const auto& entry : mapArgs) { // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set InterpretNegativeSetting(entry.first, mapArgs); } } -namespace sdc +namespace spec { void *memrchr(const void *s, int c, size_t n) { if (n < 1) - return NULL; - + return nullptr; + unsigned char* cp = (unsigned char*) s + n; - + do { if (*(--cp) == (unsigned char) c) return (void*) cp; } while (--n != 0); - - return NULL; + + return nullptr; }; // memcmp_nta - memcmp that is secure against timing attacks @@ -582,11 +593,11 @@ int memcmp_nta(const void *cs, const void *ct, size_t count) { const unsigned char *su1, *su2; int res = 0; - + for (su1 = (unsigned char*)cs, su2 = (unsigned char*)ct; 0 < count; ++su1, ++su2, count--) res |= (*su1 ^ *su2); - + return res; }; } @@ -1007,9 +1018,9 @@ static std::string FormatException(std::exception* pex, const char* pszThread) { #ifdef WIN32 char pszModule[MAX_PATH] = ""; - GetModuleFileNameA(NULL, pszModule, sizeof(pszModule)); + GetModuleFileNameA(nullptr, pszModule, sizeof(pszModule)); #else - const char* pszModule = "shadowcoin"; + const char* pszModule = "alias"; #endif if (pex) return strprintf( @@ -1036,49 +1047,78 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) strMiscWarning = message; } -boost::filesystem::path GetDefaultDataDir() +fs::path GetDefaultDataDir() { - namespace fs = boost::filesystem; - // Windows < Vista: C:\Documents and Settings\Username\Application Data\ShadowCoin - // Windows >= Vista: C:\Users\Username\AppData\Roaming\ShadowCoin - // Mac: ~/Library/Application Support/ShadowCoin - // Unix: ~/.shadowcoin - - + // Windows < Vista: C:\Documents and Settings\Username\Application Data\Aliaswallet + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Aliaswallet + // Mac: ~/Library/Application Support/Aliaswallet + // Unix: ~/.aliaswallet + + #ifdef WIN32 // Windows - return GetSpecialFolderPath(CSIDL_APPDATA) / "ShadowCoin"; + return GetSpecialFolderPath(CSIDL_APPDATA) / "Aliaswallet"; #else fs::path pathRet; char* pszHome = getenv("HOME"); - if (pszHome == NULL || strlen(pszHome) == 0) + if (pszHome == nullptr || strlen(pszHome) == 0) pathRet = fs::path("/"); else pathRet = fs::path(pszHome); - #ifdef MAC_OSX + #ifdef __APPLE__ // Mac pathRet /= "Library/Application Support"; fs::create_directory(pathRet); - return pathRet / "ShadowCoin"; + return pathRet / "Aliaswallet"; #else // Unix - return pathRet / ".shadowcoin"; + return pathRet / ".aliaswallet"; #endif #endif } -boost::filesystem::path GetTempPath() +fs::path GetOldDefaultDataDir() { - return boost::filesystem::temp_directory_path(); + // Windows < Vista: C:\Documents and Settings\Username\Application Data\Spectrecoin + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Spectrecoin + // Mac: ~/Library/Application Support/Spectrecoin + // Unix: ~/.spectrecoin + + +#ifdef WIN32 + // Windows + return GetSpecialFolderPath(CSIDL_APPDATA) / "Spectrecoin"; +#else + fs::path pathRet; + char* pszHome = getenv("HOME"); + if (pszHome == nullptr || strlen(pszHome) == 0) + pathRet = fs::path("/"); + else + pathRet = fs::path(pszHome); + #ifdef __APPLE__ + // Mac + pathRet /= "Library/Application Support"; + fs::create_directory(pathRet); + return pathRet / "Spectrecoin"; + #else + // Unix + return pathRet / ".spectrecoin"; + #endif +#endif + +} + +fs::path GetTempPath() +{ + return fs::temp_directory_path(); } -static boost::filesystem::path pathCached[CChainParams::MAX_NETWORK_TYPES+1]; +static fs::path pathCached[CChainParams::MAX_NETWORK_TYPES+1]; static CCriticalSection csPathCached; -const boost::filesystem::path &GetDataDir(bool fNetSpecific) +const fs::path& GetDataDir(bool fNetSpecific) { - namespace fs = boost::filesystem; LOCK(csPathCached); @@ -1100,6 +1140,9 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) } } else { path = GetDefaultDataDir(); + fs::path oldpath = GetOldDefaultDataDir(); + if (fs::exists(oldpath) && !fs::exists(path)) + fs::rename(oldpath, path); } if (fNetSpecific) path /= Params().DataDir(); @@ -1112,20 +1155,28 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) void ClearDatadirCache() { std::fill(&pathCached[0], &pathCached[CChainParams::MAX_NETWORK_TYPES+1], - boost::filesystem::path()); + fs::path()); } -boost::filesystem::path GetConfigFile() +fs::path GetConfigFile() { - boost::filesystem::path pathConfigFile(GetArg("-conf", "shadowcoin.conf")); - if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; + fs::path dataDir = GetDataDir(false); + + // Migrate spectrecoin.conf + fs::path oldConfigFile = dataDir / "spectrecoin.conf"; + fs::path newConfigFile = dataDir / "alias.conf"; + if (fs::exists(oldConfigFile) && !fs::exists(newConfigFile)) + fs::rename(oldConfigFile, newConfigFile); + + fs::path pathConfigFile(GetArg("-conf", "alias.conf")); + if (!pathConfigFile.is_complete()) pathConfigFile = dataDir / pathConfigFile; return pathConfigFile; } void ReadConfigFile(map& mapSettingsRet, map >& mapMultiSettingsRet) { - boost::filesystem::ifstream streamConfig(GetConfigFile()); + fs::ifstream streamConfig(GetConfigFile()); if (!streamConfig.good()) return; // No bitcoin.conf file is OK @@ -1148,15 +1199,15 @@ void ReadConfigFile(map& mapSettingsRet, ClearDatadirCache(); } -boost::filesystem::path GetPidFile() +fs::path GetPidFile() { - boost::filesystem::path pathPidFile(GetArg("-pid", "shadowcoind.pid")); + fs::path pathPidFile(GetArg("-pid", "alias.pid")); if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; return pathPidFile; } #ifndef WIN32 -void CreatePidFile(const boost::filesystem::path &path, pid_t pid) +void CreatePidFile(const fs::path& path, pid_t pid) { FILE* file = fopen(path.string().c_str(), "w"); if (file) @@ -1167,7 +1218,7 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid) } #endif -bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) +bool RenameOver(fs::path src, fs::path dest) { #ifdef WIN32 return MoveFileExA(src.string().c_str(), dest.string().c_str(), @@ -1195,7 +1246,7 @@ const char *GetNodeModeName(int modeInd) case NT_FULL: return "full"; case NT_THIN: return "thin"; }; - + return "unknown"; }; @@ -1208,7 +1259,7 @@ const char *GetNodeStateName(int stateInd) case NS_GET_FILTERED_BLOCKS: return "Get Filtered Blocks"; case NS_READY: return "Ready"; }; - + return "unknown"; }; @@ -1242,16 +1293,16 @@ std::string bytesReadable(uint64_t nBytes) return strprintf("%.2f MB", nBytes/1024.0/1024.0); if (nBytes >= 1024) return strprintf("%.2f KB", nBytes/1024.0); - + return strprintf("%d B", nBytes); }; void ShrinkDebugFile() { // Scroll debug.log if it's getting too big - boost::filesystem::path pathLog = GetDataDir() / "debug.log"; + fs::path pathLog = GetDataDir() / "debug.log"; FILE* file = fopen(pathLog.string().c_str(), "r"); - if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) + if (file && fs::file_size(pathLog) > 10 * 1000000) { // Restart the file with some of the end char pch[200000]; @@ -1281,7 +1332,7 @@ int64_t GetTime() { if (nMockTime) return nMockTime; - return time(NULL); + return time(nullptr); } void SetMockTime(int64_t nMockTimeIn) @@ -1331,22 +1382,23 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime) { // If nobody has a time different than ours but within 5 minutes of ours, give a warning bool fMatch = false; - BOOST_FOREACH(int64_t nOffset, vSorted) + for (int64_t nOffset : vSorted) { if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true; + } if (!fMatch) { fDone = true; - string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong ShadowCoin will not work properly."); + string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Alias will not work properly."); strMiscWarning = strMessage; LogPrintf("*** %s\n", strMessage.c_str()); - uiInterface.ThreadSafeMessageBox(strMessage+" ", string("ShadowCoin"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING); + uiInterface.ThreadSafeMessageBox(strMessage+" ", string("Alias"), CClientUIInterface::BTN_OK | CClientUIInterface::ICON_WARNING); } } } if (fDebug) { - BOOST_FOREACH(int64_t n, vSorted) + for (int64_t n : vSorted) LogPrintf("%+d ", n); LogPrintf("| "); } @@ -1383,6 +1435,11 @@ string FormatVersion(int nVersion) return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100); } +string FormatClientVersion() +{ + return FormatVersion(CLIENT_VERSION); +} + string FormatFullVersion() { return CLIENT_BUILD; @@ -1401,15 +1458,19 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const } #ifdef WIN32 -boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) +fs::path GetSpecialFolderPath(int nFolder, bool fCreate) { - namespace fs = boost::filesystem; - char pszPath[MAX_PATH] = ""; + wchar_t wPszPath[MAX_PATH]; - if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) + // get the path in unicode to support also non standard characters (8bit) like cyrillic + if(SHGetSpecialFolderPathW(nullptr, wPszPath, nFolder, fCreate)) { - return fs::path(pszPath); + // shorten the unicode path to be representable in 8bit chars + wchar_t wPszPathShort[MAX_PATH]; + GetShortPathNameW(wPszPath, wPszPathShort, MAX_PATH); + + return fs::path(wPszPathShort); } LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n"); @@ -1426,7 +1487,7 @@ void runCommand(std::string strCommand) bool ParseInt32(const std::string& str, int32_t *out) { - char *endp = NULL; + char *endp = nullptr; errno = 0; // strtol will not set errno if valid long int n = strtol(str.c_str(), &endp, 10); if(out) *out = (int)n; @@ -1450,7 +1511,7 @@ void RenameThread(const char* name) pthread_set_name_np(pthread_self(), name); // This is XCode 10.6-and-later; bring back if we drop 10.5 support: -// #elif defined(MAC_OSX) +// #elif defined(__APPLE__) // pthread_setname_np(name); #else diff --git a/src/util.h b/src/util.h index 3caeff59dd..8ec7ddedec 100644 --- a/src/util.h +++ b/src/util.h @@ -1,7 +1,13 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #ifndef BITCOIN_UTIL_H #define BITCOIN_UTIL_H @@ -20,11 +26,12 @@ #include #include +#ifndef Q_MOC_RUN #include -#include -#include +#include "util/fs.h" #include #include +#endif #include #include @@ -34,7 +41,6 @@ - #define BEGIN(a) ((char*)&(a)) #define END(a) ((char*)&((&(a))[1])) #define UBEGIN(a) ((unsigned char*)&(a)) @@ -142,7 +148,6 @@ static inline int errorN(int n, const char* format) - extern std::map mapArgs; extern std::map > mapMultiArgs; @@ -162,11 +167,11 @@ bool ParseMoney(const char* pszIn, int64_t& nRet); std::vector ParseHex(const char* psz); std::vector ParseHex(const std::string& str); bool IsHex(const std::string& str); -std::vector DecodeBase64(const char* p, bool* pfInvalid = NULL); +std::vector DecodeBase64(const char* p, bool* pfInvalid = nullptr); std::string DecodeBase64(const std::string& str); std::string EncodeBase64(const unsigned char* pch, size_t len); std::string EncodeBase64(const std::string& str); -std::vector DecodeBase32(const char* p, bool* pfInvalid = NULL); +std::vector DecodeBase32(const char* p, bool* pfInvalid = nullptr); std::string DecodeBase32(const std::string& str); std::string EncodeBase32(const unsigned char* pch, size_t len); std::string EncodeBase32(const std::string& str); @@ -174,18 +179,18 @@ void ParseParameters(int argc, const char*const argv[]); bool WildcardMatch(const char* psz, const char* mask); bool WildcardMatch(const std::string& str, const std::string& mask); void FileCommit(FILE *fileout); -bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); -boost::filesystem::path GetDefaultDataDir(); -boost::filesystem::path GetTempPath(); -const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); -boost::filesystem::path GetConfigFile(); -boost::filesystem::path GetPidFile(); +bool RenameOver(fs::path src, fs::path dest); +fs::path GetDefaultDataDir(); +fs::path GetTempPath(); +const fs::path& GetDataDir(bool fNetSpecific = true); +fs::path GetConfigFile(); +fs::path GetPidFile(); #ifndef WIN32 -void CreatePidFile(const boost::filesystem::path &path, pid_t pid); +void CreatePidFile(const fs::path& path, pid_t pid); #endif void ReadConfigFile(std::map& mapSettingsRet, std::map >& mapMultiSettingsRet); #ifdef WIN32 -boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); +fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif const char *GetNodeModeName(int modeInd); @@ -200,10 +205,12 @@ int GetRandInt(int nMax); uint32_t GetRandUInt32(); uint64_t GetRand(uint64_t nMax); uint256 GetRandHash(); +void GetRandBytes(std::vector& vRandBytes, int nBytes); int64_t GetTime(); void SetMockTime(int64_t nMockTimeIn); int64_t GetAdjustedTime(); int64_t GetTimeOffset(); +std::string FormatClientVersion(); std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); void AddTimeData(const CNetAddr& ip, int64_t nTime); @@ -237,7 +244,7 @@ inline int64_t atoi64(const char* psz) #ifdef _MSC_VER return _atoi64(psz); #else - return strtoll(psz, NULL, 10); + return strtoll(psz, nullptr, 10); #endif } @@ -246,7 +253,7 @@ inline int64_t atoi64(const std::string& str) #ifdef _MSC_VER return _atoi64(str.c_str()); #else - return strtoll(str.c_str(), NULL, 10); + return strtoll(str.c_str(), nullptr, 10); #endif } @@ -312,7 +319,7 @@ inline int64_t GetPerformanceCounter() QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); #else timeval t; - gettimeofday(&t, NULL); + gettimeofday(&t, nullptr); nCounter = (int64_t) t.tv_sec * 1000000 + t.tv_usec; #endif return nCounter; @@ -366,10 +373,10 @@ inline bool IsSwitchChar(char c) #endif } -namespace sdc +namespace spec { void *memrchr(const void *s, int c, size_t n); - + int memcmp_nta(const void *cs, const void *ct, size_t count); } /** @@ -549,11 +556,6 @@ inline void SetThreadPriority(int nPriority) setpriority(PRIO_PROCESS, 0, nPriority); #endif } - -inline void ExitThread(size_t nExitCode) -{ - pthread_exit((void*)nExitCode); -} #endif void RenameThread(const char* name); @@ -573,7 +575,7 @@ inline uint32_t ByteReverse(uint32_t value) // threadGroup.create_thread(boost::bind(&LoopForever >, "nothing", f, milliseconds)); template void LoopForever(const char* name, Callable func, int64_t msecs) { - std::string s = strprintf("shadow-%s", name); + std::string s = strprintf("alias-%s", name); RenameThread(s.c_str()); LogPrintf("%s thread start\n", name); try @@ -590,14 +592,14 @@ template void LoopForever(const char* name, Callable func, } catch (std::exception& e) { PrintException(&e, name); } catch (...) { - PrintException(NULL, name); + PrintException(nullptr, name); } } // .. and a wrapper that just calls func once template void TraceThread(const char* name, Callable func) { - std::string s = strprintf("shadow-%s", name); + std::string s = strprintf("alias-%s", name); RenameThread(s.c_str()); try { @@ -611,13 +613,13 @@ template void TraceThread(const char* name, Callable func) } catch (std::exception& e) { PrintException(&e, name); } catch (...) { - PrintException(NULL, name); + PrintException(nullptr, name); }; }; template void TraceThread(const char* name, Callable func, T arg) { - std::string s = strprintf("shadow-%s", name); + std::string s = strprintf("alias-%s", name); RenameThread(s.c_str()); try { @@ -631,7 +633,7 @@ template void TraceThread(const char* name, Call } catch (std::exception& e) { PrintException(&e, name); } catch (...) { - PrintException(NULL, name); + PrintException(nullptr, name); }; }; diff --git a/src/util/chaintype.cpp b/src/util/chaintype.cpp new file mode 100644 index 0000000000..f45a6c3079 --- /dev/null +++ b/src/util/chaintype.cpp @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +std::string ChainTypeToString(ChainType chain) +{ + switch (chain) { + case ChainType::MAIN: + return "main"; + case ChainType::TESTNET: + return "test"; + case ChainType::SIGNET: + return "signet"; + case ChainType::REGTEST: + return "regtest"; + } + throw std::runtime_error("Unknown chain type"); +} + +std::optional ChainTypeFromString(std::string_view chain) +{ + if (chain == "main") { + return ChainType::MAIN; + } else if (chain == "test" || chain == "testnet") { + return ChainType::TESTNET; + } else if (chain == "signet") { + return ChainType::SIGNET; + } else if (chain == "regtest") { + return ChainType::REGTEST; + } else { + return std::nullopt; + } +} + diff --git a/src/util/chaintype.h b/src/util/chaintype.h new file mode 100644 index 0000000000..93f902ba4c --- /dev/null +++ b/src/util/chaintype.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_CHAINTYPE_H +#define BITCOIN_UTIL_CHAINTYPE_H + +#include +#include +#include + +enum class ChainType { + MAIN, + TESTNET, + SIGNET, + REGTEST, +}; + +std::string ChainTypeToString(ChainType chain); + +std::optional ChainTypeFromString(std::string_view chain); + +#endif // BITCOIN_UTIL_CHAINTYPE_H + diff --git a/src/util/fs.h b/src/util/fs.h new file mode 100644 index 0000000000..0174e4b617 --- /dev/null +++ b/src/util/fs.h @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2021-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_UTIL_FS_H +#define ALIAS_UTIL_FS_H + +#include +#include +#include +#include + +namespace fs { + +using namespace std::filesystem; + +//! Path separator +#ifdef WIN32 +static constexpr char path_separator = '\\'; +#else +static constexpr char path_separator = '/'; +#endif + +//! Convert path to UTF-8 string +inline std::string PathToString(const path& p) { +#ifdef WIN32 + return p.u8string(); +#else + return p.string(); +#endif +} + +//! Convert UTF-8 string to path +inline path PathFromString(const std::string& s) { +#ifdef WIN32 + return path(std::u8string(s.begin(), s.end())); +#else + return path(s); +#endif +} + +//! Create directory if it doesn't exist +inline bool create_directories_safe(const path& p) { + std::error_code ec; + create_directories(p, ec); + return !ec; +} + +//! Check if path exists +inline bool exists_safe(const path& p) { + std::error_code ec; + return exists(p, ec); +} + +//! Remove file +inline bool remove_safe(const path& p) { + std::error_code ec; + return remove(p, ec); +} + +//! Get file size +inline std::optional file_size_safe(const path& p) { + std::error_code ec; + auto size = file_size(p, ec); + if (ec) return std::nullopt; + return size; +} + +//! File input stream that works with std::filesystem::path +class ifstream : public std::ifstream { +public: + ifstream() = default; + explicit ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in) + : std::ifstream(p, mode) {} + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { + std::ifstream::open(p, mode); + } +}; + +//! File output stream that works with std::filesystem::path +class ofstream : public std::ofstream { +public: + ofstream() = default; + explicit ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out) + : std::ofstream(p, mode) {} + void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { + std::ofstream::open(p, mode); + } +}; + +//! File stream that works with std::filesystem::path +class fstream : public std::fstream { +public: + fstream() = default; + explicit fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + : std::fstream(p, mode) {} + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { + std::fstream::open(p, mode); + } +}; + +} // namespace fs + +#endif // ALIAS_UTIL_FS_H diff --git a/src/util/hash_type.h b/src/util/hash_type.h new file mode 100644 index 0000000000..891681c5b0 --- /dev/null +++ b/src/util/hash_type.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2020-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_HASH_TYPE_H +#define BITCOIN_UTIL_HASH_TYPE_H + +#include +#include +#include + +template +class BaseHash +{ +protected: + HashType m_hash; + +public: + BaseHash() : m_hash() {} + explicit BaseHash(const HashType& in) : m_hash(in) {} + + unsigned char* begin() + { + return m_hash.begin(); + } + + const unsigned char* begin() const + { + return m_hash.begin(); + } + + unsigned char* end() + { + return m_hash.end(); + } + + const unsigned char* end() const + { + return m_hash.end(); + } + + operator std::vector() const + { + return std::vector{m_hash.begin(), m_hash.end()}; + } + + std::string ToString() const + { + return m_hash.ToString(); + } + + bool operator==(const BaseHash& other) const noexcept + { + return m_hash == other.m_hash; + } + + bool operator!=(const BaseHash& other) const noexcept + { + return !(m_hash == other.m_hash); + } + + bool operator<(const BaseHash& other) const noexcept + { + return m_hash < other.m_hash; + } + + size_t size() const + { + return m_hash.size(); + } + + unsigned char* data() { return m_hash.data(); } + const unsigned char* data() const { return m_hash.data(); } +}; + +#endif // BITCOIN_UTIL_HASH_TYPE_H + diff --git a/src/util/result.h b/src/util/result.h new file mode 100644 index 0000000000..6c21e43f59 --- /dev/null +++ b/src/util/result.h @@ -0,0 +1,137 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_UTIL_RESULT_H +#define ALIAS_UTIL_RESULT_H + +#include +#include +#include +#include + +namespace util { + +//! Bilingual string for user-facing messages +struct bilingual_str { + std::string original; + std::string translated; + + bilingual_str() = default; + bilingual_str(std::string original_in, std::string translated_in = "") + : original(std::move(original_in)) + , translated(translated_in.empty() ? original : std::move(translated_in)) {} + + bool empty() const { return original.empty(); } + void clear() { original.clear(); translated.clear(); } + + bilingual_str& operator+=(const bilingual_str& other) { + original += other.original; + translated += other.translated; + return *this; + } + + friend bilingual_str operator+(bilingual_str a, const bilingual_str& b) { + a += b; + return a; + } +}; + +//! Simple Result type for error handling +//! Holds either a success value of type T, or an error message +template +class Result { +public: + Result() = default; + + Result(T value) : m_value(std::move(value)), m_has_value(true) {} + + static Result Error(std::string error) { + Result r; + r.m_error = std::move(error); + r.m_has_value = false; + return r; + } + + static Result Error(bilingual_str error) { + Result r; + r.m_error = std::move(error.original); + r.m_has_value = false; + return r; + } + + explicit operator bool() const { return m_has_value; } + + bool has_value() const { return m_has_value; } + + const T& value() const& { return m_value; } + T& value() & { return m_value; } + T&& value() && { return std::move(m_value); } + + const T* operator->() const { return &m_value; } + T* operator->() { return &m_value; } + + const T& operator*() const& { return m_value; } + T& operator*() & { return m_value; } + T&& operator*() && { return std::move(m_value); } + + const std::string& error() const { return m_error; } + + template + T value_or(U&& default_value) const& { + return m_has_value ? m_value : static_cast(std::forward(default_value)); + } + + template + T value_or(U&& default_value) && { + return m_has_value ? std::move(m_value) : static_cast(std::forward(default_value)); + } + +private: + T m_value{}; + std::string m_error; + bool m_has_value{false}; +}; + +//! Specialization for void +template<> +class Result { +public: + Result() : m_has_value(true) {} + + static Result Error(std::string error) { + Result r; + r.m_error = std::move(error); + r.m_has_value = false; + return r; + } + + static Result Error(bilingual_str error) { + Result r; + r.m_error = std::move(error.original); + r.m_has_value = false; + return r; + } + + explicit operator bool() const { return m_has_value; } + bool has_value() const { return m_has_value; } + const std::string& error() const { return m_error; } + +private: + std::string m_error; + bool m_has_value{false}; +}; + +} // namespace util + +//! Convenience function to create bilingual strings +inline util::bilingual_str _(const char* str) { + return util::bilingual_str{str, str}; +} + +inline util::bilingual_str Untranslated(std::string original) { + return util::bilingual_str{std::move(original)}; +} + +#endif // ALIAS_UTIL_RESULT_H diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp new file mode 100644 index 0000000000..7930642c59 --- /dev/null +++ b/src/util/strencodings.cpp @@ -0,0 +1,277 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#include + +#include +#include +#include + +namespace util { + +static const char hexmap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +std::string HexStr(std::span bytes) { + std::string rv; + rv.reserve(bytes.size() * 2); + for (uint8_t v : bytes) { + rv.push_back(hexmap[v >> 4]); + rv.push_back(hexmap[v & 15]); + } + return rv; +} + +std::vector ParseHex(std::string_view hex_str) { + std::vector rv; + rv.reserve(hex_str.size() / 2); + + size_t pos = 0; + while (pos < hex_str.size()) { + while (pos < hex_str.size() && IsSpace(hex_str[pos])) { + ++pos; + } + if (pos >= hex_str.size()) break; + + if (pos + 1 >= hex_str.size()) break; + + int hi = HexDigitValue(hex_str[pos]); + int lo = HexDigitValue(hex_str[pos + 1]); + if (hi < 0 || lo < 0) break; + + rv.push_back(static_cast((hi << 4) | lo)); + pos += 2; + } + return rv; +} + +bool IsHex(std::string_view str) { + for (char c : str) { + if (!IsHexDigit(c)) return false; + } + return (str.size() > 0) && (str.size() % 2 == 0); +} + +std::string TrimString(std::string_view str, std::string_view pattern) { + auto start = str.find_first_not_of(pattern); + if (start == std::string_view::npos) return ""; + auto end = str.find_last_not_of(pattern); + return std::string(str.substr(start, end - start + 1)); +} + +std::string_view TrimStringLeft(std::string_view str, std::string_view pattern) { + auto start = str.find_first_not_of(pattern); + if (start == std::string_view::npos) return ""; + return str.substr(start); +} + +std::string_view TrimStringRight(std::string_view str, std::string_view pattern) { + auto end = str.find_last_not_of(pattern); + if (end == std::string_view::npos) return ""; + return str.substr(0, end + 1); +} + +std::string ToLower(std::string_view str) { + std::string result; + result.reserve(str.size()); + for (char c : str) { + result.push_back(static_cast(std::tolower(static_cast(c)))); + } + return result; +} + +std::string ToUpper(std::string_view str) { + std::string result; + result.reserve(str.size()); + for (char c : str) { + result.push_back(static_cast(std::toupper(static_cast(c)))); + } + return result; +} + +bool EqualsIgnoreCase(std::string_view a, std::string_view b) { + if (a.size() != b.size()) return false; + for (size_t i = 0; i < a.size(); ++i) { + if (std::tolower(static_cast(a[i])) != + std::tolower(static_cast(b[i]))) { + return false; + } + } + return true; +} + +std::vector SplitString(std::string_view str, char sep) { + std::vector result; + size_t start = 0; + size_t end; + while ((end = str.find(sep, start)) != std::string_view::npos) { + result.emplace_back(str.substr(start, end - start)); + start = end + 1; + } + result.emplace_back(str.substr(start)); + return result; +} + +std::vector SplitString(std::string_view str, std::string_view sep) { + std::vector result; + size_t start = 0; + size_t end; + while ((end = str.find(sep, start)) != std::string_view::npos) { + result.emplace_back(str.substr(start, end - start)); + start = end + sep.size(); + } + result.emplace_back(str.substr(start)); + return result; +} + +std::optional ParseInt64(std::string_view str) { + return ToIntegral(str); +} + +std::optional ParseInt32(std::string_view str) { + return ToIntegral(str); +} + +std::optional ParseUInt64(std::string_view str) { + return ToIntegral(str); +} + +std::optional ParseUInt32(std::string_view str) { + return ToIntegral(str); +} + +std::optional ParseDouble(std::string_view str) { + try { + size_t pos; + double value = std::stod(std::string(str), &pos); + if (pos == str.size()) return value; + } catch (...) {} + return std::nullopt; +} + +std::string FormatBytes(uint64_t bytes) { + const char* units[] = {"B", "KB", "MB", "GB", "TB"}; + int unit = 0; + double size = static_cast(bytes); + while (size >= 1024.0 && unit < 4) { + size /= 1024.0; + ++unit; + } + char buf[64]; + if (unit == 0) { + snprintf(buf, sizeof(buf), "%" PRIu64 " %s", bytes, units[unit]); + } else { + snprintf(buf, sizeof(buf), "%.2f %s", size, units[unit]); + } + return buf; +} + +static const char* pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +std::string EncodeBase64(std::span input) { + std::string result; + result.reserve((input.size() + 2) / 3 * 4); + + size_t i = 0; + while (i < input.size()) { + uint32_t n = static_cast(input[i++]) << 16; + if (i < input.size()) n |= static_cast(input[i++]) << 8; + if (i < input.size()) n |= input[i++]; + + result.push_back(pbase64[(n >> 18) & 0x3f]); + result.push_back(pbase64[(n >> 12) & 0x3f]); + result.push_back((i > input.size() + 1) ? '=' : pbase64[(n >> 6) & 0x3f]); + result.push_back((i > input.size()) ? '=' : pbase64[n & 0x3f]); + } + return result; +} + +static const int8_t decode64_table[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +std::optional> DecodeBase64(std::string_view input) { + std::vector result; + result.reserve(input.size() * 3 / 4); + + uint32_t n = 0; + int bits = 0; + + for (char c : input) { + if (c == '=') break; + if (IsSpace(c)) continue; + + int8_t val = decode64_table[static_cast(c)]; + if (val < 0) return std::nullopt; + + n = (n << 6) | val; + bits += 6; + + if (bits >= 8) { + bits -= 8; + result.push_back(static_cast((n >> bits) & 0xff)); + } + } + return result; +} + +std::string SanitizeString(std::string_view str, int rule) { + std::string result; + result.reserve(str.size()); + for (char c : str) { + if (c >= 32 && c <= 126) { + result.push_back(c); + } + } + return result; +} + +std::string UrlEncode(std::string_view str) { + std::string result; + result.reserve(str.size() * 3); + for (unsigned char c : str) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') { + result.push_back(c); + } else { + result.push_back('%'); + result.push_back(hexmap[c >> 4]); + result.push_back(hexmap[c & 15]); + } + } + return result; +} + +std::string UrlDecode(std::string_view str) { + std::string result; + result.reserve(str.size()); + for (size_t i = 0; i < str.size(); ++i) { + if (str[i] == '%' && i + 2 < str.size()) { + int hi = HexDigitValue(str[i + 1]); + int lo = HexDigitValue(str[i + 2]); + if (hi >= 0 && lo >= 0) { + result.push_back(static_cast((hi << 4) | lo)); + i += 2; + continue; + } + } + result.push_back(str[i]); + } + return result; +} + +} // namespace util diff --git a/src/util/strencodings.h b/src/util/strencodings.h new file mode 100644 index 0000000000..cc179704b7 --- /dev/null +++ b/src/util/strencodings.h @@ -0,0 +1,143 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_UTIL_STRENCODINGS_H +#define ALIAS_UTIL_STRENCODINGS_H + +#include +#include +#include +#include +#include +#include +#include + +namespace util { + +//! Check if character is a space +constexpr inline bool IsSpace(char c) noexcept { + return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v'; +} + +//! Check if character is a digit +constexpr inline bool IsDigit(char c) { + return c >= '0' && c <= '9'; +} + +//! Check if character is a hex digit +constexpr inline bool IsHexDigit(char c) { + return IsDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +//! Convert hex character to integer +constexpr inline int HexDigitValue(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; +} + +//! Convert bytes to hex string +std::string HexStr(std::span bytes); + +inline std::string HexStr(std::span bytes) { + return HexStr(std::span( + reinterpret_cast(bytes.data()), bytes.size())); +} + +//! Convert hex string to bytes +std::vector ParseHex(std::string_view hex_str); + +//! Check if string is valid hex +bool IsHex(std::string_view str); + +//! Trim whitespace from string +std::string TrimString(std::string_view str, std::string_view pattern = " \f\n\r\t\v"); + +//! Left trim whitespace +std::string_view TrimStringLeft(std::string_view str, std::string_view pattern = " \f\n\r\t\v"); + +//! Right trim whitespace +std::string_view TrimStringRight(std::string_view str, std::string_view pattern = " \f\n\r\t\v"); + +//! Convert string to lowercase +std::string ToLower(std::string_view str); + +//! Convert string to uppercase +std::string ToUpper(std::string_view str); + +//! Check if strings are equal (case-insensitive) +bool EqualsIgnoreCase(std::string_view a, std::string_view b); + +//! Join strings with separator +template +std::string Join(const Container& container, std::string_view separator) { + std::string result; + bool first = true; + for (const auto& item : container) { + if (!first) result += separator; + result += item; + first = false; + } + return result; +} + +//! Split string by separator +std::vector SplitString(std::string_view str, char sep); +std::vector SplitString(std::string_view str, std::string_view sep); + +//! Parse integer from string +template +std::optional ToIntegral(std::string_view str) { + T value; + const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value); + if (ec == std::errc{} && ptr == str.data() + str.size()) { + return value; + } + return std::nullopt; +} + +//! Safe conversion from string to int64 +std::optional ParseInt64(std::string_view str); + +//! Safe conversion from string to int32 +std::optional ParseInt32(std::string_view str); + +//! Safe conversion from string to uint64 +std::optional ParseUInt64(std::string_view str); + +//! Safe conversion from string to uint32 +std::optional ParseUInt32(std::string_view str); + +//! Safe conversion from string to double +std::optional ParseDouble(std::string_view str); + +//! Convert bytes to human-readable string +std::string FormatBytes(uint64_t bytes); + +//! Encode bytes as base64 +std::string EncodeBase64(std::span input); + +//! Decode base64 to bytes +std::optional> DecodeBase64(std::string_view input); + +//! Encode bytes as base32 +std::string EncodeBase32(std::span input); + +//! Decode base32 to bytes +std::optional> DecodeBase32(std::string_view input); + +//! URL encode string +std::string UrlEncode(std::string_view str); + +//! URL decode string +std::string UrlDecode(std::string_view str); + +//! Sanitize string for safe display +std::string SanitizeString(std::string_view str, int rule = 0); + +} // namespace util + +#endif // ALIAS_UTIL_STRENCODINGS_H diff --git a/src/util/time.cpp b/src/util/time.cpp new file mode 100644 index 0000000000..a642820378 --- /dev/null +++ b/src/util/time.cpp @@ -0,0 +1,87 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#include + +#include +#include +#include +#include +#include + +namespace util { + +static std::atomic nTimeOffset{0}; + +std::string FormatISO8601DateTime(int64_t time) { + std::time_t t = static_cast(time); + std::tm* tm = std::gmtime(&t); + if (!tm) return ""; + + char buf[32]; + std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", tm); + return buf; +} + +std::string FormatISO8601Date(int64_t time) { + std::time_t t = static_cast(time); + std::tm* tm = std::gmtime(&t); + if (!tm) return ""; + + char buf[16]; + std::strftime(buf, sizeof(buf), "%Y-%m-%d", tm); + return buf; +} + +int64_t ParseISO8601DateTime(const std::string& str) { + std::tm tm = {}; + int year, month, day, hour, min, sec; + + if (sscanf(str.c_str(), "%d-%d-%dT%d:%d:%dZ", + &year, &month, &day, &hour, &min, &sec) != 6) { + return 0; + } + + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + tm.tm_isdst = 0; + +#ifdef _WIN32 + return _mkgmtime(&tm); +#else + return timegm(&tm); +#endif +} + +static std::mutex cs_nTimeOffset; +static std::set setTimeOffsets; + +void AddTimeData(int64_t nOffset) { + std::lock_guard lock(cs_nTimeOffset); + + setTimeOffsets.insert(nOffset); + + if (setTimeOffsets.size() >= 5) { + auto it = setTimeOffsets.begin(); + std::advance(it, setTimeOffsets.size() / 2); + nTimeOffset.store(*it, std::memory_order_relaxed); + } +} + +int64_t GetTimeOffset() { + return nTimeOffset.load(std::memory_order_relaxed); +} + +int64_t GetAdjustedTime() { + int64_t mock = GetMockTime(); + if (mock > 0) return mock; + return GetTime() + GetTimeOffset(); +} + +} // namespace util diff --git a/src/util/time.h b/src/util/time.h new file mode 100644 index 0000000000..11ac9a42e6 --- /dev/null +++ b/src/util/time.h @@ -0,0 +1,113 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// SPDX-License-Identifier: MIT + +#ifndef ALIAS_UTIL_TIME_H +#define ALIAS_UTIL_TIME_H + +#include +#include +#include +#include + +using namespace std::chrono_literals; + +namespace util { + +//! Get current system time in seconds since epoch +inline int64_t GetTime() { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count(); +} + +//! Get current system time in milliseconds since epoch +inline int64_t GetTimeMillis() { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count(); +} + +//! Get current system time in microseconds since epoch +inline int64_t GetTimeMicros() { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count(); +} + +//! Sleep for specified milliseconds +inline void MilliSleep(int64_t n) { + std::this_thread::sleep_for(std::chrono::milliseconds(n)); +} + +//! Sleep for specified seconds +inline void Sleep(int64_t n) { + std::this_thread::sleep_for(std::chrono::seconds(n)); +} + +//! High resolution clock for performance measurement +using SteadyClock = std::chrono::steady_clock; +using SteadyTimePoint = std::chrono::time_point; + +inline SteadyTimePoint SteadyNow() { + return SteadyClock::now(); +} + +//! Convert duration to milliseconds +template +int64_t ToMillis(Duration d) { + return std::chrono::duration_cast(d).count(); +} + +//! Convert duration to seconds +template +int64_t ToSeconds(Duration d) { + return std::chrono::duration_cast(d).count(); +} + +//! Format time as ISO 8601 string +std::string FormatISO8601DateTime(int64_t time); +std::string FormatISO8601Date(int64_t time); + +//! Parse ISO 8601 datetime string +int64_t ParseISO8601DateTime(const std::string& str); + +//! Mockable time for testing +class MockableClock { +public: + using time_point = std::chrono::time_point; + using duration = std::chrono::seconds; + + static time_point now() noexcept { + return time_point{std::chrono::seconds{s_mock_time.load(std::memory_order_relaxed)}}; + } + + static void SetMockTime(int64_t time) { + s_mock_time.store(time, std::memory_order_relaxed); + } + + static int64_t GetMockTime() { + return s_mock_time.load(std::memory_order_relaxed); + } + +private: + static inline std::atomic s_mock_time{0}; +}; + +//! Set mock time for testing +inline void SetMockTime(int64_t time) { + MockableClock::SetMockTime(time); +} + +//! Get mock time for testing +inline int64_t GetMockTime() { + return MockableClock::GetMockTime(); +} + +//! Get adjusted time (accounts for network time offset) +int64_t GetAdjustedTime(); + +} // namespace util + +#endif // ALIAS_UTIL_TIME_H diff --git a/src/util/vector.h b/src/util/vector.h new file mode 100644 index 0000000000..36f29c0115 --- /dev/null +++ b/src/util/vector.h @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// Copyright (c) 2019-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_VECTOR_H +#define BITCOIN_UTIL_VECTOR_H + +#include +#include +#include +#include +#include +#include + +/** Construct a vector with the specified elements. */ +template +inline std::vector::type> Vector(Args&&... args) +{ + std::vector::type> ret; + ret.reserve(sizeof...(args)); + (void)std::initializer_list{(ret.emplace_back(std::forward(args)), 0)...}; + return ret; +} + +/** Concatenate two vectors, moving elements. */ +template +inline V Cat(V v1, V&& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (auto& arg : v2) { + v1.push_back(std::move(arg)); + } + return v1; +} + +/** Concatenate two vectors. */ +template +inline V Cat(V v1, const V& v2) +{ + v1.reserve(v1.size() + v2.size()); + for (const auto& arg : v2) { + v1.push_back(arg); + } + return v1; +} + +/** Clear a vector (or std::deque) and release its allocated memory. */ +template +inline void ClearShrink(V& v) noexcept +{ + V{}.swap(v); +} + +template +inline std::optional FindFirst(const std::vector& vec, const L fnc) +{ + for (const auto& el : vec) { + if (fnc(el)) { + return el; + } + } + return std::nullopt; +} + +#endif // BITCOIN_UTIL_VECTOR_H + diff --git a/src/validation_alias.cpp b/src/validation_alias.cpp new file mode 100644 index 0000000000..17c77ee2b4 --- /dev/null +++ b/src/validation_alias.cpp @@ -0,0 +1,153 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AliasValidation { + +bool IsProofOfAnonStake(const CBlock& block) +{ + if (!block.IsProofOfStake() || block.vtx.size() < 2) + return false; + + // Alias-specific: Check if coinstake transaction is anon version + return (block.vtx[1]->nVersion == ANON_TXN_VERSION); +} + +bool CheckAnonInputsForBlock(const CTransaction& tx, CTxDB& txdb, int64_t& nAnonIn, bool& fInvalid) +{ + if (tx.nVersion != ANON_TXN_VERSION) + return true; // Not an anon transaction, skip + + int64_t nTxAnonIn = 0; + // Note: CheckAnonInputs is a method on CTransaction, but we need non-const reference + // For now, this is a placeholder - actual implementation will be integrated into ConnectBlock + // where we have access to the transaction object + (void)tx; + (void)txdb; + (void)nAnonIn; + (void)fInvalid; + + // TODO: Integrate actual CheckAnonInputs call when migrating ConnectBlock + // The actual call would be: tx.CheckAnonInputs(txdb, nTxAnonIn, fInvalid, true) + + return true; +} + +int64_t CountAnonOutputs(const CTransaction& tx) +{ + int64_t nAnonOut = 0; + for (const auto& txout : tx.vout) + { + if (txout.IsAnonOutput()) + nAnonOut += txout.nValue; + } + return nAnonOut; +} + +bool ValidateStakeReward(const CBlock& block, const CBlockIndex* pindexPrev, + int64_t nStakeReward, int64_t nFees, int64_t nCoinAge, + BlockValidationState& state) +{ + if (!block.IsProofOfStake() || block.vtx.size() < 2) + return true; // Not a PoS block + + const CTransaction& coinstake = *block.vtx[1]; + + // Alias-specific: Calculate stake reward based on type + int64_t nCalculatedStakeReward; + if (IsProofOfAnonStake(block)) + { + nCalculatedStakeReward = Params().GetProofOfAnonStakeReward(pindexPrev, nFees); + } + else + { + nCalculatedStakeReward = Params().GetProofOfStakeReward(pindexPrev, nCoinAge, nFees); + } + + // Check reward amount + if (nStakeReward > nCalculatedStakeReward) + { + LogPrintf("ERROR: ValidateStakeReward() : coinstake pays too much (actual=%d vs calculated=%d)\n", + nStakeReward, nCalculatedStakeReward); + return state.Invalid(BlockValidationResult::DOS_100, "bad-cs-amount", + strprintf("coinstake pays too much (actual=%d vs calculated=%d)", + nStakeReward, nCalculatedStakeReward)); + } + + // Alias-specific: Check dev contribution or supply increase address + bool fSupplyIncrease = Params().IsForkV4SupplyIncrease(pindexPrev); + if (fSupplyIncrease || (Params().IsForkV2(block.nTime) && pindexPrev->nHeight % 6 == 0)) + { + std::string strAddress = fSupplyIncrease ? Params().GetSupplyIncreaseAddress() : + Params().GetDevContributionAddress(); + CBitcoinAddress address(strAddress); + if (!address.IsValid()) + { + LogPrintf("ValidateStakeReward() : invalid address %s\n", strAddress.c_str()); + return state.Invalid(BlockValidationResult::DOS_100, "bad-cs-address", + strprintf("invalid address %s", strAddress.c_str())); + } + + CScript scriptPubKey; + scriptPubKey.SetDestination(address.Get()); + + bool containsDonation = false; + + // The donation can be at i = 2 or above + for (size_t i = 2; i < coinstake.vout.size(); i++) + { + if (coinstake.vout[i].scriptPubKey == scriptPubKey) + { + if (coinstake.vout[i].nValue >= nCalculatedStakeReward) + { + containsDonation = true; + break; + } + } + } + + if (!containsDonation) + { + LogPrintf("ValidateStakeReward() : stake does not pay to address %s\n", + address.ToString().c_str()); + return state.Invalid(BlockValidationResult::DOS_100, "bad-cs-donation", + strprintf("stake does not pay to address %s", + address.ToString().c_str())); + } + } + + return true; +} + +void UpdateAnonSupply(CBlockIndex* pindex, int64_t nAnonOut, int64_t nAnonIn) +{ + // Alias-specific: Track anon coin supply separately + pindex->nAnonSupply = (pindex->pprev ? pindex->pprev->nAnonSupply : 0) + nAnonOut - nAnonIn; +} + +bool CheckAndRebuildAnonCache(CBlockIndex* pindex) +{ + // Alias-specific: Check if anon cache needs rebuilding + // Note: fStaleAnonCache and pwalletMain are global variables defined elsewhere + // This function should be called from ConnectBlock when needed + // For now, return true - actual implementation will be integrated into ConnectBlock + (void)pindex; // Suppress unused parameter warning + return true; +} + +} // namespace AliasValidation diff --git a/src/validation_alias.h b/src/validation_alias.h new file mode 100644 index 0000000000..72404e5090 --- /dev/null +++ b/src/validation_alias.h @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_VALIDATION_ALIAS_H +#define BITCOIN_VALIDATION_ALIAS_H + +#include +#include +#include +#include +#include +#include + +class CBlockIndex; +class CTxDB; +class CCoinsViewCache; + +/** + * Alias-specific validation helpers + * These functions preserve Alias-specific validation logic while using modern structures + */ + +namespace AliasValidation { + +/** + * Check if block is proof of anon stake + * Alias-specific: Checks if coinstake transaction is anon version + */ +bool IsProofOfAnonStake(const CBlock& block); + +/** + * Validate anon inputs for a transaction + * Alias-specific: Validates ring signatures and key images for anon transactions + */ +bool CheckAnonInputsForBlock(const CTransaction& tx, CTxDB& txdb, int64_t& nAnonIn, bool& fInvalid); + +/** + * Validate anon outputs for a transaction + * Alias-specific: Counts and validates anon outputs + */ +int64_t CountAnonOutputs(const CTransaction& tx); + +/** + * Validate stake reward for Alias + * Alias-specific: Validates both regular PoS and Anon PoS rewards + * Also validates dev contribution and supply increase addresses + */ +bool ValidateStakeReward(const CBlock& block, const CBlockIndex* pindexPrev, + int64_t nStakeReward, int64_t nFees, int64_t nCoinAge, + BlockValidationState& state); + +/** + * Update anon supply tracking + * Alias-specific: Tracks anon coin supply separately + */ +void UpdateAnonSupply(CBlockIndex* pindex, int64_t nAnonOut, int64_t nAnonIn); + +/** + * Check anon cache and rebuild if needed + * Alias-specific: Manages anon statistics cache + */ +bool CheckAndRebuildAnonCache(CBlockIndex* pindex); + +} // namespace AliasValidation + +#endif // BITCOIN_VALIDATION_ALIAS_H diff --git a/src/validation_connectblock_alias.cpp b/src/validation_connectblock_alias.cpp new file mode 100644 index 0000000000..c84389694e --- /dev/null +++ b/src/validation_connectblock_alias.cpp @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AliasConnectBlock { + +bool ProcessAnonTransaction(const CTransaction& tx, CTxDB& txdb, + int64_t& nAnonIn, int64_t& nAnonOut, + bool& fInvalid, BlockValidationState& state) +{ + if (tx.nVersion != ANON_TXN_VERSION) + return true; // Not an anon transaction, skip + + // Count anon outputs + nAnonOut = AliasValidation::CountAnonOutputs(tx); + + // Validate anon inputs + int64_t nTxAnonIn = 0; + if (!tx.CheckAnonInputs(txdb, nTxAnonIn, fInvalid, true)) + { + if (fInvalid) + { + LogPrintf("ProcessAnonTransaction() : CheckAnonInputs found invalid tx %s\n", + tx.GetHash().ToString().substr(0,10).c_str()); + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-anon-inputs", + strprintf("CheckAnonInputs found invalid tx %s", + tx.GetHash().ToString().substr(0,10).c_str())); + } + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-anon-inputs", + "CheckAnonInputs failed"); + } + + nAnonIn = nTxAnonIn; + return true; +} + +bool ValidateStakeRewardInConnectBlock(const CBlock& block, + const CBlockIndex* pindexPrev, + int64_t nStakeReward, int64_t nFees, + int64_t nCoinAge, + BlockValidationState& state) +{ + return AliasValidation::ValidateStakeReward(block, pindexPrev, nStakeReward, + nFees, nCoinAge, state); +} + +void UpdateAliasBlockIndex(CBlockIndex* pindex, int64_t nAnonOut, int64_t nAnonIn) +{ + AliasValidation::UpdateAnonSupply(pindex, nAnonOut, nAnonIn); +} + +bool CheckAnonCacheEarly(CBlockIndex* pindex) +{ + // Alias-specific: Check if anon cache needs rebuilding + extern bool fStaleAnonCache; + extern bool fDebugRingSig; + extern CWallet* pwalletMain; + + if (fStaleAnonCache && pindex && pindex->pprev) + { + LogPrintf("CheckAnonCacheEarly() : Stale anon cache => rebuild.\n"); + if (pwalletMain && !pwalletMain->CacheAnonStats(pindex->pprev->nHeight)) + { + LogPrintf("CheckAnonCacheEarly() : CacheAnonStats() failed.\n"); + // Don't fail block validation, just log + } + } + + if (fDebugRingSig && pindex && pindex->pprev) + { + // TODO: Implement validateAnonCache if needed + // validateAnonCache(pindex->pprev->nHeight); + } + + return true; +} + +} // namespace AliasConnectBlock diff --git a/src/validation_connectblock_alias.h b/src/validation_connectblock_alias.h new file mode 100644 index 0000000000..424fd64a1d --- /dev/null +++ b/src/validation_connectblock_alias.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_VALIDATION_CONNECTBLOCK_ALIAS_H +#define BITCOIN_VALIDATION_CONNECTBLOCK_ALIAS_H + +#include +#include +#include +#include +#include + +class CBlockIndex; +class CTxDB; +class CCoinsViewCache; +class Chainstate; + +namespace AliasConnectBlock { + +/** + * Alias-specific ConnectBlock integration helpers + * These functions integrate Alias validation into the modern ConnectBlock flow + */ + +/** + * Process anon transaction in ConnectBlock + * Alias-specific: Validates anon inputs and counts anon outputs + * Returns true on success, false on failure + */ +bool ProcessAnonTransaction(const CTransaction& tx, CTxDB& txdb, + int64_t& nAnonIn, int64_t& nAnonOut, + bool& fInvalid, BlockValidationState& state); + +/** + * Validate stake reward for Alias in ConnectBlock + * Alias-specific: Validates both regular PoS and Anon PoS rewards + * Also validates dev contribution and supply increase addresses + * Should be called after processing all transactions + */ +bool ValidateStakeRewardInConnectBlock(const CBlock& block, + const CBlockIndex* pindexPrev, + int64_t nStakeReward, int64_t nFees, + int64_t nCoinAge, + BlockValidationState& state); + +/** + * Update Alias-specific block index fields + * Alias-specific: Updates nAnonSupply tracking + * Should be called at the end of ConnectBlock before writing to disk + */ +void UpdateAliasBlockIndex(CBlockIndex* pindex, int64_t nAnonOut, int64_t nAnonIn); + +/** + * Check and rebuild anon cache if needed + * Alias-specific: Manages anon statistics cache + * Should be called early in ConnectBlock + */ +bool CheckAnonCacheEarly(CBlockIndex* pindex); + +} // namespace AliasConnectBlock + +#endif // BITCOIN_VALIDATION_CONNECTBLOCK_ALIAS_H diff --git a/src/validation_connectblock_integration.cpp b/src/validation_connectblock_integration.cpp new file mode 100644 index 0000000000..46aa693818 --- /dev/null +++ b/src/validation_connectblock_integration.cpp @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// Copyright (c) 2009-2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +/** + * Integration example: How to use AliasConnectBlock helpers in modern ConnectBlock + * + * This file shows how to integrate the Alias-specific validation helpers + * into a modern ConnectBlock implementation (similar to particl-core's structure) + * + * NOTE: This is an integration guide - actual implementation will be in validation.cpp + */ + +#include +#include +#include +#include +#include +#include +#include + +// Example integration points for modern ConnectBlock: + +/* + * Example 1: Early anon cache check + * + * In ConnectBlock, early in the function: + * + * if (!AliasConnectBlock::CheckAnonCacheEarly(pindex)) { + * return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-anon-cache"); + * } + */ + +/* + * Example 2: Process anon transactions + * + * In the transaction processing loop: + * + * for (const auto& tx : block.vtx) { + * if (tx->nVersion == ANON_TXN_VERSION) { + * bool fInvalid = false; + * int64_t nTxAnonIn = 0; + * int64_t nTxAnonOut = 0; + * + * if (!AliasConnectBlock::ProcessAnonTransaction(*tx, txdb, + * nTxAnonIn, nTxAnonOut, + * fInvalid, state)) { + * return false; // state already set + * } + * + * nAnonIn += nTxAnonIn; + * nAnonOut += nTxAnonOut; + * } + * } + */ + +/* + * Example 3: Validate stake reward + * + * After processing all transactions, for PoS blocks: + * + * if (block.IsProofOfStake()) { + * uint64_t nCoinAge = 0; + * // ... calculate coin age ... + * + * if (!AliasConnectBlock::ValidateStakeRewardInConnectBlock(block, pindexPrev, + * nStakeReward, nFees, + * nCoinAge, state)) { + * return false; // state already set + * } + * } + */ + +/* + * Example 4: Update anon supply + * + * At the end of ConnectBlock, before writing to disk: + * + * AliasConnectBlock::UpdateAliasBlockIndex(pindex, nAnonOut, nAnonIn); + */ + +// This file serves as documentation and integration guide +// The actual integration will be done in the main validation.cpp file diff --git a/src/version.cpp b/src/version.cpp index d60e63ba43..53804c3e34 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -1,6 +1,14 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #include #include "version.h" @@ -8,7 +16,7 @@ // Name of client reported in the 'version' message. Report the same name // for both bitcoind and bitcoin-qt, to make it harder for attackers to // target servers or GUI users specifically. -const std::string CLIENT_NAME("Satoshi"); +const std::string CLIENT_NAME("Ghost_Protocol"); // Client version number #define CLIENT_VERSION_SUFFIX "" @@ -28,31 +36,34 @@ const std::string CLIENT_NAME("Satoshi"); // * otherwise, use v[maj].[min].[rev].[build]-unk // finally CLIENT_VERSION_SUFFIX is added -// First, include build.h if requested -#ifdef HAVE_BUILD_INFO -# include "build.h" -#endif +//// First, include build.h if requested +//#ifdef HAVE_BUILD_INFO +//# include "build.h" +//#endif +// +//// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. +//#define GIT_ARCHIVE 0 +//#ifdef GIT_ARCHIVE +//# define GIT_COMMIT_ID "" +//# define GIT_COMMIT_DATE "$Format:%cD" +//#endif +// +//#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit +// +//#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk" -// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. -#define GIT_ARCHIVE 0 -#ifdef GIT_ARCHIVE -# define GIT_COMMIT_ID "" -# define GIT_COMMIT_DATE "$Format:%cD" -#endif +#define DEFINE_PLAIN_VERSION(maj,min,rev,build) \ + "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) -#define BUILD_DESC_FROM_COMMIT(maj,min,rev,build,commit) \ - "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-g" commit +#define PLAIN_VERSION DEFINE_PLAIN_VERSION(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) -#define BUILD_DESC_FROM_UNKNOWN(maj,min,rev,build) \ - "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) "-unk" - -#ifndef BUILD_DESC -# ifdef GIT_COMMIT_ID -# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) -# else -# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) -# endif -#endif +//#ifndef BUILD_DESC +//# ifdef GIT_COMMIT_ID +//# define BUILD_DESC BUILD_DESC_FROM_COMMIT(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_COMMIT_ID) +//# else +//# define BUILD_DESC BUILD_DESC_FROM_UNKNOWN(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD) +//# endif +//#endif #ifndef BUILD_DATE # ifdef GIT_COMMIT_DATE @@ -62,5 +73,13 @@ const std::string CLIENT_NAME("Satoshi"); # endif #endif +#ifdef GIT_HASH +# define BUILD_DESC_FROM_BUILD_H(maj,min,rev,build,commit,date) \ + "v" DO_STRINGIZE(maj) "." DO_STRINGIZE(min) "." DO_STRINGIZE(rev) "." DO_STRINGIZE(build) " (" commit " - " date ")" + +# define BUILD_DESC BUILD_DESC_FROM_BUILD_H(CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, CLIENT_VERSION_REVISION, CLIENT_VERSION_BUILD, GIT_HASH, BUILD_DATE) +#endif + const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX); const std::string CLIENT_DATE(BUILD_DATE); +const std::string CLIENT_PLAIN_VERSION(PLAIN_VERSION); diff --git a/src/version.h b/src/version.h index afe143a253..aacebd1b20 100644 --- a/src/version.h +++ b/src/version.h @@ -1,6 +1,14 @@ -// Copyright (c) 2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_VERSION_H #define BITCOIN_VERSION_H @@ -20,23 +28,27 @@ static const int CLIENT_VERSION = extern const std::string CLIENT_NAME; extern const std::string CLIENT_BUILD; extern const std::string CLIENT_DATE; +extern const std::string CLIENT_PLAIN_VERSION; // // database format versioning // -static const int DATABASE_VERSION = 70511; +static const int DATABASE_VERSION = 70512; // // network protocol versioning // -static const int PROTOCOL_VERSION = 60018; +static const int PROTOCOL_VERSION = 60042; // intial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; // disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 60018; +static const int MIN_PEER_PROTO_VERSION = 60030; + +// Enforce minimum protocol version for chain V3. +static const int LEGACY_CUTOFF_MIN_PROTOCOL_VERSION = 60040; // nTime field added to CAddress, starting with this version; // if possible, avoid requesting addresses nodes older than this diff --git a/src/wallet.cpp b/src/wallet.cpp index 7da0c7bb28..983332e265 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1,20 +1,31 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "txdb.h" #include "wallet.h" #include "walletdb.h" #include "bloom.h" #include "crypter.h" -#include "ui_interface.h" +#include "interface.h" #include "base58.h" #include "kernel.h" #include "coincontrol.h" #include "pbkdf2.h" +#include "chainparams_migration.h" +#include +#include #include +#include +#include + using namespace std; @@ -254,7 +265,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase) { LOCK2(cs_main, cs_wallet); - BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + for (const auto& pMasterKey : mapMasterKeys) { if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; @@ -268,13 +279,12 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase) UnlockStealthAddresses(vMasterKey); ExtKeyUnlock(vMasterKey); ProcessLockedAnonOutputs(); - SecureMsgWalletUnlocked(); if (fMakeExtKeyInitials) { fMakeExtKeyInitials = false; CWalletDB wdb(strWalletFile, "r+"); - if (ExtKeyCreateInitial(&wdb) != 0) + if (ExtKeyCreateInitial(&wdb, GetArg("-bip44key", "")) != 0) { LogPrintf("Warning: ExtKeyCreateInitial failed.\n"); }; @@ -295,7 +305,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, CCrypter crypter; CKeyingMaterial vMasterKey; - BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + for (auto& pMasterKey : mapMasterKeys) { if (!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; @@ -481,7 +491,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet. delete pwalletdbEncryption; - pwalletdbEncryption = NULL; + pwalletdbEncryption = nullptr; }; Lock(); @@ -537,7 +547,7 @@ CWallet::TxItems CWallet::OrderedTxItems(std::list& acentries, acentries.clear(); walletdb.ListAccountCreditDebit(strAccount, acentries); - BOOST_FOREACH(CAccountingEntry& entry, acentries) + for (CAccountingEntry& entry : acentries) { txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry))); }; @@ -552,7 +562,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock) // restored from backup or the user making copies of wallet.dat. { LOCK(cs_wallet); - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { if (tx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -572,7 +582,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock) } else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n])) { - LogPrintf("WalletUpdateSpent found spent coin %s SDC %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + LogPrintf("WalletUpdateSpent found spent coin %s ALIAS (public) %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); wtx.MarkSpent(txin.prevout.n); wtx.WriteToDisk(); NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); @@ -586,7 +596,7 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock) WalletTxMap::iterator mi = mapWallet.find(hash); CWalletTx& wtx = (*mi).second; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { if (tx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) @@ -611,7 +621,7 @@ void CWallet::MarkDirty() { { LOCK(cs_wallet); - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (auto& item : mapWallet) item.second.MarkDirty(); } } @@ -758,7 +768,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, const uint256& hashIn) { CScript scriptDefaultKey; scriptDefaultKey.SetDestination(vchDefaultKey.GetID()); - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) { if (txout.scriptPubKey == scriptDefaultKey) { @@ -788,7 +798,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, const uint256& hashIn) uint32_t nAdded = 0; // -- add unspent outputs to bloom filters - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { if (wtx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -832,6 +842,40 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, const uint256& hashIn) return true; } +static int GetBlockHeightFromHash(const uint256& blockHash) +{ + if (blockHash == 0) + return 0; + + if (nNodeMode == NT_FULL) + { + std::map::iterator mi = mapBlockIndex.find(blockHash); + if (mi == mapBlockIndex.end()) + return 0; + return mi->second->nHeight; + } else + { + std::map::iterator mi = mapBlockThinIndex.find(blockHash); + if (mi == mapBlockThinIndex.end() + && !fThinFullIndex + && pindexRear) + { + CTxDB txdb("r"); + CDiskBlockThinIndex diskindex; + if (txdb.ReadBlockThinIndex(blockHash, diskindex) + || diskindex.hashNext != 0) + { + return diskindex.nHeight; + }; + } else + { + return mi->second->nHeight; + }; + }; + + return 0; +} + // Add a transaction to the wallet, or update it. // pblock is optional, but should be provided if the transaction is known to be in a block. // If fUpdate is true, existing transactions will be updated. @@ -855,34 +899,37 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const uint256& ha { // Skip transactions that we know wouldn't be stealth... FindStealthTransactions(tx, mapNarr); + } - if (tx.nVersion == ANON_TXN_VERSION) - { - LOCK(cs_main); // cs_wallet is already locked - CWalletDB walletdb(strWalletFile, "cr+"); - CTxDB txdb("cr+"); + if (tx.nVersion == ANON_TXN_VERSION) + { + LOCK(cs_main); // cs_wallet is already locked + CWalletDB walletdb(strWalletFile, "cr+"); + CTxDB txdb("cr+"); - uint256 blockHash = (pblock ? (nNodeMode == NT_FULL ? ((CBlock*)pblock)->GetHash() : *(uint256*)pblock) : 0); + uint256 blockHash = (pblock ? (nNodeMode == NT_FULL ? ((CBlock*)pblock)->GetHash() : *(uint256*)pblock) : 0); - walletdb.TxnBegin(); - txdb.TxnBegin(); - std::vector vUpdatedTxns; - if (!ProcessAnonTransaction(&walletdb, &txdb, tx, blockHash, fIsMine, mapNarr, vUpdatedTxns)) - { - LogPrintf("ProcessAnonTransaction failed %s\n", hash.ToString().c_str()); - walletdb.TxnAbort(); - txdb.TxnAbort(); - return false; - } else - { - walletdb.TxnCommit(); - txdb.TxnCommit(); - for (std::vector::iterator it = vUpdatedTxns.begin(); - it != vUpdatedTxns.end(); ++it) - NotifyTransactionChanged(this, (*it)->first, CT_UPDATED); - }; + walletdb.TxnBegin(); + txdb.TxnBegin(); + std::vector vUpdatedTxns; + std::map mapAnonBlockStat; + if (!ProcessAnonTransaction(&walletdb, &txdb, tx, blockHash, fIsMine, mapNarr, vUpdatedTxns, mapAnonBlockStat)) + { + LogPrintf("ProcessAnonTransaction failed %s\n", hash.ToString().c_str()); + walletdb.TxnAbort(); + txdb.TxnAbort(); + return false; + } else + { + walletdb.TxnCommit(); + txdb.TxnCommit(); + int nBlockHeight = GetBlockHeightFromHash(blockHash); + AddToAnonBlockStats(mapAnonBlockStat, nBlockHeight); + for (std::vector::iterator it = vUpdatedTxns.begin(); + it != vUpdatedTxns.end(); ++it) + NotifyTransactionChanged(this, (*it)->first, CT_UPDATED); }; - } + }; if (fExisted || fIsMine || IsMine(tx) || IsFromMe(tx)) { @@ -914,6 +961,22 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const uint256& ha return false; } +void CWallet::AddToAnonBlockStats(const std::map& mapAnonBlockStat, int nBlockHeight) +{ + if(!nBlockHeight) + return; + + for (const auto & [nValue, newAnonBlockStat] : mapAnonBlockStat) + { + CAnonBlockStat& anonBlockStat = mapAnonBlockStats[nBlockHeight][nValue]; + anonBlockStat.nSpends += newAnonBlockStat.nSpends; + anonBlockStat.nOutputs += newAnonBlockStat.nOutputs; + anonBlockStat.nStakingOutputs += newAnonBlockStat.nStakingOutputs; + anonBlockStat.nCompromisedOutputs += newAnonBlockStat.nCompromisedOutputs; + } +} + + bool CWallet::EraseFromWallet(uint256 hash) { if (!fFileBacked) @@ -960,12 +1023,12 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const return 0; } -int64_t CWallet::GetShadowDebit(const CTxIn& txin) const +int64_t CWallet::GetSpectreDebit(const CTxIn& txin) const { if (!txin.IsAnonInput()) return 0; - // - amount of owned shadow decreased + // - amount of owned spectre decreased // TODO: store links in memory { @@ -994,7 +1057,7 @@ int64_t CWallet::GetShadowDebit(const CTxIn& txin) const return 0; }; -int64_t CWallet::GetShadowCredit(const CTxOut& txout) const +int64_t CWallet::GetSpectreCredit(const CTxOut& txout) const { if (!txout.IsAnonOutput()) return 0; @@ -1008,21 +1071,38 @@ int64_t CWallet::GetShadowCredit(const CTxOut& txout) const CPubKey pkCoin = txout.ExtractAnonPk(); + COutPoint outpoint; std::vector vchImage; - if (!walletdb.ReadOwnedAnonOutputLink(pkCoin, vchImage)) - return 0; + if (walletdb.ReadOwnedAnonOutputLink(pkCoin, vchImage)) + { + COwnedAnonOutput oao; + if (!walletdb.ReadOwnedAnonOutput(vchImage, oao)) + return 0; - COwnedAnonOutput oao; - if (!walletdb.ReadOwnedAnonOutput(vchImage, oao)) - return 0; + outpoint = oao.outpoint; + } + else + { + if (!IsCrypted()) + return 0; - WalletTxMap::const_iterator mi = mapWallet.find(oao.outpoint.hash); + // - tokens received with locked wallet won't have oao until wallet unlocked + CKeyID ckCoinId = pkCoin.GetID(); + CLockedAnonOutput lockedAo; + if (!walletdb.ReadLockedAnonOutput(ckCoinId, lockedAo)) + return 0; + + outpoint = lockedAo.outpoint; + }; + + + WalletTxMap::const_iterator mi = mapWallet.find(outpoint.hash); if (mi != mapWallet.end()) { const CWalletTx& prev = (*mi).second; - if (oao.outpoint.n < prev.vout.size()) + if (outpoint.n < prev.vout.size()) { - return prev.vout[oao.outpoint.n].nValue; + return prev.vout[outpoint.n].nValue; }; }; } // cs_wallet @@ -1041,7 +1121,17 @@ bool CWallet::IsChange(const CTxOut& txout) const // a better way of identifying which outputs are 'the send' and which are // 'the change' will need to be implemented (maybe extend CWalletTx to remember // which output, if any, was change). - if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*this, address)) + if (txout.IsAnonOutput()) { + // TODO ExtractDestination does currently not support anonoutputs + CKeyID ckidD = txout.ExtractAnonPk().GetID(); + + bool fIsMine = HaveKey(ckidD); + address = ckidD; + LOCK(cs_wallet); + if (fIsMine && !mapAddressBook.count(ckidD)) + return true; + } + else if (ExtractDestination(txout.scriptPubKey, address) && IsDestMine(*this, address)) { LOCK(cs_wallet); if (!mapAddressBook.count(address)) @@ -1096,8 +1186,7 @@ int CWalletTx::GetRequestCount() const return nRequests; } -void CWalletTx::GetAmounts(list >& listReceived, - list >& listSent, int64_t& nFee, string& strSentAccount) const +void CWalletTx::GetDestinationDetails(list& listReceived, list& listSent, int64_t& nFee, string& strSentAccount) const { nFee = 0; listReceived.clear(); @@ -1106,43 +1195,88 @@ void CWalletTx::GetAmounts(list >& listReceived, // Compute fee: int64_t nDebit = GetDebit(); - - //if (nVersion == ANON_TXN_VERSION) - // nDebit += GetShadowDebit(); - if (nDebit > 0) // debit>0 means we signed/sent this transaction { int64_t nValueOut = GetValueOut(); nFee = nDebit - nValueOut; }; + Currency currencyDestination = PUBLIC; + Currency currencySource = PUBLIC; + + if (IsAnonCoinStake()) + currencySource = PRIVATE; + else + for(const CTxIn& txin: vin) + { + if (txin.IsAnonInput()) + { + currencySource = PRIVATE; + break; + } + } + + bool generated = IsCoinBase() || IsCoinStake(); + // Sent/received. - BOOST_FOREACH(const CTxOut& txout, vout) + std::map mapStealthReceived; + std::map mapStealthSent; + std::map> mapDestinationSubs; + std::map mapStealthNarration; + + // Only need to handle txouts if AT LEAST one of these is true: + // 1) they debit from us (sent) + // 2) the output is to us (received) + for (uint32_t index = 0; index < vout.size(); ++index) { + const CTxOut& txout = vout[index]; + + // Skip special stake out + if (txout.scriptPubKey.empty()) + continue; + + // Don't report 'change' txouts + if (nDebit > 0 && !generated && pwallet->IsChange(txout)) + continue; + if (nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { - const CScript &s = txout.scriptPubKey; - CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); + currencyDestination = PRIVATE; + + CKeyID ckidD = txout.ExtractAnonPk().GetID(); bool fIsMine = pwallet->HaveKey(ckidD); + if (nDebit <= 0 && !fIsMine) + continue; + + std::string stealthAddress; + { + LOCK(pwallet->cs_wallet); + if (pwallet->mapAddressBook.count(ckidD)) + stealthAddress = pwallet->mapAddressBook.at(ckidD); + else + stealthAddress = "UNKNOWN"; + } - CTxDestination address = ckidD; + mapDestinationSubs[stealthAddress].push_back(ckidD); // If we are debited by the transaction, add the output as a "sent" entry if (nDebit > 0) - listSent.push_back(make_pair(address, txout.nValue)); + mapStealthSent[stealthAddress] += txout.nValue; // If we are receiving the output, add it as a "received" entry if (fIsMine) - listReceived.push_back(make_pair(address, txout.nValue)); + mapStealthReceived[stealthAddress] += txout.nValue; - continue; - }; + // Get narration for stealth address + std::string sNarr; + if (GetNarration(index, sNarr)) + // TODO for UNKNOWN we should concat narrations if multiple are available + mapStealthNarration[stealthAddress] = sNarr; - // Skip special stake out - if (txout.scriptPubKey.empty()) continue; + }; opcodetype firstOpCode; CScript::const_iterator pc = txout.scriptPubKey.begin(); @@ -1150,41 +1284,149 @@ void CWalletTx::GetAmounts(list >& listReceived, && firstOpCode == OP_RETURN) continue; - - bool fIsMine; - // Only need to handle txouts if AT LEAST one of these is true: - // 1) they debit from us (sent) - // 2) the output is to us (received) - if (nDebit > 0) - { - // Don't report 'change' txouts - if (pwallet->IsChange(txout)) - continue; - fIsMine = pwallet->IsMine(txout); - } else - if (!(fIsMine = pwallet->IsMine(txout))) + bool fIsMine = pwallet->IsMine(txout); + if (nDebit <= 0 && !fIsMine) continue; + // Get narration for output + std::string sNarr; + bool hasNarr = GetNarration(index, sNarr); + // In either case, we need to get the destination address CTxDestination address; if (!ExtractDestination(txout.scriptPubKey, address)) { - LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", + LogPrintf("CWalletTx::GetDestinationDetails: Unknown transaction type found, txid %s\n", this->GetHash().ToString().c_str()); address = CNoDestination(); - }; + } + else + { + LOCK(pwallet->cs_wallet); + if (pwallet->mapAddressBook.count(address)) + { + std::string stealthAddress = pwallet->mapAddressBook.at(address); + if (IsStealthAddressMappingLabel(stealthAddress, false)) + { + mapDestinationSubs[stealthAddress].push_back(address); + + // If we are debited by the transaction, add the output as a "sent" entry + if (nDebit > 0) + mapStealthSent[stealthAddress] += txout.nValue; + + // If we are receiving the output, add it as a "received" entry + if (fIsMine) + mapStealthReceived[stealthAddress] += txout.nValue; + + // Add narration to stealth output + if (hasNarr) + // TODO for UNKNOWN we should concat narrations if multiple are available + mapStealthNarration[stealthAddress] = sNarr; + + continue; + } + } + } // If we are debited by the transaction, add the output as a "sent" entry if (nDebit > 0) - listSent.push_back(make_pair(address, txout.nValue)); + listSent.emplace_back(address, std::vector(), txout.nValue, std::optional{index}, currencySource, sNarr); // If we are receiving the output, add it as a "received" entry if (fIsMine) - listReceived.push_back(make_pair(address, txout.nValue)); + listReceived.emplace_back(address, std::vector(), txout.nValue, std::optional{index}, currencyDestination, sNarr); }; + for (const auto & [address, amount] : mapStealthSent) { + CStealthAddress stealthAddress; + if (pwallet->GetStealthAddress(address, stealthAddress)) + listSent.emplace_back(stealthAddress, mapDestinationSubs[address], amount, std::nullopt, currencySource, mapStealthNarration[address]); + else + listSent.emplace_back(CNoDestination(), mapDestinationSubs[address], amount, std::nullopt, currencySource, mapStealthNarration[address]); + } + + for (const auto & [address, amount] : mapStealthReceived) { + CStealthAddress stealthAddress; + if (pwallet->GetStealthAddress(address, stealthAddress)) + listReceived.emplace_back(stealthAddress, mapDestinationSubs[address], amount, std::nullopt, currencyDestination, mapStealthNarration[address]); + else + listReceived.emplace_back(CNoDestination(), mapDestinationSubs[address], amount, std::nullopt, currencyDestination, mapStealthNarration[address]); + } +} + +bool CWallet::GetStealthAddress(const std::string& address, CStealthAddress& stealthAddressRet) const +{ + CStealthAddress sxAddr; + std::string sAddressToCompare; + + if (IsAnonOrStealthMappingLabel(address)) + sAddressToCompare = address.substr(sAnonPrefix.length(), 16); + else + { + if (sxAddr.SetEncoded(address)) + stealthAddressRet = sxAddr; + else + return false; + } + + for (const CStealthAddress & sa : stealthAddresses) + { + if (!sAddressToCompare.empty()) + { + std::string saEncoded = sa.Encoded(); + if (saEncoded.compare(0, sAddressToCompare.length(), sAddressToCompare) == 0) + { + stealthAddressRet = sa; + return true; + } + } + else if (sa == sxAddr) + { + stealthAddressRet = sa; + return true; + } + } + + ExtKeyAccountMap::const_iterator mi; + for (mi = mapExtAccounts.begin(); mi != mapExtAccounts.end(); ++mi) + { + CExtKeyAccount *ea = mi->second; + if (ea->mapStealthKeys.size() < 1) + continue; + + for (const auto& stealthKeys : ea->mapStealthKeys) + { + const CEKAStealthKey &aks = stealthKeys.second; + + if (!sAddressToCompare.empty()) + { + std::string saEncoded = aks.ToStealthAddress(); + if (saEncoded.compare(0, sAddressToCompare.length(), sAddressToCompare) == 0) + { + sxAddr.SetEncoded(saEncoded); + sxAddr.label = aks.sLabel; + stealthAddressRet = sxAddr; + return true; + } + } + else + { + CStealthAddress cekaSxAddr; + aks.SetSxAddr(cekaSxAddr); + if (cekaSxAddr == sxAddr) + { + sxAddr.label = aks.sLabel; + stealthAddressRet = sxAddr; + return true; + } + } + } + } + + return sxAddr.scan_pubkey.size() != 0; } + void CWalletTx::GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee) const { @@ -1192,30 +1434,30 @@ void CWalletTx::GetAccountAmounts(const std::string& strAccount, int64_t& nRecei int64_t allFee; std::string strSentAccount; - std::list > listReceived; - std::list > listSent; - GetAmounts(listReceived, listSent, allFee, strSentAccount); + std::list listReceived; + std::list listSent; + GetDestinationDetails(listReceived, listSent, allFee, strSentAccount); if (strAccount == strSentAccount) { - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& s, listSent) - nSent += s.second; + for(const auto & destination : listSent) + nSent += destination.amount; nFee = allFee; }; { LOCK(pwallet->cs_wallet); - BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) + for(const auto & destination : listReceived) { - if (pwallet->mapAddressBook.count(r.first)) + if (pwallet->mapAddressBook.count(destination.address)) { - std::map::const_iterator mi = pwallet->mapAddressBook.find(r.first); + std::map::const_iterator mi = pwallet->mapAddressBook.find(destination.address); if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount) - nReceived += r.second; + nReceived += destination.amount; } else if (strAccount.empty()) { - nReceived += r.second; + nReceived += destination.amount; }; }; } // pwallet->cs_wallet @@ -1229,7 +1471,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) if (SetMerkleBranch() < COPY_DEPTH) { std::vector vWorkQueue; - BOOST_FOREACH(const CTxIn& txin, vin) + for (const CTxIn& txin : vin) vWorkQueue.push_back(txin.prevout.hash); // This critsect is OK because txdb is already open @@ -1249,7 +1491,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) if (mi != pwallet->mapWallet.end()) { tx = (*mi).second; - BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev) + for (const CMerkleTx& txWalletPrev : (*mi).second.vtxPrev) mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev; } else if (mapWalletPrev.count(hash)) @@ -1270,7 +1512,7 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) if (nDepth < COPY_DEPTH) { - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) vWorkQueue.push_back(txin.prevout.hash); }; }; @@ -1285,10 +1527,139 @@ bool CWalletTx::WriteToDisk() return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this); } +uint32_t CWallet::ClearWalletTransactions(bool onlyUnaccepted) +{ + uint32_t nTransactions = 0; + char cbuf[256]; + { + LOCK2(cs_main, cs_wallet); + + CWalletDB walletdb(strWalletFile); + walletdb.TxnBegin(); + Dbc* pcursor = walletdb.GetTxnCursor(); + if (!pcursor) + throw std::runtime_error("Cannot get wallet DB cursor"); + + Dbt datKey; + Dbt datValue; + + datKey.set_flags(DB_DBT_USERMEM); + datValue.set_flags(DB_DBT_USERMEM); + + std::vector vchKey; + std::vector vchType; + std::vector vchKeyData; + std::vector vchValueData; + + vchKeyData.resize(100); + vchValueData.resize(100); + + datKey.set_ulen(vchKeyData.size()); + datKey.set_data(&vchKeyData[0]); + + datValue.set_ulen(vchValueData.size()); + datValue.set_data(&vchValueData[0]); + + unsigned int fFlags = DB_NEXT; // same as using DB_FIRST for new cursor + while (true) + { + int ret = pcursor->get(&datKey, &datValue, fFlags); + + if (ret == ENOMEM + || ret == DB_BUFFER_SMALL) + { + if (datKey.get_size() > datKey.get_ulen()) + { + vchKeyData.resize(datKey.get_size()); + datKey.set_ulen(vchKeyData.size()); + datKey.set_data(&vchKeyData[0]); + }; + + if (datValue.get_size() > datValue.get_ulen()) + { + vchValueData.resize(datValue.get_size()); + datValue.set_ulen(vchValueData.size()); + datValue.set_data(&vchValueData[0]); + }; + // -- try once more, when DB_BUFFER_SMALL cursor is not expected to move + ret = pcursor->get(&datKey, &datValue, fFlags); + }; + + if (ret == DB_NOTFOUND) + break; + else + if (datKey.get_data() == nullptr || datValue.get_data() == nullptr + || ret != 0) + { + snprintf(cbuf, sizeof(cbuf), "wallet DB error %d, %s", ret, db_strerror(ret)); + throw std::runtime_error(cbuf); + }; + + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.SetType(SER_DISK); + ssValue.clear(); + ssValue.write((char*)datKey.get_data(), datKey.get_size()); + + ssValue >> vchType; + + + std::string strType(vchType.begin(), vchType.end()); + + //LogPrintf("strType %s\n", strType.c_str()); + + if (strType == "tx") + { + uint256 hash; + ssValue >> hash; + + if (onlyUnaccepted) + { + const CWalletTx& wtx = mapWallet[hash]; + if (!wtx.IsInMainChain()) + { + if ((ret = pcursor->del(0)) != 0) + { + LogPrintf("Delete transaction failed %d, %s\n", ret, db_strerror(ret)); + continue; + } + mapWallet.erase(hash); + NotifyTransactionChanged(this, hash, CT_DELETED); + nTransactions++; + } + continue; + } + + if ((ret = pcursor->del(0)) != 0) + { + LogPrintf("Delete transaction failed %d, %s\n", ret, db_strerror(ret)); + continue; + } + + mapWallet.erase(hash); + NotifyTransactionChanged(this, hash, CT_DELETED); + + nTransactions++; + }; + }; + pcursor->close(); + walletdb.TxnCommit(); + + //pwalletMain->mapWallet.clear(); + + if (nNodeMode == NT_THIN) + { + // reset LastFilteredHeight + walletdb.WriteLastFilteredHeight(0); + } + } + + return nTransactions; +} + // Scan the block chain (starting in pindexStart) for transactions // from or to us. If fUpdate is true, found transactions that already // exist in the wallet will be updated. -int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) +int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, std::function funcProgress, int progressBatchSize) { if (fDebug) LogPrintf("ScanForWalletTransactions()\n"); @@ -1300,45 +1671,50 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) }; int ret = 0; - int64_t nTimeFirstKeyTmp = nTimeFirstKey; int nCurBestHeight = nBestHeight; fReindexing = true; - // When scanning from a certain height, people could be interested in rebuilding stealth address and anonymous transaction cache. - if(pindexStart->nHeight > 1) - nTimeFirstKey = pindexStart->nTime; - + // Note: Every block is scanned to rebuild the anonymous transaction cache + // therefore nTimeFirstKey (time of first wallet key) is not considered as filter CBlockIndex* pindex = pindexStart; { LOCK2(cs_main, cs_wallet); + + // call progress callback on start + if (funcProgress) funcProgress(pindex->nHeight, nCurBestHeight, ret); + + CTxDB txdb; while (pindex) { - // no need to read and scan block, if block was created before - // our wallet birthday (as adjusted for block time variability) - if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) - { - pindex = pindex->pnext; - continue; - }; - CBlock block; block.ReadFromDisk(pindex, true); nBestHeight = pindex->nHeight; - BOOST_FOREACH(CTransaction& tx, block.vtx) + + for (CTransaction& tx : block.vtx) { uint256 hash = tx.GetHash(); if (AddToWalletIfInvolvingMe(tx, hash, &block, fUpdate)) ret++; }; + if (funcProgress && pindex->nHeight % progressBatchSize == 0 && !funcProgress(pindex->nHeight, nCurBestHeight, ret)) { + // abort scanning indicated + break; + }; pindex = pindex->pnext; }; + + // call progress callback on end + if (funcProgress) funcProgress(nCurBestHeight, nCurBestHeight, ret); + } // cs_main, cs_wallet - // Reset nTimeFirstKey - nTimeFirstKey = nTimeFirstKeyTmp; nBestHeight = nCurBestHeight; fReindexing = false; + // Make sure anon cache reflects restored nBestHeight + if (!CacheAnonStats(nBestHeight)) + LogPrintf("ScanForWalletTransactions() : CacheAnonStats() failed.\n"); + return ret; } @@ -1388,7 +1764,7 @@ void CWallet::ReacceptWalletTransactions() fRepeat = false; std::vector vMissingTx; - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (auto& item : mapWallet) { CWalletTx& wtx = item.second; if ((wtx.IsCoinBase() && wtx.IsSpent(0)) @@ -1421,7 +1797,7 @@ void CWallet::ReacceptWalletTransactions() if (fUpdated) { - LogPrintf("ReacceptWalletTransactions found spent coin %s SDC %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); + LogPrintf("ReacceptWalletTransactions found spent coin %s ALIAS (public) %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str()); wtx.MarkDirty(); wtx.WriteToDisk(); }; @@ -1444,7 +1820,7 @@ void CWallet::ReacceptWalletTransactions() void CWalletTx::RelayWalletTransaction(CTxDB& txdb) { - BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) + for (const CMerkleTx& tx : vtxPrev) { if (!(tx.IsCoinBase() || tx.IsCoinStake())) { @@ -1500,7 +1876,7 @@ void CWallet::ResendWalletTransactions(bool fForce) { LOCK(cs_wallet); // Sort them in chronological order - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (auto& item : mapWallet) { CWalletTx& wtx = item.second; // Don't rebroadcast until it's had plenty of time that @@ -1510,7 +1886,7 @@ void CWallet::ResendWalletTransactions(bool fForce) }; } // cs_wallet - BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) + for (auto& item : mapSorted) { CWalletTx& wtx = *item.second; if (wtx.CheckTransaction()) @@ -1549,7 +1925,7 @@ int64_t CWallet::GetBalance() const return nTotal; } -int64_t CWallet::GetShadowBalance() const +int64_t CWallet::GetSpectreBalance() const { int64_t nTotal = 0; @@ -1558,8 +1934,8 @@ int64_t CWallet::GetShadowBalance() const for (WalletTxMap::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - if (pcoin->IsTrusted() && pcoin->nVersion == ANON_TXN_VERSION) - nTotal += pcoin->GetAvailableShadowCredit(); + if (pcoin->nVersion == ANON_TXN_VERSION && pcoin->IsTrusted()) + nTotal += pcoin->GetAvailableSpectreCredit(); }; } @@ -1582,21 +1958,48 @@ int64_t CWallet::GetUnconfirmedBalance() const return nTotal; } -int64_t CWallet::GetImmatureBalance() const +int64_t CWallet::GetUnconfirmedSpectreBalance() const { int64_t nTotal = 0; { LOCK2(cs_main, cs_wallet); for (WalletTxMap::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { - const CWalletTx& pcoin = (*it).second; + const CWalletTx* pcoin = &(*it).second; + if (pcoin->nVersion != ANON_TXN_VERSION || pcoin->IsCoinBase() || pcoin->IsCoinStake()) + continue; + if (!pcoin->IsFinal() || (pcoin->GetDepthInMainChain() >= 0 && pcoin->GetDepthInMainChain() < MIN_ANON_SPEND_DEPTH)) + { + int64_t nSPEC = 0, nSpectre = 0; + if (CWallet::GetCredit(*pcoin, nSPEC, nSpectre)) + nTotal += nSpectre; + } + }; + } + return nTotal; +} + + +int64_t CWallet::GetImmatureBalance() const +{ + int64_t nTotal = 0; + { + LOCK2(cs_main, cs_wallet); + for (WalletTxMap::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx& pcoin = (*it).second; if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain()) - nTotal += GetCredit(pcoin); + nTotal += pcoin.GetCredit(); } } return nTotal; } +int64_t CWallet::GetImmatureSpectreBalance() const +{ + return 0; // not used +} + // populate vCoins with vector of spendable COutputs void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { @@ -1636,19 +2039,22 @@ void CWallet::AvailableCoinsForStaking(std::vector& vCoins, unsigned in { LOCK2(cs_main, cs_wallet); + + bool fPoSv3 = Params().IsProtocolV3(nBestHeight); + for (WalletTxMap::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; // Filtering by tx timestamp instead of block timestamp may give false positives but never false negatives - if (pcoin->nTime + nStakeMinAge > nSpendTime) + if ((!fPoSv3 || !Params().IsForkV3(nSpendTime)) && pcoin->nTime + nStakeMinAge > nSpendTime) continue; if (pcoin->GetBlocksToMaturity() > 0) continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < 1) + if (nDepth < 1 || (fPoSv3 && nDepth < Params().GetStakeMinConfirmations(nSpendTime))) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) @@ -1711,7 +2117,30 @@ int64_t CWallet::GetStake() const { const CWalletTx* pcoin = &(*it).second; if (pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0) - nTotal += CWallet::GetCredit(*pcoin); + { + int64_t nSPEC = 0, nSpectre = 0; + if (CWallet::GetCredit(*pcoin, nSPEC, nSpectre)) + nTotal += nSPEC; + } + }; + return nTotal; +} + +int64_t CWallet::GetSpectreStake() const +{ + int64_t nTotal = 0; + LOCK2(cs_main, cs_wallet); + for (WalletTxMap::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->nVersion != ANON_TXN_VERSION) + continue; + if (pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0) + { + int64_t nSPEC = 0, nSpectre = 0; + if (CWallet::GetCredit(*pcoin, nSPEC, nSpectre)) + nTotal += nSpectre; + } }; return nTotal; } @@ -1737,14 +2166,17 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, // List of values less than target pair > coinLowestLarger; coinLowestLarger.first = std::numeric_limits::max(); - coinLowestLarger.second.first = NULL; + coinLowestLarger.second.first = nullptr; std::vector > > vValue; int64_t nTotalLower = 0; - random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); +// Removed with c++17, see https://en.cppreference.com/w/cpp/algorithm/random_shuffle +// random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); + std::random_device rng; + std::mt19937 urng(rng()); + std::shuffle(vCoins.begin(), vCoins.end(), urng); - BOOST_FOREACH(COutput output, vCoins) - { + for (const COutput& output : vCoins) { const CWalletTx *pcoin = output.tx; if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) @@ -1789,7 +2221,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, if (nTotalLower < nTargetValue) { - if (coinLowestLarger.second.first == NULL) + if (coinLowestLarger.second.first == nullptr) return false; setCoinsRet.insert(coinLowestLarger.second); nValueRet += coinLowestLarger.first; @@ -1814,7 +2246,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, nValueRet += coinLowestLarger.first; } else - { + { for (unsigned int i = 0; i < vValue.size(); i++) if (vfBest[i]) { @@ -1844,7 +2276,7 @@ bool CWallet::SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, set return all selected outputs (we want all selected to go into the transaction for sure) if (coinControl && coinControl->HasSelected()) { - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) { nValueRet += out.tx->vout[out.i].nValue; setCoinsRet.insert(make_pair(out.tx, out.i)); @@ -1860,7 +2292,7 @@ bool CWallet::SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64_t& nValueRet) const +bool CWallet::SelectCoinsForStaking(int64_t nMaxAmount, unsigned int nSpendTime, set >& setCoinsRet, int64_t& nValueRet) const { std::vector vCoins; AvailableCoinsForStaking(vCoins, nSpendTime); @@ -1868,32 +2300,18 @@ bool CWallet::SelectCoinsForStaking(int64_t nTargetValue, unsigned int nSpendTim setCoinsRet.clear(); nValueRet = 0; - BOOST_FOREACH(COutput output, vCoins) - { + for (const COutput& output : vCoins) { const CWalletTx *pcoin = output.tx; int i = output.i; - - // Stop if we've chosen enough inputs - if (nValueRet >= nTargetValue) - break; - int64_t n = pcoin->vout[i].nValue; - pair > coin = make_pair(n, make_pair(pcoin, i)); + // Skip if the selection of the coin would overflow the target + if (nValueRet + n > nMaxAmount) + continue; - if (n >= nTargetValue) - { - // If input value is greater or equal to target then simply insert - // it into the current subset and exit - setCoinsRet.insert(coin.second); - nValueRet += coin.first; - break; - } else - if (n < nTargetValue + CENT) - { - setCoinsRet.insert(coin.second); - nValueRet += coin.first; - }; + pair > coin = make_pair(n, make_pair(pcoin, i)); + setCoinsRet.insert(coin.second); + nValueRet += coin.first; } return true; @@ -1903,7 +2321,7 @@ bool CWallet::SelectCoinsForStaking(int64_t nTargetValue, unsigned int nSpendTim bool CWallet::CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, int64_t& nFeeRet, int32_t& nChangePos, const CCoinControl* coinControl) { int64_t nValue = 0; - BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend) + for (const auto& s : vecSend) { if (nValue < 0) return false; @@ -1930,8 +2348,7 @@ bool CWallet::CreateTransaction(const std::vector >& int64_t nTotalValue = nValue + nFeeRet; double dPriority = 0; // vouts to the payees - BOOST_FOREACH(const PAIRTYPE(CScript, int64_t)& s, vecSend) - { + for (const auto& s : vecSend) { wtxNew.vout.push_back(CTxOut(s.second, s.first)); }; @@ -1941,7 +2358,7 @@ bool CWallet::CreateTransaction(const std::vector >& if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn, coinControl)) return false; - BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + for (const auto& pcoin : setCoins) { int64_t nCredit = pcoin.first->vout[pcoin.second].nValue; dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain(); @@ -1951,9 +2368,9 @@ bool CWallet::CreateTransaction(const std::vector >& // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE // or until nChange becomes zero // NOTE: this depends on the exact behaviour of GetMinFee - if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) + if (nFeeRet < nMinTxFee && nChange > 0 && nChange < CENT) { - int64_t nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); + int64_t nMoveToFee = min(nChange, nMinTxFee - nFeeRet); nChange -= nMoveToFee; nFeeRet += nMoveToFee; }; @@ -1999,17 +2416,17 @@ bool CWallet::CreateTransaction(const std::vector >& position--; }; }; - wtxNew.vout.insert(position, CTxOut(nChange, scriptChange)); + position = wtxNew.vout.insert(position, CTxOut(nChange, scriptChange)); nChangePos = std::distance(wtxNew.vout.begin(), position); }; // Fill vin - BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) + for (const auto& coin : setCoins) wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second)); // Sign int nIn = 0; - BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins) + for (const auto& coin : setCoins) if (!SignSignature(*this, *coin.first, wtxNew, nIn++)) { LogPrintf("%s: Error SignSignature failed.\n", __func__); @@ -2356,169 +2773,6 @@ bool CWallet::UpdateStealthAddress(std::string &addr, std::string &label, bool a return true; }; -bool CWallet::CreateStealthTransaction(CScript scriptPubKey, int64_t nValue, std::vector& P, std::vector& narr, std::string& sNarr, CWalletTx& wtxNew, int64_t& nFeeRet, const CCoinControl* coinControl) -{ - std::vector > vecSend; - vecSend.push_back(make_pair(scriptPubKey, nValue)); - - CScript scriptP = CScript() << OP_RETURN << P; - if (narr.size() > 0) - scriptP = scriptP << OP_RETURN << narr; - - vecSend.push_back(make_pair(scriptP, 0)); - - // -- shuffle inputs, change output won't mix enough as it must be not fully random for plantext narrations - std::random_shuffle(vecSend.begin(), vecSend.end()); - - int nChangePos; - bool rv = CreateTransaction(vecSend, wtxNew, nFeeRet, nChangePos, coinControl); - - // -- the change txn is inserted in a random pos, check here to match narr to output - if (rv && narr.size() > 0) - { - for (unsigned int k = 0; k < wtxNew.vout.size(); ++k) - { - if (wtxNew.vout[k].scriptPubKey != scriptPubKey - || wtxNew.vout[k].nValue != nValue) - continue; - - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", k) < 1) - { - LogPrintf("%s: Error creating narration key.", __func__); - break; - }; - wtxNew.mapValue[key] = sNarr; - break; - }; - }; - - return rv; -}; - -string CWallet::SendStealthMoney(CScript scriptPubKey, int64_t nValue, std::vector& P, std::vector& narr, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee) -{ - int64_t nFeeRequired; - - if (IsLocked()) - { - string strError = _("Error: Wallet locked, unable to create transaction "); - LogPrintf("SendStealthMoney(): %s", strError.c_str()); - return strError; - }; - - if (fWalletUnlockStakingOnly) - { - string strError = _("Error: Wallet unlocked for staking only, unable to create transaction."); - LogPrintf("SendStealthMoney(): %s", strError.c_str()); - return strError; - }; - - if (!CreateStealthTransaction(scriptPubKey, nValue, P, narr, sNarr, wtxNew, nFeeRequired)) - { - string strError; - if (nValue + nFeeRequired > GetBalance()) - strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds "), FormatMoney(nFeeRequired).c_str()); - else - strError = _("Error: Transaction creation failed "); - LogPrintf("SendStealthMoney(): %s\n", strError.c_str()); - return strError; - }; - - if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending..."))) - return "ABORTED"; - - if (!CommitTransaction(wtxNew)) - return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); - - return ""; -}; - -bool CWallet::SendStealthMoneyToDestination(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee) -{ - // -- Check amount - if (nValue <= 0) - { - sError = "Invalid amount"; - return false; - }; - if (nValue + nTransactionFee > GetBalance()) - { - sError = "Insufficient funds"; - return false; - }; - - ec_secret ephem_secret; - ec_secret secretShared; - ec_point pkSendTo; - ec_point ephem_pubkey; - - if (GenerateRandomSecret(ephem_secret) != 0) - { - sError = "GenerateRandomSecret failed."; - return false; - }; - - if (StealthSecret(ephem_secret, sxAddress.scan_pubkey, sxAddress.spend_pubkey, secretShared, pkSendTo) != 0) - { - sError = "Could not generate receiving public key."; - return false; - }; - - CPubKey cpkTo(pkSendTo); - if (!cpkTo.IsValid()) - { - sError = "Invalid public key generated."; - return false; - }; - - CKeyID ckidTo = cpkTo.GetID(); - - CBitcoinAddress addrTo(ckidTo); - - if (SecretToPublicKey(ephem_secret, ephem_pubkey) != 0) - { - sError = "Could not generate ephem public key."; - return false; - }; - - if (fDebug) - { - LogPrintf("Stealth send to generated pubkey %u: %s\n", pkSendTo.size(), HexStr(pkSendTo).c_str()); - LogPrintf("hash %s\n", addrTo.ToString().c_str()); - LogPrintf("ephem_pubkey %u: %s\n", ephem_pubkey.size(), HexStr(ephem_pubkey).c_str()); - }; - - std::vector vchNarr; - if (sNarr.length() > 0) - { - SecMsgCrypter crypter; - crypter.SetKey(&secretShared.e[0], &ephem_pubkey[0]); - - if (!crypter.Encrypt((uint8_t*)&sNarr[0], sNarr.length(), vchNarr)) - { - sError = "Narration encryption failed."; - return false; - }; - - if (vchNarr.size() > MAX_STEALTH_NARRATION_SIZE) - { - sError = "Encrypted narration is too long."; - return false; - }; - }; - - // -- Parse Bitcoin address - CScript scriptPubKey; - scriptPubKey.SetDestination(addrTo.Get()); - - if ((sError = SendStealthMoney(scriptPubKey, nValue, ephem_pubkey, vchNarr, sNarr, wtxNew, fAskFee)) != "") - return false; - - - return true; -} - bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNarr) { if (fDebug) @@ -2541,7 +2795,7 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar char cbuf[256]; int32_t nOutputIdOuter = -1; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { nOutputIdOuter++; // -- for each OP_RETURN need to check all other valid outputs @@ -2584,7 +2838,7 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar int32_t nOutputId = -1; nStealth++; - BOOST_FOREACH(const CTxOut& txoutB, tx.vout) + for (const CTxOut& txoutB : tx.vout) { nOutputId++; @@ -2607,8 +2861,9 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar CKeyID ckidMatch = boost::get(address); - if (HaveKey(ckidMatch)) // no point checking if already have key - continue; + bool haveKey = HaveKey(ckidMatch); // if we allready have the key we still reprocess to store address mapping + if (haveKey && fDebug) + LogPrintf("Found existing stealth output key - txn has been processed before, reprocessing to store mapping.\n"); std::set::iterator it; for (it = stealthAddresses.begin(); it != stealthAddresses.end(); ++it) @@ -2637,81 +2892,89 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar if (fDebug) LogPrintf("Found stealth txn to address %s\n", it->Encoded().c_str()); - if (IsLocked()) + if (haveKey) { + std::string sLabel = sStealthPrefix + it->Encoded().substr(0, 16) + "..."; + SetAddressBookName(ckidE, sLabel); + } + else { - if (fDebug) - LogPrintf("Wallet locked, adding key without secret.\n"); - - // -- add key without secret - std::vector vchEmpty; - AddCryptedKey(cpkE, vchEmpty); - CKeyID keyId = cpkE.GetID(); - CBitcoinAddress coinAddress(keyId); - std::string sLabel = it->Encoded(); - SetAddressBookName(keyId, sLabel); - - CPubKey cpkEphem(vchEphemPK); - CPubKey cpkScan(it->scan_pubkey); - CStealthKeyMetadata lockedSkMeta(cpkEphem, cpkScan); + if (IsLocked()) + { + if (fDebug) + LogPrintf("Wallet locked, adding key without secret.\n"); + + // -- add key without secret + std::vector vchEmpty; + AddCryptedKey(cpkE, vchEmpty); + CKeyID keyId = cpkE.GetID(); + CBitcoinAddress coinAddress(keyId); + std::string sLabel = sStealthPrefix + it->Encoded().substr(0, 16) + "..."; + SetAddressBookName(keyId, sLabel); + + CPubKey cpkEphem(vchEphemPK); + CPubKey cpkScan(it->scan_pubkey); + CStealthKeyMetadata lockedSkMeta(cpkEphem, cpkScan); + + if (!CWalletDB(strWalletFile).WriteStealthKeyMeta(keyId, lockedSkMeta)) + LogPrintf("WriteStealthKeyMeta failed for %s.\n", coinAddress.ToString().c_str()); + + mapStealthKeyMeta[keyId] = lockedSkMeta; + nFoundStealth++; + } else + { + if (it->spend_secret.size() != EC_SECRET_SIZE) + continue; - if (!CWalletDB(strWalletFile).WriteStealthKeyMeta(keyId, lockedSkMeta)) - LogPrintf("WriteStealthKeyMeta failed for %s.\n", coinAddress.ToString().c_str()); + memcpy(&sSpend.e[0], &it->spend_secret[0], EC_SECRET_SIZE); - mapStealthKeyMeta[keyId] = lockedSkMeta; - nFoundStealth++; - } else - { - if (it->spend_secret.size() != EC_SECRET_SIZE) - continue; + if (StealthSharedToSecretSpend(sShared, sSpend, sSpendR) != 0) + { + LogPrintf("StealthSharedToSecretSpend() failed.\n"); + continue; + }; - memcpy(&sSpend.e[0], &it->spend_secret[0], EC_SECRET_SIZE); + CKey ckey; + ckey.Set(&sSpendR.e[0], true); - if (StealthSharedToSecretSpend(sShared, sSpend, sSpendR) != 0) - { - LogPrintf("StealthSharedToSecretSpend() failed.\n"); - continue; - }; + if (!ckey.IsValid()) + { + LogPrintf("%s: Reconstructed key is invalid.\n", __func__); + continue; + }; - CKey ckey; - ckey.Set(&sSpendR.e[0], true); + CPubKey cpkT = ckey.GetPubKey(); + if (!cpkT.IsValid()) + { + LogPrintf("%s: cpkT is invalid.\n", __func__); + continue; + }; - if (!ckey.IsValid()) - { - LogPrintf("%s: Reconstructed key is invalid.\n", __func__); - continue; - }; + CKeyID keyID = cpkT.GetID(); - CPubKey cpkT = ckey.GetPubKey(); - if (!cpkT.IsValid()) - { - LogPrintf("%s: cpkT is invalid.\n", __func__); - continue; - }; + if (keyID != ckidMatch) + { + LogPrintf("%s: Spend key mismatch!\n", __func__); + continue; + }; - CKeyID keyID = cpkT.GetID(); + if (fDebug) + { + CBitcoinAddress coinAddress(keyID); + LogPrintf("Adding key %s.\n", coinAddress.ToString().c_str()); + }; - if (keyID != ckidMatch) - { - LogPrintf("%s: Spend key mismatch!\n", __func__); - continue; - }; + if (!AddKeyPubKey(ckey, cpkT)) + { + LogPrintf("%s: AddKeyPubKey failed.\n", __func__); + continue; + }; - if (fDebug) - { - CBitcoinAddress coinAddress(keyID); - LogPrintf("Adding key %s.\n", coinAddress.ToString().c_str()); - }; - if (!AddKeyPubKey(ckey, cpkT)) - { - LogPrintf("%s: AddKeyPubKey failed.\n", __func__); - continue; + std::string sLabel = sStealthPrefix + it->Encoded().substr(0, 16) + "..."; + SetAddressBookName(keyID, sLabel); + nFoundStealth++; }; - - std::string sLabel = it->Encoded(); - SetAddressBookName(keyID, sLabel); - nFoundStealth++; - }; + } txnMatch = true; break; @@ -2750,46 +3013,54 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar if (ckidMatch != ckidE) continue; - if (fDebug) + if (haveKey) { + // - for compatability + std::string sLabel = sStealthPrefix + aks.ToStealthAddress().substr(0, 16) + "..."; + SetAddressBookName(ckidMatch, sLabel); + } + else { - LogPrintf("Found stealth txn to address %s\n", aks.ToStealthAddress().c_str()); - - // - check key if not locked - if (!IsLocked()) + if (fDebug) { - CKey kTest; + LogPrintf("Found stealth txn to address %s\n", aks.ToStealthAddress().c_str()); - if (0 != ea->ExpandStealthChildKey(&aks, sShared, kTest)) + // - check key if not locked + if (!IsLocked()) { - LogPrintf("%s: Error: ExpandStealthChildKey failed! %s.\n", __func__, aks.ToStealthAddress().c_str()); - continue; + CKey kTest; + + if (0 != ea->ExpandStealthChildKey(&aks, sShared, kTest)) + { + LogPrintf("%s: Error: ExpandStealthChildKey failed! %s.\n", __func__, aks.ToStealthAddress().c_str()); + continue; + }; + + CKeyID kTestId = kTest.GetPubKey().GetID(); + if (kTestId != ckidMatch) + { + LogPrintf("Error: Spend key mismatch!\n"); + continue; + }; + CBitcoinAddress coinAddress(kTestId); + LogPrintf("Debug: ExpandStealthChildKey matches! %s, %s.\n", aks.ToStealthAddress().c_str(), coinAddress.ToString().c_str()); }; - CKeyID kTestId = kTest.GetPubKey().GetID(); - if (kTestId != ckidMatch) - { - LogPrintf("Error: Spend key mismatch!\n"); - continue; - }; - CBitcoinAddress coinAddress(kTestId); - LogPrintf("Debug: ExpandStealthChildKey matches! %s, %s.\n", aks.ToStealthAddress().c_str(), coinAddress.ToString().c_str()); }; - }; + // - don't need to extract key now, wallet may be locked - // - don't need to extract key now, wallet may be locked + CKeyID idStealthKey = aks.GetID(); + CEKASCKey kNew(idStealthKey, sShared); + if (0 != ExtKeySaveKey(ea, ckidMatch, kNew)) + { + LogPrintf("%s: Error: ExtKeySaveKey failed!\n", __func__); + continue; + }; - CKeyID idStealthKey = aks.GetID(); - CEKASCKey kNew(idStealthKey, sShared); - if (0 != ExtKeySaveKey(ea, ckidMatch, kNew)) - { - LogPrintf("%s: Error: ExtKeySaveKey failed!\n", __func__); - continue; - }; - - // - for compatability - std::string sLabel = aks.ToStealthAddress(); - SetAddressBookName(ckidMatch, sLabel); + // - for compatability + std::string sLabel = sStealthPrefix + aks.ToStealthAddress().substr(0, 16) + "..."; + SetAddressBookName(ckidMatch, sLabel); + } txnMatch = true; break; @@ -2827,40 +3098,6 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar return true; }; -static int GetBlockHeightFromHash(const uint256& blockHash) -{ - if (blockHash == 0) - return 0; - - if (nNodeMode == NT_FULL) - { - std::map::iterator mi = mapBlockIndex.find(blockHash); - if (mi == mapBlockIndex.end()) - return 0; - return mi->second->nHeight; - } else - { - std::map::iterator mi = mapBlockThinIndex.find(blockHash); - if (mi == mapBlockThinIndex.end() - && !fThinFullIndex - && pindexRear) - { - CTxDB txdb("r"); - CDiskBlockThinIndex diskindex; - if (txdb.ReadBlockThinIndex(blockHash, diskindex) - || diskindex.hashNext != 0) - { - return diskindex.nHeight; - }; - } else - { - return mi->second->nHeight; - }; - }; - - return 0; -} - static int IsAnonCoinCompromised(CTxDB *txdb, CPubKey &pubKey, CAnonOutput &ao, ec_point &vchSpentImage) { // check if its been compromised (signer known) @@ -2874,114 +3111,14 @@ static int IsAnonCoinCompromised(CTxDB *txdb, CPubKey &pubKey, CAnonOutput &ao, { ao.nCompromised = 1; txdb->WriteAnonOutput(pubKey, ao); - if(fDebugRingSig) - LogPrintf("Spent key image, mark as compromised: %s\n", pubKey.GetID().ToString()); + fStaleAnonCache = true; // force rebuild of anon cache + LogPrintf("Spent key image, mark as compromised: %s\n", pubKey.GetID().ToString()); return 1; } return 0; } -bool CWallet::UpdateAnonTransaction(CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash) -{ - uint256 txnHash = tx.GetHash(); - if (fDebugRingSig) - { - LogPrintf("UpdateAnonTransaction() tx: %s\n", txnHash.GetHex().c_str()); - AssertLockHeld(cs_main); - AssertLockHeld(cs_wallet); - }; - - // -- update txns not received in a block - - int nNewHeight = GetBlockHeightFromHash(blockHash); - - CKeyImageSpent spentKeyImage; - for (uint32_t i = 0; i < tx.vin.size(); ++i) - { - const CTxIn& txin = tx.vin[i]; - - if (!txin.IsAnonInput()) - continue; - - const CScript &s = txin.scriptSig; - - std::vector vchImage; - txin.ExtractKeyImage(vchImage); - - int nRingSize = txin.ExtractRingSize(); - - // -- get nCoinValue by reading first ring element - CPubKey pkRingCoin; - CAnonOutput ao; - CTxIndex txindex; - - const uint8_t *pPubkeys; - if (nRingSize > 1 && s.size() == 2 + EC_SECRET_SIZE + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE) * nRingSize) - { - pPubkeys = &s[2 + EC_SECRET_SIZE + EC_SECRET_SIZE * nRingSize]; - } else - if (s.size() >= 2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE + EC_SECRET_SIZE) * nRingSize) - { - pPubkeys = &s[2]; - } else - return error("%s: Input %d scriptSig too small.", __func__, i); - - pkRingCoin = CPubKey(&pPubkeys[0 * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); - - if (!ptxdb->ReadAnonOutput(pkRingCoin, ao)) - { - LogPrintf("UpdateAnonTransaction(): Error input %u AnonOutput %s not found.\n", i, pkRingCoin.GetID().ToString()); - //LogPrintf("%s, %s\n", pkRingCoin.GetID().ToString(), CBitcoinAddress(pkRingCoin.GetID()).ToString()); - return false; - }; - int64_t nCoinValue = ao.nValue; - - spentKeyImage.txnHash = txnHash; - spentKeyImage.inputNo = i; - spentKeyImage.nValue = nCoinValue; - - if (!ptxdb->WriteKeyImage(vchImage, spentKeyImage)) - { - LogPrintf("UpdateAnonTransaction(): Error input %d WriteKeyImage failed %s .\n", i, HexStr(vchImage).c_str()); - return false; - } - - } - - for (uint32_t i = 0; i < tx.vout.size(); ++i) - { - const CTxOut& txout = tx.vout[i]; - - if (!txout.IsAnonOutput()) - continue; - - const CScript &s = txout.scriptPubKey; - - CPubKey pkCoin = CPubKey(&s[2+1], EC_COMPRESSED_SIZE); - CAnonOutput ao; - if (!ptxdb->ReadAnonOutput(pkCoin, ao)) - { - LogPrintf("ReadAnonOutput %d failed.\n", i); - return false; - }; - - ao.nBlockHeight = nNewHeight; - - if (!ptxdb->WriteAnonOutput(pkCoin, ao)) - { - LogPrintf("ReadAnonOutput %d failed.\n", i); - return false; - }; - - LogPrintf("UpdateAnonTransaction(): updateDepth: %d, value: %d\n", nNewHeight, ao.nValue); - mapAnonOutputStats[ao.nValue].updateDepth(nNewHeight, ao.nValue); - }; - - return true; -}; - - -bool CWallet::UndoAnonTransaction(const CTransaction& tx) +bool CWallet::UndoAnonTransaction(const CTransaction& tx, const std::map * const mapPubStealth, bool fEraseTx) { if (fDebugRingSig) LogPrintf("UndoAnonTransaction() tx: %s\n", tx.GetHash().GetHex().c_str()); @@ -2994,6 +3131,14 @@ bool CWallet::UndoAnonTransaction(const CTransaction& tx) CWalletDB walletdb(strWalletFile, "cr+"); CTxDB txdb("cr+"); + // Remove all pub to stealth key mappings + if (mapPubStealth != nullptr) + { + for (auto& element : *mapPubStealth) { + DelAddressBookName(element.first, &walletdb); + } + } + for (unsigned int i = 0; i < tx.vin.size(); ++i) { const CTxIn& txin = tx.vin[i]; @@ -3094,6 +3239,7 @@ bool CWallet::UndoAnonTransaction(const CTransaction& tx) }; mapAnonOutputStats[ao.nValue].decExists(ao.nValue); + mapAnonOutputStats[ao.nValue].nStakes -= ao.fCoinStake; if (!txdb.EraseAnonOutput(pkCoin)) { @@ -3108,7 +3254,8 @@ bool CWallet::UndoAnonTransaction(const CTransaction& tx) if (!walletdb.ReadOwnedAnonOutputLink(pkCoin, vchImage)) { - LogPrintf("ReadOwnedAnonOutputLink(): %u failed - output wasn't owned.\n", i); + if (fDebugRingSig) + LogPrintf("ReadOwnedAnonOutputLink(): %u failed - output wasn't owned.\n", i); continue; }; @@ -3126,18 +3273,20 @@ bool CWallet::UndoAnonTransaction(const CTransaction& tx) }; - if (!walletdb.EraseTx(txnHash)) + if (fEraseTx) // owned coinstake transaction are kept in the wallet { - LogPrintf("UndoAnonTransaction() EraseTx %s failed.\n", txnHash.ToString().c_str()); - return false; - }; - - mapWallet.erase(txnHash); + if (!walletdb.EraseTx(txnHash)) + { + LogPrintf("UndoAnonTransaction() EraseTx %s failed.\n", txnHash.ToString().c_str()); + return false; + } + mapWallet.erase(txnHash); + } return true; }; -bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash, bool& fIsMine, mapValue_t& mapNarr, std::vector& vUpdatedTxns) +bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash, bool& fIsMine, mapValue_t& mapNarr, std::vector& vUpdatedTxns, std::map& mapAnonBlockStat, const std::map * const mapPubStealth) { uint256 txnHash = tx.GetHash(); @@ -3155,12 +3304,19 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans return error("%s: Skipped - must run in full mode.\n", __func__); }; + int nBlockHeight = GetBlockHeightFromHash(blockHash); + + bool fHasNonAnonInputs = false; + bool fHasNonAnonOutputs = false; + bool fDebitAnonFromMe = false; for (uint32_t i = 0; i < tx.vin.size(); ++i) { const CTxIn& txin = tx.vin[i]; - if (!txin.IsAnonInput()) + if (!txin.IsAnonInput()) { + fHasNonAnonInputs = true; continue; + } const CScript &s = txin.scriptSig; @@ -3176,21 +3332,21 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans && spentKeyImage.inputNo == i) { if (fDebugRingSig) - LogPrintf("found matching spent key image - txn has been processed before\n"); - return UpdateAnonTransaction(ptxdb, tx, blockHash); - }; - - if (TxnHashInSystem(ptxdb, spentKeyImage.txnHash)) - { - return error("%s: Error input %d keyimage %s already spent.", __func__, i, HexStr(vchImage).c_str()); - }; + LogPrintf("found matching spent key image - txn has been processed before -> reprocess vin[%d].\n", i); + } + else { + if (TxnHashInSystem(ptxdb, spentKeyImage.txnHash)) + { + return error("%s: Error input %d keyimage %s already spent.", __func__, i, HexStr(vchImage).c_str()); + }; - if (fDebugRingSig) - LogPrintf("Input %d keyimage %s matches unknown txn %s, continuing.\n", i, HexStr(vchImage).c_str(), spentKeyImage.txnHash.ToString().c_str()); + if (fDebugRingSig) + LogPrintf("Input %d keyimage %s matches unknown txn %s, continuing.\n", i, HexStr(vchImage).c_str(), spentKeyImage.txnHash.ToString().c_str()); - // -- keyimage is in db, but invalid as does not point to a known transaction - // could be an old mempool keyimage - // continue + // -- keyimage is in db, but invalid as does not point to a known transaction + // could be an old mempool keyimage + // continue + } }; @@ -3201,6 +3357,9 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans if (pwdb->ReadOwnedAnonOutput(vchNewImage, oao)) { + // remember that this transaction debits from me + fDebitAnonFromMe = true; + if (fDebugRingSig) LogPrintf("%s: input %d keyimage %s found in wallet (owned).\n", __func__, i, HexStr(vchImage).c_str()); @@ -3232,12 +3391,12 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans { return error("%s: Input %d WriteOwnedAnonOutput failed %s.", __func__, i, HexStr(vchImage).c_str()); }; - }; + } - int nRingSize = txin.ExtractRingSize(); - if (nRingSize < (Params().IsProtocolV3(nBestHeight) ? 1 : (int)MIN_RING_SIZE) - ||nRingSize > (Params().IsProtocolV3(nBestHeight) ? (int)MAX_RING_SIZE : (int)MAX_RING_SIZE_OLD)) - return error("%s: Input %d ringsize %d not in range [%d, %d].", __func__, i, nRingSize, MIN_RING_SIZE, MAX_RING_SIZE); + uint32_t nRingSize = (uint32_t)txin.ExtractRingSize(); + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(tx.nTime); + if (nRingSize < nMinRingSize || nRingSize > nMaxRingSize) + return error("%s: Input %d ringsize %d not in range [%d, %d].", __func__, i, nRingSize, nMinRingSize, nMaxRingSize); const uint8_t *pPubkeys; int rsType; @@ -3259,13 +3418,14 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans CAnonOutput ao; CTxIndex txindex; + int minBlockHeight = tx.IsAnonCoinStake() ? Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; for (uint32_t ri = 0; ri < (uint32_t)nRingSize; ++ri) { pkRingCoin = CPubKey(&pPubkeys[ri * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE); if (!ptxdb->ReadAnonOutput(pkRingCoin, ao)) return error("%s: Input %u AnonOutput %s not found, rsType: %d.", __func__, i, HexStr(pkRingCoin).c_str(), rsType); - if (IsAnonCoinCompromised(ptxdb, pkRingCoin, ao, vchImage) and Params().IsProtocolV3(nBestHeight)) + if (IsAnonCoinCompromised(ptxdb, pkRingCoin, ao, vchImage) && Params().IsProtocolV3(nBestHeight)) return error("%s: Found spent pubkey at index %u: AnonOutput: %s, rsType: %d.", __func__, i, HexStr(pkRingCoin).c_str(), rsType); if (nCoinValue == -1) @@ -3275,15 +3435,15 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans return error("%s: Input %u ring amount mismatch %d, %d.", __func__, i, nCoinValue, ao.nValue); if (ao.nBlockHeight == 0 - || nBestHeight - ao.nBlockHeight < MIN_ANON_SPEND_DEPTH) - return error("%s: Input %u ring coin %u depth < MIN_ANON_SPEND_DEPTH.", __func__, i, ri); + || nBestHeight - ao.nBlockHeight + 1 < minBlockHeight) // ao confirmed in last block has depth of 1 + return error("%s: Input %u ring coin %u depth < %d.", __func__, i, ri, minBlockHeight); - if (nRingSize == 1) + if (blockHash != 0 && nRingSize == 1) { ao.nCompromised = 1; if (!ptxdb->WriteAnonOutput(pkRingCoin, ao)) return error("%s: Input %d WriteAnonOutput failed %s.", __func__, i, HexStr(vchImage).c_str()); - mapAnonOutputStats[ao.nValue].nCompromised++; + fStaleAnonCache = true; // force rebuild of anon cache } // -- ring sig validation is done in CTransaction::CheckAnonInputs() @@ -3292,6 +3452,9 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans spentKeyImage.txnHash = txnHash; spentKeyImage.inputNo = i; spentKeyImage.nValue = nCoinValue; + spentKeyImage.nBlockHeight = nBlockHeight; + + mapAnonBlockStat[nCoinValue].nSpends++; if (blockHash != 0) { @@ -3300,8 +3463,6 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans } else // -- add keyImage to mempool, will be added to txdb in UpdateAnonTransaction mempool.insertKeyImage(vchImage, spentKeyImage); - - mapAnonOutputStats[spentKeyImage.nValue].incSpends(spentKeyImage.nValue); } ec_secret sSpendR; @@ -3323,14 +3484,16 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans return error("%s: vchEphemPK.resize threw: %s.", __func__, e.what()); }; - int nBlockHeight = GetBlockHeightFromHash(blockHash); - + std::map mapOutReceiveAddr; + bool fNotAllOutputsOwned = false; for (uint32_t i = 0; i < tx.vout.size(); ++i) { const CTxOut& txout = tx.vout[i]; - if (!txout.IsAnonOutput()) + if (!txout.IsAnonOutput()) { + fHasNonAnonOutputs = true; continue; + } const CScript &s = txout.scriptPubKey; @@ -3347,20 +3510,33 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans if (blockHash != 0) { if (fDebugRingSig) - LogPrintf("Found existing anon output - assuming txn has been processed before.\n"); - return UpdateAnonTransaction(ptxdb, tx, blockHash); - }; - return error("%s: Found duplicate anon output.", __func__); - }; + LogPrintf("Found existing anon output - assuming txn has been processed before -> reprocess vout[%d].\n", i); - ao = CAnonOutput(outpoint, txout.nValue, nBlockHeight, 0); + if (ao.nBlockHeight && ao.nBlockHeight != nBlockHeight) + { + LogPrintf("%s: Warning: persisted block height of anon %s does not match current block %s -> ATXO cache must be rebuild.\n", __func__, ao.nBlockHeight, nBlockHeight); + fStaleAnonCache = true; // force rebuild of anon cache + } + ao.nBlockHeight = nBlockHeight; + ao.fCoinStake = tx.IsCoinStake(); + } + else { + return error("%s: Found duplicate anon output.", __func__); + } + } + else { + ao = CAnonOutput(outpoint, txout.nValue, nBlockHeight, 0, tx.IsCoinStake()); + } if (!ptxdb->WriteAnonOutput(pkCoin, ao)) { LogPrintf("%s: WriteAnonOutput failed.\n", __func__); continue; }; - - mapAnonOutputStats[txout.nValue].addCoin(nBlockHeight, txout.nValue); + // add to anon cache + if (tx.IsAnonCoinStake()) + mapAnonBlockStat[txout.nValue].nStakingOutputs++; + else + mapAnonBlockStat[txout.nValue].nOutputs++; memcpy(&vchEphemPK[0], &s[2+EC_COMPRESSED_SIZE+2], EC_COMPRESSED_SIZE); @@ -3469,8 +3645,14 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans break; }; - if (!fOwnOutput) + if (!fOwnOutput) { + if (mapPubStealth && mapPubStealth->count(ckCoinId)) { + // if we have stealth address for the non owned pubkey, add the mapping to the addressbook + SetAddressBookName(ckCoinId, mapPubStealth->at(ckCoinId).Encoded(), pwdb, false); + } + fNotAllOutputsOwned = true; // remember that at least one output is not owned continue; + } if (fDebugRingSig) LogPrintf("anon output match tx, no %s, %u\n", txnHash.GetHex().c_str(), i); @@ -3513,15 +3695,12 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans std::vector vchEmpty; CWalletDB *pwalletdbEncryptionOld = pwalletdbEncryption; pwalletdbEncryption = pwdb; // HACK, pass pdb to AddCryptedKey - AddCryptedKey(cpkE, vchEmpty); + AddCryptedKey(pkCoin, vchEmpty); pwalletdbEncryption = pwalletdbEncryptionOld; if (fDebugRingSig) LogPrintf("Wallet locked, adding key without secret.\n"); - std::string sLabel = std::string("ao ") + sSxAddr.substr(0, 16) + "..."; - SetAddressBookName(ckCoinId, sLabel, pwdb, false); - CPubKey cpkEphem(vchEphemPK); CPubKey cpkScan(pkScan); CLockedAnonOutput lockedAo(cpkEphem, cpkScan, COutPoint(txnHash, i)); @@ -3569,10 +3748,6 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans continue; }; - // TODO: groupings? - std::string sLabel = std::string("ao ") + sSxAddr.substr(0, 16) + "..."; - SetAddressBookName(ckCoinId, sLabel, pwdb, false); - // -- store keyImage ec_point pkImage; ec_point pkOldImage; @@ -3603,8 +3778,37 @@ bool CWallet::ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTrans if (fDebugRingSig) LogPrintf("Adding anon output to wallet: %s.\n", HexStr(pkImage).c_str()); }; + + // Remember used stealth address + std::string sLabel = sAnonPrefix + sSxAddr.substr(0, 16) + "..."; + mapOutReceiveAddr[ckCoinId] = sLabel; }; + if (!mapOutReceiveAddr.empty()) + { + // detect non change anon outputs an add them to te addressbook + for (auto const& out : mapOutReceiveAddr) + { + // if nonAnonInputs exists, anonOutputs are never change + if (fHasNonAnonInputs || + // AnonCoinStake outputs are never change + tx.IsAnonCoinStake() || ( + // if nonAnonOutputs exists, anonOutputs are change when anon is debited from us + !(fDebitAnonFromMe && fHasNonAnonOutputs) && + // if not all outputs are owned, owned anonOutputs are change when anon is debited from us + !(fDebitAnonFromMe && fNotAllOutputsOwned) )) + { + SetAddressBookName(out.first, out.second, pwdb, false); + } + else { + // don't add change outputs to the addressbook + // legacy: remove change outputs added from previous wallet versions + DelAddressBookName(out.first, pwdb); + } + } + } + + return true; }; @@ -3638,7 +3842,48 @@ bool CWallet::GetAnonChangeAddress(CStealthAddress &sxAddress) return false; }; -bool CWallet::CreateStealthOutput(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, std::map& mapNarr, std::string& sError) +bool CWallet::GetAnonStakeAddress(const COwnedAnonOutput& stakedOao, CStealthAddress& sxAddress) +{ + // TODO Get corresponding stealth address for stakedOao + LOCK(cs_wallet); + + ExtKeyAccountMap::iterator mi = mapExtAccounts.find(idDefaultAccount); + if (mi != mapExtAccounts.end()) + { + CExtKeyAccount *ea = mi->second; + + AccStealthKeyMap::iterator it = ea->mapStealthKeys.begin(); + + if (it != ea->mapStealthKeys.end()) + { + if (0 == it->second.SetSxAddr(sxAddress)) + { + CKey skSpend; + if (ea->GetKey(it->second.akSpend, skSpend)) + { + sxAddress.spend_secret.resize(EC_SECRET_SIZE); + memcpy(&sxAddress.spend_secret[0], skSpend.begin(), EC_SECRET_SIZE); + return true; + } + } + return false; + } + }; + + std::set::iterator it; + for (it = stealthAddresses.begin(); it != stealthAddresses.end(); ++it) + { + if (it->scan_secret.size() < 1) + continue; // stealth address is not owned + + sxAddress = *it; + return true; + }; + return false; +} + + +bool CWallet::CreateStealthOutput(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::string& sError) { if (fDebugRingSig) LogPrintf("CreateStealthOutput()\n"); @@ -3716,61 +3961,51 @@ bool CWallet::CreateStealthOutput(CStealthAddress* sxAddress, int64_t nValue, st vecSend.push_back(make_pair(scriptPubKey, nValue)); CScript scriptP = CScript() << OP_RETURN << ephem_pubkey; - if (vchENarr.size() > 0) + if (vchENarr.size() > 0) { scriptP = scriptP << OP_RETURN << vchENarr; + scriptNarration = scriptP; + } vecSend.push_back(make_pair(scriptP, 0)); - // TODO: shuffle change later? - if (vchENarr.size() > 0) - { - for (unsigned int k = 0; k < vecSend.size(); ++k) - { - if (vecSend[k].first != scriptPubKey - || vecSend[k].second != nValue) - continue; - - mapNarr[k] = sNarr; - break; - }; - }; - return true; }; -bool CWallet::CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration) +bool CWallet::CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::map* const mapPubStealth, std::vector * const vecSecShared, int64_t maxAnonOutput) +{ + std::vector vOutAmounts; + if (splitAmount(nValue, vOutAmounts, maxAnonOutput) != 0) + { + LogPrintf("splitAmount() failed.\n"); + return false; + }; + return CreateAnonOutputs(sxAddress, vOutAmounts, sNarr, vecSend, scriptNarration, mapPubStealth, vecSecShared); +} + +bool CWallet::CreateAnonOutputs(CStealthAddress* sxAddress, std::vector& vOutAmounts, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::map* const mapPubStealth, std::vector * const vecSecShared) { if (fDebugRingSig) LogPrintf("CreateAnonOutputs()\n"); ec_secret scEphem; - ec_secret scShared; ec_point pkSendTo; ec_point pkEphem; - CPubKey cpkTo; - // -- output scripts OP_RETURN ANON_TOKEN pkTo R enarr // Each outputs split from the amount must go to a unique pk, or the key image would be the same - // Only the first output of the group carries the enarr (if present) - - - std::vector vOutAmounts; - if (splitAmount(nValue, vOutAmounts) != 0) - { - LogPrintf("splitAmount() failed.\n"); - return false; - }; - + // Only the first output of the group carries the enarr (if present) for (uint32_t i = 0; i < vOutAmounts.size(); ++i) { + ec_secret scShared; + CPubKey cpkTo; + if (GenerateRandomSecret(scEphem) != 0) { LogPrintf("GenerateRandomSecret failed.\n"); return false; }; - if (sxAddress) // NULL for test only + if (sxAddress) // nullptr for test only { if (StealthSecret(scEphem, sxAddress->scan_pubkey, sxAddress->spend_pubkey, scShared, pkSendTo) != 0) { @@ -3790,6 +4025,10 @@ bool CWallet::CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std: LogPrintf("Could not generate ephem public key.\n"); return false; }; + + if (mapPubStealth) + // save which stealth address was used for creating this key + (*mapPubStealth)[cpkTo.GetID()] = *sxAddress; }; CScript scriptSendTo; @@ -3833,11 +4072,11 @@ bool CWallet::CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std: LogPrintf("scriptPubKey %s\n", scriptSendTo.ToString().c_str()); }; vecSend.push_back(make_pair(scriptSendTo, vOutAmounts[i])); + if (vecSecShared) + // save which shared secret was used for creating this key + vecSecShared->push_back(scShared); }; - // TODO: will this be optimised away? - memset(&scShared.e[0], 0, EC_SECRET_SIZE); - return true; }; @@ -3882,7 +4121,8 @@ static bool checkCombinations(int64_t nReq, int m, std::vector 2 to use coarse seeking bool fSeekFine = m <= 2; @@ -3991,11 +4230,11 @@ static bool checkCombinations(int64_t nReq, int m, std::vector& lAvailableCoins, std::vector& vPickedCoins, std::vector >& vecChange, bool fTest, std::string& sError) +int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRingSize, CWalletTx& wtxNew, int nOutputs, int nSizeOutputs, int& nExpectChangeOuts, std::list& lAvailableCoins, std::vector& vPickedCoins, std::vector >& vecChange, bool fTest, std::string& sError, int feeMode) { if (fDebugRingSig) - LogPrintf("PickAnonInputs(), ChangeOuts %d\n", nExpectChangeOuts); - // - choose the smallest coin that can cover the amount + fee + LogPrintf("PickAnonInputs(), ChangeOuts %d, FeeMode %d\n", nExpectChangeOuts, feeMode); + // - choose the smallest coin that can cover the amount (feeMode==1) or the amount + fee (feeMode!=1) // or least no. of smallest coins @@ -4049,29 +4288,71 @@ int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRing + GetSizeOfCompactSize((i+1)) + nByteSizePerInCoin * (i+1); - nFee = wtxNew.GetMinFee(0, GMF_ANON, nTotalBytes); - - if (fDebugRingSig) - LogPrintf("nValue + nFee: %d, nValue: %d, nAmountCheck: %d, nTotalBytes: %u\n", nValue + nFee, nValue, nAmountCheck, nTotalBytes); - - if (nValue + nFee > nAmountCheck) + nFee = wtxNew.GetMinFee(0, GMF_SEND, nTotalBytes); + if (nFee == MAX_MONEY) { - sError = "Not enough mature coins with requested ring size."; + sError = "The transaction is over the maximum size limit. Create multiple transactions with smaller amounts."; + if (fDebugRingSig) + LogPrintf("Transaction with nTotalBytes %d results in MAX_MONEY fee.\n", nTotalBytes); return 3; - }; + } - vPickedCoins.clear(); - vecChange.clear(); + int64_t nValueTest; + if (feeMode == 1) { + nValueTest = nValue; + } + else { + nValueTest = nValue + nFee; - std::vector vecInputIndex; - if (checkCombinations(nValue + nFee, i+1, vData, vecInputIndex)) - { - if (fDebugRingSig) + int64_t nFeeDiff = nAmountCheck - nValueTest; + if (nFeeDiff < 0) { - LogPrintf("Found combination %u, ", i+1); - for (int ic = vecInputIndex.size(); ic--;) - LogPrintf("%d%c", vecInputIndex[ic], ic ? ' ': '\n'); - + // substract fee + nValueTest += nFeeDiff; + if (nValueTest <= 0) + { + sError = "Not enough (mature) coins with requested ring size to cover amount with fees."; + if (fDebugRingSig) + LogPrintf("Not enough (mature) coins %d with requested ring size to cover amount %d together with fees %d.\n", nAmountCheck, nValue, nFee); + return 3; + } + + if (fDebugRingSig) + LogPrintf("AmountWithFeeExceedsBalance! simulate exhaustive trx, lower amount by nFeeDiff: %d\n", nFeeDiff); + + if (nExpectChangeOuts != 0) { + // -- set nExpectChangeOuts to 0 to simulate exhaustive payment (total+fee=totalAvailableCoins) + nExpectChangeOuts = 0; + // -- get nTotalBytes again for 0 change outputs + uint32_t nTotalBytes = (4 + 4 + 4) // Ctx: nVersion, nTime, nLockTime + + GetSizeOfCompactSize(nOutputs) + + nSizeOutputs + + (GetSizeOfCompactSize(MIN_ANON_OUT_SIZE) + MIN_ANON_OUT_SIZE + sizeof(int64_t)) * vecChange.size() + + GetSizeOfCompactSize((i + 1)) + + nByteSizePerInCoin * (i + 1); + + if (fDebugRingSig) + LogPrintf("New nTotalBytes: %d\n", nTotalBytes); + } + } + } + + if (fDebugRingSig) + LogPrintf("nValue: %d, nFee: %d, nValueTest: %d, nAmountCheck: %d, nTotalBytes: %u\n", nValue, nFee, nValueTest, nAmountCheck, nTotalBytes); + + vPickedCoins.clear(); + vecChange.clear(); + + std::vector vecInputIndex; + + if (checkCombinations(nValueTest, i+1, vData, vecInputIndex)) + { + if (fDebugRingSig) + { + LogPrintf("Found combination %u, ", i+1); + for (int ic = vecInputIndex.size(); ic--;) + LogPrintf("%d%c", vecInputIndex[ic], ic ? ' ': '\n'); + LogPrintf("nTotalBytes %u\n", nTotalBytes); LogPrintf("nFee %d\n", nFee); }; @@ -4084,7 +4365,7 @@ int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRing nTotalIn += vPickedCoins[ic]->nValue; }; - int64_t nChange = nTotalIn - (nValue + nFee); + int64_t nChange = nTotalIn - nValueTest; CStealthAddress sxChange; @@ -4097,7 +4378,7 @@ int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRing std::string sNone; sNone.clear(); CScript scriptNone; - if (!CreateAnonOutputs(fTest ? NULL : &sxChange, nChange, sNone, vecChange, scriptNone)) + if (!CreateAnonOutputs(fTest ? nullptr : &sxChange, nChange, sNone, vecChange, scriptNone)) { sError = "CreateAnonOutputs() change failed."; return 3; @@ -4112,7 +4393,7 @@ int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRing + GetSizeOfCompactSize((i+1)) + nByteSizePerInCoin * (i+1); - int64_t nTestFee = wtxNew.GetMinFee(0, GMF_ANON, nTotalBytes); + int64_t nTestFee = wtxNew.GetMinFee(0, GMF_SEND, nTotalBytes); if (nTestFee > nFee) { @@ -4123,6 +4404,16 @@ int CWallet::PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRing }; nFee = nTestFee; + + if (feeMode != 1 && nValue + nFee > nAmountCheck) + { + sError = "Not enough (mature) coins with requested ring size to cover amount with fees."; + if (fDebugRingSig) + LogPrintf("Not enough (mature) coins %d with requested ring size to cover amount %d together with fees %d.\n", nAmountCheck, nValue, nFee); + return 3; + }; + + return 1; // found }; }; @@ -4160,25 +4451,29 @@ int CWallet::GetTxnPreImage(CTransaction& txn, uint256& hash) return 0; }; -int CWallet::PickHidingOutputs(int64_t nValue, int nRingSize, CPubKey& pkCoin, int skip, uint8_t* p) +bool CWallet::InitMixins(CMixins& mixins, const std::vector& vPickedCoins, bool fStaking) { - if (fDebug) - LogPrintf("PickHidingOutputs() %d, %d\n", nValue, nRingSize); - - // TODO: process multiple inputs in 1 db loop? + LOCK(cs_main); - // -- offset skip is pre filled with the real coin + int64_t nStart = GetTimeMicros(); + if (fDebugRingSig) + LogPrintf("CWallet::InitMixins() : fStaking=%d\n", fStaking); - LOCK(cs_main); CTxDB txdb("r"); - leveldb::DB* pdb = txdb.GetInstance(); if (!pdb) - throw runtime_error("CWallet::PickHidingOutputs() : cannot get leveldb instance"); + throw runtime_error("CWallet::InitMixins() : cannot get leveldb instance"); - leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); + // Init denominations needed and used Txs to skip + std::set setUsedOutputsTxs; + std::set setDenominations; + for (const auto & oao : vPickedCoins) + { + setUsedOutputsTxs.insert(oao->outpoint.hash); + setDenominations.insert(oao->nValue); + } - std::vector vHideKeys; + leveldb::Iterator *iterator = pdb->NewIterator(txdb.GetReadOptions()); // Seek to start key. CPubKey pkZero; @@ -4190,6 +4485,7 @@ int CWallet::PickHidingOutputs(int64_t nValue, int nRingSize, CPubKey& pkCoin, i CPubKey pkAo; CAnonOutput anonOutput; + uint32_t nTotal = 0, nMixins = 0, nInvalid = 0, nUsedTx = 0, nDiffDenom = 0, nImmature = 0, nCompromised = 0; while (iterator->Valid()) { // Unpack keys and values. @@ -4204,61 +4500,74 @@ int CWallet::PickHidingOutputs(int64_t nValue, int nRingSize, CPubKey& pkCoin, i CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.write(iterator->value().data(), iterator->value().size()); - ssKey >> pkAo; + ssValue >> anonOutput; - if (pkAo != pkCoin - && pkAo.IsValid()) + nTotal++; + if (!pkAo.IsValid()) + nInvalid++; + else if (setDenominations.find(anonOutput.nValue) == setDenominations.end()) + nDiffDenom++; + else if (setUsedOutputsTxs.find(anonOutput.outpoint.hash) != setUsedOutputsTxs.end()) + nUsedTx++; + else { - ssValue >> anonOutput; - - if ((anonOutput.nBlockHeight > 0 && nBestHeight - anonOutput.nBlockHeight >= MIN_ANON_SPEND_DEPTH) - && anonOutput.nValue == nValue - && anonOutput.nCompromised == 0) - try { vHideKeys.push_back(pkAo); } catch (std::exception& e) - { - LogPrintf("Error: PickHidingOutputs() vHideKeys.push_back threw: %s.\n", e.what()); - return 1; - } + int nCompromisedHeight = mapAnonOutputStats[anonOutput.nValue].nCompromisedHeight; + // If hiding outputs are for staking, all outputs must have a enough confirmations for staking + int minDepth = fStaking || anonOutput.fCoinStake ? Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; + if (anonOutput.nBlockHeight <= 0 || nBestHeight - anonOutput.nBlockHeight + 1 < minDepth) // ao confirmed in last block has depth of 1 + nImmature++; + else if (anonOutput.nCompromised != 0 || (nCompromisedHeight != 0 && nCompromisedHeight - MIN_ANON_SPEND_DEPTH >= anonOutput.nBlockHeight)) + nCompromised++; + else + try { + nMixins++; + mixins.AddAnonOutput(pkAo, anonOutput, nBestHeight); + } catch (std::exception& e) + { + LogPrintf("ERROR: CWallet::InitMixins() : mixins.addAnonOutput threw: %s.\n", e.what()); + return false; + } } - iterator->Next(); }; + if (fDebugRingSig) + LogPrintf("CWallet::InitMixins() : processed %d anons in %d µs; potential mixins: %d; skipped invalid: %d, txUsed: %d, diffDenom: %d, immature: %d, compromised: %d.\n", + nTotal, GetTimeMicros() - nStart, nMixins, nInvalid, nUsedTx, nDiffDenom, nImmature, nCompromised); + delete iterator; + return true; +} - if ((int)vHideKeys.size() < nRingSize-1) +int CWallet::PickHidingOutputs(CMixins& mixins, int64_t nValue, int nRingSize, int skip, uint8_t* p) +{ + // -- offset skip is pre filled with the real coin + std::vector vHideKeys; + if (!mixins.Pick(nValue, nRingSize - 1, vHideKeys)) return errorN(1, "%s: Not enough keys found.", __func__); - for (int i = 0; i < nRingSize; ++i) + for (int i = 0, iMixin = 0; i < nRingSize; ++i) { if (i == skip) continue; - if (vHideKeys.size() < 1) - return errorN(1, "%s: vHideKeys.size() < 1", __func__); - - uint32_t pick = GetRand(vHideKeys.size()); - - memcpy(p + i * 33, vHideKeys[pick].begin(), 33); - - vHideKeys.erase(vHideKeys.begin()+pick); + memcpy(p + i * 33, vHideKeys[iMixin++].begin(), 33); }; - return 0; }; -bool CWallet::AreOutputsUnique(CWalletTx& wtxNew) +bool CWallet::AreOutputsUnique(CTransaction& txNew) { LOCK(cs_main); CTxDB txdb; - for (uint32_t i = 0; i < wtxNew.vout.size(); ++i) + for (uint32_t i = 0; i < txNew.vout.size(); ++i) { - const CTxOut& txout = wtxNew.vout[i]; + const CTxOut& txout = txNew.vout[i]; - if (txout.IsAnonOutput()) + if (!txout.IsAnonOutput()) continue; const CScript &s = txout.scriptPubKey; @@ -4304,54 +4613,240 @@ static uint8_t *GetRingSigPkStart(int rsType, int nRingSize, uint8_t *pStart) }; } -bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::vector >&vecSend, std::vector >&vecChange, CWalletTx& wtxNew, int64_t& nFeeRequired, bool fTestOnly, std::string& sError) + +bool CWallet::ListAvailableAnonOutputs(std::list& lAvailableAnonOutputs, int64_t& nAmountCheck, int nRingSize, MaturityFilter nFilter, std::string& sError, int64_t nMaxAmount) const { - if (fDebugRingSig) - LogPrintf("AddAnonInputs() %d, %d, rsType:%d\n", nTotalOut, nRingSize, rsType); + LOCK2(cs_main, cs_wallet); - std::list lAvailableCoins; - if (ListUnspentAnonOutputs(lAvailableCoins, true) != 0) + nAmountCheck = 0; + if (ListUnspentAnonOutputs(lAvailableAnonOutputs, nFilter) != 0) { sError = "ListUnspentAnonOutputs() failed"; return false; }; - std::map mOutputCounts; - for (std::list::iterator it = lAvailableCoins.begin(); it != lAvailableCoins.end(); ++it) - mOutputCounts[it->nValue] = 0; + // -- remove coins that don't have enough same value anonoutputs in the system for the ring size + // -- remove coins which spending would lead to ALL SPENT + int nCoinsPerValue = 0; + int64_t nLastCoinValue = -1; + int nMaxSpendable = -1; + int nAvailableMixins = 0; + for (std::list::iterator it = lAvailableAnonOutputs.begin(); it != lAvailableAnonOutputs.end();) + { + if (nLastCoinValue != it->nValue) + { + nCoinsPerValue = 0; + nLastCoinValue = it->nValue; + CAnonOutputCount anonOutputCount = mapAnonOutputStats[it->nValue]; + nAvailableMixins = nFilter == MaturityFilter::FOR_STAKING ? anonOutputCount.nMixinsStaking : anonOutputCount.nMixins; + if (it->nValue <= nMaxAnonOutput) + nMaxSpendable = (anonOutputCount.nMature - anonOutputCount.nSpends) - + (nFilter == MaturityFilter::FOR_STAKING ? 1 : UNSPENT_ANON_SELECT_MIN); + else + nMaxSpendable = -1; + if (fDebugRingSig && nFilter == MaturityFilter::FOR_SPENDING) // called to often when staking + LogPrintf("ListAvailableAnonOutputs anonValue %d, nAvailableMixins %d, nMaxSpendable %d\n", nLastCoinValue, nAvailableMixins, nMaxSpendable); + } + + if (nAvailableMixins < nRingSize || + (nMaxSpendable != -1 && nCoinsPerValue >= nMaxSpendable) || + nAmountCheck + it->nValue > nMaxAmount) + // -- not enough coins of same value, unspends or over max amount, drop coin + it = lAvailableAnonOutputs.erase(it); + else + { + nAmountCheck += it->nValue; + nCoinsPerValue++; + ++it; + } + } + + return true; +} + + +bool CWallet::AddAnonInput(CMixins& mixins, CTxIn& txin, const COwnedAnonOutput& oao, int rsType, int nRingSize, int& oaoRingIndex, bool fStaking, bool fTestOnly, std::string& sError) +{ + int nSigSize = GetRingSigSize(rsType, nRingSize); - if (CountAnonOutputs(mOutputCounts, true) != 0) + // -- overload prevout to hold keyImage + memcpy(txin.prevout.hash.begin(), &oao.vchImage[0], EC_SECRET_SIZE); + + txin.prevout.n = 0 | ((oao.vchImage[32]) & 0xFF) | (int32_t)(((int16_t) nRingSize) << 16); + + // -- size for full signature, signature is added later after hash + try { txin.scriptSig.resize(nSigSize); } catch (std::exception& e) { - sError = "CountAnonOutputs() failed"; + LogPrintf("Error: AddAnonInput() txin.scriptSig.resize threw: %s.\n", e.what()); + sError = "resize failed.\n"; return false; }; - if (fDebugRingSig) + txin.scriptSig[0] = OP_RETURN; + txin.scriptSig[1] = OP_ANON_MARKER; + + if (fTestOnly) + return true; + + int nCoinOutId = oao.outpoint.n; + WalletTxMap::iterator mi = mapWallet.find(oao.outpoint.hash); + if (mi == mapWallet.end() + || mi->second.nVersion != ANON_TXN_VERSION + || (int)mi->second.vout.size() < nCoinOutId) { - for (std::map::iterator it = mOutputCounts.begin(); it != mOutputCounts.end(); ++it) - LogPrintf("mOutputCounts %ld %d\n", it->first, it->second); + LogPrintf("Error: AddAnonInput() picked coin not in wallet, %s version %d.\n", oao.outpoint.hash.ToString().c_str(), (*mi).second.nVersion); + sError = "picked coin not in wallet.\n"; + return false; }; - int64_t nAmountCheck = 0; - // -- remove coins that don't have enough same value anonoutputs in the system for the ring size - std::list::iterator it = lAvailableCoins.begin(); - while (it != lAvailableCoins.end()) + CWalletTx& wtxAnonCoin = mi->second; + + const CTxOut& txout = wtxAnonCoin.vout[nCoinOutId]; + const CScript &s = txout.scriptPubKey; + + if (!txout.IsAnonOutput()) { - std::map::iterator mi = mOutputCounts.find(it->nValue); - if (mi == mOutputCounts.end() - || mi->second < nRingSize) - { - // -- not enough coins of same value, drop coin - lAvailableCoins.erase(it++); - continue; - }; + sError = "picked coin not an anon output.\n"; + return false; + }; - nAmountCheck += it->nValue; - ++it; + CPubKey pkCoin = CPubKey(&s[2+1], EC_COMPRESSED_SIZE); + + if (!pkCoin.IsValid()) + { + sError = "pkCoin is invalid.\n"; + return false; + }; + + oaoRingIndex = GetRand(nRingSize); + + uint8_t *pPubkeyStart = GetRingSigPkStart(rsType, nRingSize, &txin.scriptSig[0]); + + memcpy(pPubkeyStart + oaoRingIndex * EC_COMPRESSED_SIZE, pkCoin.begin(), EC_COMPRESSED_SIZE); + + if (PickHidingOutputs(mixins, oao.nValue, nRingSize, oaoRingIndex, pPubkeyStart) != 0) + { + sError = "PickHidingOutputs() failed.\n"; + return false; + } + + return true; +} + +bool CWallet::GenerateRingSignature(CTxIn& txin, const int& rsType, const int& nRingSize, const int& nSecretOffset, const uint256& preimage, std::string& sError) +{ + // Test + std::vector vchImageTest; + txin.ExtractKeyImage(vchImageTest); + + int nTestRingSize = txin.ExtractRingSize(); + if (nTestRingSize != nRingSize) + { + sError = "nRingSize embed error."; + return false; + }; + + int nSigSize = GetRingSigSize(rsType, nRingSize); + if (txin.scriptSig.size() < (unsigned long) nSigSize) + { + sError = "Error: scriptSig too small."; + return false; + }; + + uint8_t *pPubkeyStart = GetRingSigPkStart(rsType, nRingSize, &txin.scriptSig[0]); + + // -- get secret + CPubKey pkCoin = CPubKey(pPubkeyStart + EC_COMPRESSED_SIZE * nSecretOffset, EC_COMPRESSED_SIZE); + CKeyID pkId = pkCoin.GetID(); + + CKey key; + if (!GetKey(pkId, key)) + { + sError = "Error: don't have key for output."; + return false; + }; + + ec_secret ecSecret; + if (key.size() != EC_SECRET_SIZE) + { + sError = "Error: key.size() != EC_SECRET_SIZE."; + return false; + }; + + memcpy(&ecSecret.e[0], key.begin(), key.size()); + + switch(rsType) + { + case RING_SIG_1: + { + uint8_t *pPubkeys = &txin.scriptSig[2]; + uint8_t *pSigc = &txin.scriptSig[2 + EC_COMPRESSED_SIZE * nRingSize]; + uint8_t *pSigr = &txin.scriptSig[2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE) * nRingSize]; + if (generateRingSignature(vchImageTest, preimage, nRingSize, nSecretOffset, ecSecret, pPubkeys, pSigc, pSigr) != 0) + { + sError = "Error: generateRingSignature() failed."; + return false; + }; + // -- test verify + if (verifyRingSignature(vchImageTest, preimage, nRingSize, pPubkeys, pSigc, pSigr) != 0) + { + sError = "Error: verifyRingSignature() failed."; + return false; + }; + } + break; + case RING_SIG_2: + { + ec_point pSigC; + uint8_t *pSigS = &txin.scriptSig[2 + EC_SECRET_SIZE]; + uint8_t *pPubkeys = &txin.scriptSig[2 + EC_SECRET_SIZE + EC_SECRET_SIZE * nRingSize]; + if (generateRingSignatureAB(vchImageTest, nRingSize, nSecretOffset, ecSecret, pPubkeys, pSigC, pSigS) != 0) + { + sError = "Error: generateRingSignatureAB() failed."; + return false; + }; + if (pSigC.size() == EC_SECRET_SIZE) + memcpy(&txin.scriptSig[2], &pSigC[0], EC_SECRET_SIZE); + else + LogPrintf("pSigC.size() : %d Invalid!!\n", pSigC.size()); + + // -- test verify + if (verifyRingSignatureAB(vchImageTest, nRingSize, pPubkeys, pSigC, pSigS) != 0) + { + sError = "Error: verifyRingSignatureAB() failed."; + return false; + }; + } + break; + default: + sError = "Unknown ring signature type."; + return false; }; + memset(&ecSecret.e[0], 0, EC_SECRET_SIZE); // optimised away? + + return true; +} + +bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, const std::vector >&vecSend, std::vector >&vecChange, CWalletTx& wtxNew, int64_t& nFeeRequired, bool fTestOnly, std::string& sError) +{ + int64_t nStart = GetTimeMicros(); + if (fDebugRingSig) + LogPrintf("AddAnonInputs() %d, %d, rsType:%d\n", nTotalOut, nRingSize, rsType); + + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (nRingSize < (int)nMinRingSize || nRingSize > (int)nMaxRingSize) + { + sError = tfm::format("Ringsize %d not in range [%d, %d]: ", nRingSize, nMinRingSize, nMaxRingSize); + return false; + } + + std::list lAvailableCoins; + int64_t nAmountCheck; + if (!ListAvailableAnonOutputs(lAvailableCoins, nAmountCheck, nRingSize, MaturityFilter::FOR_SPENDING, sError)) + return false; if (fDebugRingSig) - LogPrintf("%u coins available with ring size %d, total %d\n", lAvailableCoins.size(), nRingSize, nAmountCheck); + LogPrintf("Debug: CWallet::AddAnonInputs() : ListAvailableAnonOutputs() : %d anons picked in %d µs, total %d.\n", lAvailableCoins.size(), GetTimeMicros() - nStart, nAmountCheck); // -- estimate fee @@ -4359,11 +4854,12 @@ bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::v for (uint32_t i = 0; i < vecSend.size(); ++i) // need to sum due to narration nSizeOutputs += GetSizeOfCompactSize(vecSend[i].first.size()) + vecSend[i].first.size() + sizeof(int64_t); // CTxOut + int64_t nStartPickAnon = GetTimeMicros(); bool fFound = false; int64_t nFee; int nExpectChangeOuts = 1; std::string sPickError; - std::vector vPickedCoins; + std::vector vPickedCoins; for (int k = 0; k < 50; ++k) // safety { // -- nExpectChangeOuts is raised if needed (rv == 2) @@ -4382,88 +4878,41 @@ bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::v break; }; }; + if (fDebugRingSig) + LogPrintf("Debug: CWallet::AddAnonInputs() : PickAnonInputs() : picked %d anons in %d µs.\n", vPickedCoins.size(), GetTimeMicros() - nStartPickAnon); if (!fFound) { - sError = "No combination of coins matches amount and ring size."; + sError = "No combination of (mature) coins matches amount and ring size."; return false; }; nFeeRequired = nFee; // set in PickAnonInputs() - int nSigSize = GetRingSigSize(rsType, nRingSize); // -- need hash of tx without signatures std::vector vCoinOffsets; uint32_t ii = 0; wtxNew.vin.resize(vPickedCoins.size()); vCoinOffsets.resize(vPickedCoins.size()); - for (std::vector::iterator it = vPickedCoins.begin(); it != vPickedCoins.end(); ++it) + + // -- Initialize mixins set + CMixins mixins; + if (!InitMixins(mixins, vPickedCoins, false)) + return false; + + int64_t nStartPickMixins = GetTimeMicros(); + for (std::vector::iterator it = vPickedCoins.begin(); it != vPickedCoins.end(); ++it) { - CTxIn& txin = wtxNew.vin[ii]; if (fDebugRingSig) LogPrintf("pickedCoin %s %d\n", HexStr((*it)->vchImage).c_str(), (*it)->nValue); - // -- overload prevout to hold keyImage - memcpy(txin.prevout.hash.begin(), &(*it)->vchImage[0], EC_SECRET_SIZE); - - txin.prevout.n = 0 | (((*it)->vchImage[32]) & 0xFF) | (int32_t)(((int16_t) nRingSize) << 16); - - // -- size for full signature, signature is added later after hash - try { txin.scriptSig.resize(nSigSize); } catch (std::exception& e) - { - LogPrintf("Error: AddAnonInputs() txin.scriptSig.resize threw: %s.\n", e.what()); - sError = "resize failed.\n"; - return false; - }; - - txin.scriptSig[0] = OP_RETURN; - txin.scriptSig[1] = OP_ANON_MARKER; - - if (fTestOnly) - continue; - - int nCoinOutId = (*it)->outpoint.n; - WalletTxMap::iterator mi = mapWallet.find((*it)->outpoint.hash); - if (mi == mapWallet.end() - || mi->second.nVersion != ANON_TXN_VERSION - || (int)mi->second.vout.size() < nCoinOutId) - { - LogPrintf("Error: AddAnonInputs() picked coin not in wallet, %s version %d.\n", (*it)->outpoint.hash.ToString().c_str(), (*mi).second.nVersion); - sError = "picked coin not in wallet.\n"; - return false; - }; - - CWalletTx& wtxAnonCoin = mi->second; - - const CTxOut& txout = wtxAnonCoin.vout[nCoinOutId]; - const CScript &s = txout.scriptPubKey; - - if (!txout.IsAnonOutput()) - { - sError = "picked coin not an anon output.\n"; + if (!AddAnonInput(mixins, wtxNew.vin[ii], *(*it), rsType, nRingSize, vCoinOffsets[ii], false, fTestOnly, sError)) return false; - }; - - CPubKey pkCoin = CPubKey(&s[2+1], EC_COMPRESSED_SIZE); - - if (!pkCoin.IsValid()) - { - sError = "pkCoin is invalid.\n"; - return false; - }; - vCoinOffsets[ii] = GetRand(nRingSize); - - uint8_t *pPubkeyStart = GetRingSigPkStart(rsType, nRingSize, &txin.scriptSig[0]); - - memcpy(pPubkeyStart + vCoinOffsets[ii] * EC_COMPRESSED_SIZE, pkCoin.begin(), EC_COMPRESSED_SIZE); - if (PickHidingOutputs((*it)->nValue, nRingSize, pkCoin, vCoinOffsets[ii], pPubkeyStart) != 0) - { - sError = "PickHidingOutputs() failed.\n"; - return false; - }; ii++; }; + if (fDebugRingSig) + LogPrintf("Debug: CWallet::AddAnonInputs() : AddAnonInput(): picked mixins for %d ring signatures with ring size %d in %d µs.\n", vPickedCoins.size(), nRingSize, GetTimeMicros() - nStartPickMixins); for (uint32_t i = 0; i < vecSend.size(); ++i) wtxNew.vout.push_back(CTxOut(vecSend[i].second, vecSend[i].first)); @@ -4484,102 +4933,14 @@ bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::v // TODO: Does it lower security to use the same preimage for each input? // cryptonote seems to do so too - + int64_t nStartRingSig = GetTimeMicros(); for (uint32_t i = 0; i < wtxNew.vin.size(); ++i) { - CTxIn& txin = wtxNew.vin[i]; - - // Test - std::vector vchImageTest; - txin.ExtractKeyImage(vchImageTest); - - int nTestRingSize = txin.ExtractRingSize(); - if (nTestRingSize != nRingSize) - { - sError = "nRingSize embed error."; - return false; - }; - - if (txin.scriptSig.size() < nSigSize) - { - sError = "Error: scriptSig too small."; - return false; - }; - - int nSecretOffset = vCoinOffsets[i]; - - uint8_t *pPubkeyStart = GetRingSigPkStart(rsType, nRingSize, &txin.scriptSig[0]); - - // -- get secret - CPubKey pkCoin = CPubKey(pPubkeyStart + EC_COMPRESSED_SIZE * nSecretOffset, EC_COMPRESSED_SIZE); - CKeyID pkId = pkCoin.GetID(); - - CKey key; - if (!GetKey(pkId, key)) - { - sError = "Error: don't have key for output."; + if (!GenerateRingSignature(wtxNew.vin[i], rsType, nRingSize, vCoinOffsets[i], preimage, sError)) return false; - }; - - ec_secret ecSecret; - if (key.size() != EC_SECRET_SIZE) - { - sError = "Error: key.size() != EC_SECRET_SIZE."; - return false; - }; - - memcpy(&ecSecret.e[0], key.begin(), key.size()); - - switch(rsType) - { - case RING_SIG_1: - { - uint8_t *pPubkeys = &txin.scriptSig[2]; - uint8_t *pSigc = &txin.scriptSig[2 + EC_COMPRESSED_SIZE * nRingSize]; - uint8_t *pSigr = &txin.scriptSig[2 + (EC_COMPRESSED_SIZE + EC_SECRET_SIZE) * nRingSize]; - if (generateRingSignature(vchImageTest, preimage, nRingSize, nSecretOffset, ecSecret, pPubkeys, pSigc, pSigr) != 0) - { - sError = "Error: generateRingSignature() failed."; - return false; - }; - // -- test verify - if (verifyRingSignature(vchImageTest, preimage, nRingSize, pPubkeys, pSigc, pSigr) != 0) - { - sError = "Error: verifyRingSignature() failed."; - return false; - }; - } - break; - case RING_SIG_2: - { - ec_point pSigC; - uint8_t *pSigS = &txin.scriptSig[2 + EC_SECRET_SIZE]; - uint8_t *pPubkeys = &txin.scriptSig[2 + EC_SECRET_SIZE + EC_SECRET_SIZE * nRingSize]; - if (generateRingSignatureAB(vchImageTest, preimage, nRingSize, nSecretOffset, ecSecret, pPubkeys, pSigC, pSigS) != 0) - { - sError = "Error: generateRingSignatureAB() failed."; - return false; - }; - if (pSigC.size() == EC_SECRET_SIZE) - memcpy(&txin.scriptSig[2], &pSigC[0], EC_SECRET_SIZE); - else - LogPrintf("pSigC.size() : %d Invalid!!\n", pSigC.size()); - - // -- test verify - if (verifyRingSignatureAB(vchImageTest, preimage, nRingSize, pPubkeys, pSigC, pSigS) != 0) - { - sError = "Error: verifyRingSignatureAB() failed."; - return false; - }; - } - break; - default: - sError = "Unknown ring signature type."; - return false; - }; - - memset(&ecSecret.e[0], 0, EC_SECRET_SIZE); // optimised away? }; + if (fDebugRingSig) + LogPrintf("Debug: CWallet::AddAnonInputs() : GenerateRingSignature() : generated %d ring signatures with ring size %d in %d µs.\n", wtxNew.vin.size(), nRingSize, GetTimeMicros() - nStartRingSig); // -- check if new coins already exist (in case random is broken ?) if (!AreOutputsUnique(wtxNew)) @@ -4588,13 +4949,15 @@ bool CWallet::AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::v return false; }; + if (fDebugRingSig) + LogPrintf("Debug: CWallet::AddAnonInputs() : finished in %d µs.\n", GetTimeMicros() - nStart); return true; }; -bool CWallet::SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee) +bool CWallet::SendSpecToAnon(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee) { if (fDebugRingSig) - LogPrintf("SendSdcToAnon()\n"); + LogPrintf("SendSpecToAnon()\n"); if (IsLocked()) { @@ -4622,7 +4985,7 @@ bool CWallet::SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::str if (vNodes.empty()) { - sError = _("Error: ShadowCoin is not connected!"); + sError = _("Error: Alias is not connected!"); return false; }; @@ -4644,8 +5007,9 @@ bool CWallet::SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::str CScript scriptNarration; // needed to match output id of narr std::vector > vecSend; + std::map mapPubStealth; - if (!CreateAnonOutputs(&sxAddress, nValue, sNarr, vecSend, scriptNarration)) + if (!CreateAnonOutputs(&sxAddress, nValue, sNarr, vecSend, scriptNarration, &mapPubStealth)) { sError = "CreateAnonOutputs() failed."; return false; @@ -4653,32 +5017,22 @@ bool CWallet::SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::str // -- shuffle outputs - std::random_shuffle(vecSend.begin(), vecSend.end()); +// Removed with c++17, see https://en.cppreference.com/w/cpp/algorithm/random_shuffle +// std::random_shuffle(vecSend.begin(), vecSend.end()); + std::random_device rng; + std::mt19937 urng(rng()); + std::shuffle(vecSend.begin(), vecSend.end(), urng); int64_t nFeeRequired; int nChangePos; - if (!CreateTransaction(vecSend, wtxNew, nFeeRequired, nChangePos, NULL)) + if (!CreateTransaction(vecSend, wtxNew, nFeeRequired, nChangePos, nullptr)) { sError = "CreateTransaction() failed."; return false; }; - if (scriptNarration.size() > 0) - { - for (uint32_t k = 0; k < wtxNew.vout.size(); ++k) - { - if (wtxNew.vout[k].scriptPubKey != scriptNarration) - continue; - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", k) < 1) - { - sError = "Error creating narration key."; - return false; - }; - wtxNew.mapValue[key] = sNarr; - break; - }; - }; + if (!SaveNarrationOutput(wtxNew, scriptNarration, sNarr, sError)) + return false; if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending..."))) { @@ -4693,15 +5047,13 @@ bool CWallet::SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::str return false; }; - - if (!CommitTransaction(wtxNew)) + if (!CommitTransaction(wtxNew, &mapPubStealth)) { sError = "Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."; - UndoAnonTransaction(wtxNew); + UndoAnonTransaction(wtxNew, &mapPubStealth); return false; }; - return true; }; @@ -4736,7 +5088,7 @@ bool CWallet::SendAnonToAnon(CStealthAddress& sxAddress, int64_t nValue, int nRi if (vNodes.empty()) { - sError = _("Error: ShadowCoin is not connected!"); + sError = _("Error: Alias is not connected!"); return false; }; @@ -4747,9 +5099,9 @@ bool CWallet::SendAnonToAnon(CStealthAddress& sxAddress, int64_t nValue, int nRi return false; }; - if (nValue + nTransactionFee > GetShadowBalance()) + if (nValue + nTransactionFee > GetSpectreBalance()) { - sError = "Insufficient shadow funds"; + sError = "Insufficient SPECTRE funds"; return false; }; @@ -4758,16 +5110,15 @@ bool CWallet::SendAnonToAnon(CStealthAddress& sxAddress, int64_t nValue, int nRi CScript scriptNarration; // needed to match output id of narr std::vector > vecSend; std::vector > vecChange; + std::map mapPubStealth; - - if (!CreateAnonOutputs(&sxAddress, nValue, sNarr, vecSend, scriptNarration)) + if (!CreateAnonOutputs(&sxAddress, nValue, sNarr, vecSend, scriptNarration, &mapPubStealth)) { sError = "CreateAnonOutputs() failed."; return false; }; - // -- shuffle outputs (any point?) //std::random_shuffle(vecSend.begin(), vecSend.end()); @@ -4780,37 +5131,26 @@ bool CWallet::SendAnonToAnon(CStealthAddress& sxAddress, int64_t nValue, int nRi return false; }; - if (scriptNarration.size() > 0) + if (!SaveNarrationOutput(wtxNew, scriptNarration, sNarr, sError2)) { - for (uint32_t k = 0; k < wtxNew.vout.size(); ++k) - { - if (wtxNew.vout[k].scriptPubKey != scriptNarration) - continue; - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", k) < 1) - { - sError = "Error creating narration key."; - return false; - }; - wtxNew.mapValue[key] = sNarr; - break; - }; - }; - - if (!CommitTransaction(wtxNew)) + LogPrintf("SendAnonToAnon() SaveNarrationOutput failed %s.\n", sError.c_str()); + sError = "SaveNarrationOutput() failed : " + sError2; + return false; + } + if (!CommitTransaction(wtxNew, &mapPubStealth)) { sError = "Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."; - UndoAnonTransaction(wtxNew); + UndoAnonTransaction(wtxNew, &mapPubStealth); return false; }; return true; }; -bool CWallet::SendAnonToSdc(CStealthAddress& sxAddress, int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee) +bool CWallet::SendAnonToSpec(CStealthAddress& sxAddress, int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee) { if (fDebug) - LogPrintf("SendAnonToSdc()\n"); + LogPrintf("SendAnonToSpec()\n"); if (IsLocked()) { @@ -4838,7 +5178,7 @@ bool CWallet::SendAnonToSdc(CStealthAddress& sxAddress, int64_t nValue, int nRin if (vNodes.empty()) { - sError = _("Error: ShadowCoin is not connected!"); + sError = _("Error: Alias is not connected!"); return false; }; @@ -4849,42 +5189,48 @@ bool CWallet::SendAnonToSdc(CStealthAddress& sxAddress, int64_t nValue, int nRin return false; }; - if (nValue + nTransactionFee > GetShadowBalance()) + if (nValue + nTransactionFee > GetSpectreBalance()) { - sError = "Insufficient shadow funds"; + sError = "Insufficient SPECTRE funds"; return false; }; + std::ostringstream ssThrow; + auto [nMinRingSize, nMaxRingSize] = GetRingSizeMinMax(); + if (nRingSize < (int)nMinRingSize || nRingSize > (int)nMaxRingSize) + { + sError = nMinRingSize == nMaxRingSize ? tfm::format("Ring size must be = %d.", nMinRingSize) : + tfm::format("Ring size must be >= %d and <= %d.", nMinRingSize, nMaxRingSize); + return false; + } + wtxNew.nVersion = ANON_TXN_VERSION; std::vector > vecSend; std::vector > vecChange; - std::map mapStealthNarr; - if (!CreateStealthOutput(&sxAddress, nValue, sNarr, vecSend, mapStealthNarr, sError)) + std::map mapScriptNarr; + CScript scriptNarration; + std::string sError2; + if (!CreateStealthOutput(&sxAddress, nValue, sNarr, vecSend, scriptNarration, sError2)) { - LogPrintf("SendCoinsAnon() CreateStealthOutput failed %s.\n", sError.c_str()); + LogPrintf("SendAnonToSpec() CreateStealthOutput failed %s.\n", sError2.c_str()); + sError = "CreateStealthOutput() failed : " + sError2; return false; }; - std::map::iterator itN; - for (itN = mapStealthNarr.begin(); itN != mapStealthNarr.end(); ++itN) + + if (!SaveNarrationOutput(wtxNew, scriptNarration, sNarr, sError2)) { - int pos = itN->first; - char key[64]; - if (snprintf(key, sizeof(key), "n_%u", pos) < 1) - { - LogPrintf("SendCoinsAnon(): Error creating narration key."); - continue; - }; - wtxNew.mapValue[key] = itN->second; - }; + LogPrintf("SendAnonToSpec() SaveNarrationOutput failed %s.\n", sError2.c_str()); + sError = "SaveNarrationOutput() failed : " + sError2; + return false; + } // -- get anon inputs int64_t nFeeRequired; - std::string sError2; if (!AddAnonInputs(nRingSize == 1 ? RING_SIG_1 : RING_SIG_2, nValue, nRingSize, vecSend, vecChange, wtxNew, nFeeRequired, false, sError2)) { - LogPrintf("SendAnonToSdc() AddAnonInputs failed %s.\n", sError2.c_str()); + LogPrintf("SendAnonToSpec() AddAnonInputs failed %s.\n", sError2.c_str()); sError = "AddAnonInputs() failed: " + sError2; return false; }; @@ -4899,6 +5245,26 @@ bool CWallet::SendAnonToSdc(CStealthAddress& sxAddress, int64_t nValue, int nRin return true; }; +bool CWallet::SaveNarrationOutput(CWalletTx& wtxNew, const CScript& scriptNarration, const std::string& sNarr, std::string& sError) +{ + if (scriptNarration.size() > 0) + { + for (uint32_t k = 0; k < wtxNew.vout.size(); ++k) + { + if (wtxNew.vout[k].scriptPubKey != scriptNarration) + continue; + char key[64]; + if (snprintf(key, sizeof(key), "n_%u", k) < 1) + { + sError = "Error creating narration key."; + return false; + }; + wtxNew.mapValue[key] = sNarr; + break; + } + } + return true; +} bool CWallet::ExpandLockedAnonOutput(CWalletDB *pwdb, CKeyID &ckeyId, CLockedAnonOutput &lao, std::set &setUpdated) { @@ -5167,9 +5533,9 @@ bool CWallet::EstimateAnonFee(int64_t nValue, int nRingSize, std::string& sNarr, return false; }; - if (nValue + nTransactionFee > GetShadowBalance()) + if (nValue + nTransactionFee > GetSpectreBalance()) { - sError = "Insufficient shadow funds"; + sError = "Insufficient SPECTRE funds"; return false; }; @@ -5177,14 +5543,14 @@ bool CWallet::EstimateAnonFee(int64_t nValue, int nRingSize, std::string& sNarr, std::vector > vecSend; std::vector > vecChange; - if (!CreateAnonOutputs(NULL, nValue, sNarr, vecSend, scriptNarration)) + if (!CreateAnonOutputs(nullptr, nValue, sNarr, vecSend, scriptNarration)) { sError = "CreateAnonOutputs() failed."; return false; }; int64_t nFeeRequired; - if (!AddAnonInputs(RING_SIG_2, nValue, nRingSize, vecSend, vecChange, wtxNew, nFeeRequired, true, sError)) + if (!AddAnonInputs(nRingSize == 1 ? RING_SIG_1 : RING_SIG_2, nValue, nRingSize, vecSend, vecChange, wtxNew, nFeeRequired, true, sError)) { LogPrintf("EstimateAnonFee() AddAnonInputs failed %s.\n", sError.c_str()); sError = "AddAnonInputs() failed."; @@ -5196,8 +5562,10 @@ bool CWallet::EstimateAnonFee(int64_t nValue, int nRingSize, std::string& sNarr, return true; }; -int CWallet::ListUnspentAnonOutputs(std::list& lUAnonOutputs, bool fMatureOnly) +int CWallet::ListUnspentAnonOutputs(std::list& lUAnonOutputs, MaturityFilter nFilter) const { + LOCK(cs_wallet); + CWalletDB walletdb(strWalletFile, "r"); Dbc* pcursor = walletdb.GetAtCursor(); @@ -5236,19 +5604,24 @@ int CWallet::ListUnspentAnonOutputs(std::list& lUAnonOutputs, if (oao.fSpent) continue; - WalletTxMap::iterator mi = mapWallet.find(oao.outpoint.hash); + WalletTxMap::const_iterator mi = mapWallet.find(oao.outpoint.hash); if (mi == mapWallet.end() || mi->second.nVersion != ANON_TXN_VERSION || mi->second.vout.size() <= oao.outpoint.n || mi->second.IsSpent(oao.outpoint.n)) continue; - // -- txn must be in MIN_ANON_SPEND_DEPTH deep in the blockchain to be spent - if (fMatureOnly - && mi->second.GetDepthInMainChain() < MIN_ANON_SPEND_DEPTH) + + // -- Check maturity + if (nFilter != NONE) { - continue; - }; + // maturity (minDepth) depends on if the output was created in a staking transaction or is used for staking + int minBlockHeight = mi->second.IsCoinStake() || nFilter == MaturityFilter::FOR_STAKING ? + Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; + + if (mi->second.GetDepthInMainChain() < minBlockHeight) + continue; + } // TODO: check ReadAnonOutput? @@ -5273,7 +5646,7 @@ int CWallet::ListUnspentAnonOutputs(std::list& lUAnonOutputs, return 0; } -int CWallet::CountAnonOutputs(std::map& mOutputCounts, bool fMatureOnly) +int CWallet::CountAnonOutputs(std::map& mOutputCounts, MaturityFilter nFilter) const { LOCK(cs_main); CTxDB txdb("r"); @@ -5282,7 +5655,7 @@ int CWallet::CountAnonOutputs(std::map& mOutputCounts, bool fMatur if (!pdb) throw runtime_error("CWallet::CountAnonOutputs() : cannot get leveldb instance"); - leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); + leveldb::Iterator *iterator = pdb->NewIterator(txdb.GetReadOptions()); // Seek to start key. @@ -5311,10 +5684,17 @@ int CWallet::CountAnonOutputs(std::map& mOutputCounts, bool fMatur CAnonOutput anonOutput; ssValue >> anonOutput; + // maturity (minDepth) depends on if the output was created in a staking transaction or is used for staking + int minBlockHeight = anonOutput.fCoinStake || nFilter == MaturityFilter::FOR_STAKING ? + Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; + + // Don't count anons which are compromised by ALL SPENT + int nCompromisedHeight = mapAnonOutputStats[anonOutput.nValue].nCompromisedHeight; - if ((!fMatureOnly - ||(anonOutput.nBlockHeight > 0 && nBestHeight - anonOutput.nBlockHeight >= MIN_ANON_SPEND_DEPTH)) - && (Params().IsProtocolV3(nBestHeight) ? anonOutput.nCompromised == 0 : true)) + if ((nFilter == MaturityFilter::NONE || + (anonOutput.nBlockHeight > 0 && nBestHeight - anonOutput.nBlockHeight + 1 >= minBlockHeight)) // ao confirmed in last block has depth of 1 + && (Params().IsProtocolV3(nBestHeight) ? anonOutput.nCompromised == 0 : true) + && (nCompromisedHeight == 0 || anonOutput.nBlockHeight > nCompromisedHeight - MIN_ANON_SPEND_DEPTH)) { std::map::iterator mi = mOutputCounts.find(anonOutput.nValue); if (mi != mOutputCounts.end()) @@ -5329,22 +5709,30 @@ int CWallet::CountAnonOutputs(std::map& mOutputCounts, bool fMatur return 0; }; -int CWallet::CountAllAnonOutputs(std::list& lOutputCounts, bool fMatureOnly) +int CWallet::CountAllAnonOutputs(std::list& lOutputCounts, int nBlockHeight, std::function funcProgress) { - if (fDebugRingSig) - LogPrintf("CountAllAnonOutputs()\n"); + auto start = std::chrono::high_resolution_clock::now(); + int64_t nTotalAoRead = 0; + int64_t nTotalKiRead = 0; // TODO: there are few enough possible coin values to preinitialise a vector with all of them LOCK(cs_main); CTxDB txdb("r"); + // initialize mapAnonBlockStats for last nMaxAnonBlockCache blocks + mapAnonBlockStats.clear(); + for (int i = nBlockHeight;i >= 0 && i >= nBlockHeight - nMaxAnonBlockCache;--i) + mapAnonBlockStats[i]; + + std::map> mapCompromisedHeights; + txdb.ReadCompromisedAnonHeights(mapCompromisedHeights); + leveldb::DB* pdb = txdb.GetInstance(); if (!pdb) throw runtime_error("CWallet::CountAnonOutputs() : cannot get leveldb instance"); - leveldb::Iterator *iterator = pdb->NewIterator(leveldb::ReadOptions()); - + leveldb::Iterator *iterator = pdb->NewIterator(txdb.GetReadOptions()); // Seek to start key. CPubKey pkZero; @@ -5354,9 +5742,12 @@ int CWallet::CountAllAnonOutputs(std::list& lOutputCounts, boo ssStartKey << make_pair(string("ao"), pkZero); iterator->Seek(ssStartKey.str()); - + uint32_t count = 0; while (iterator->Valid()) - { + { + if (funcProgress && count != 0 && count % 10000 == 0) funcProgress(0, count); + count++; + // Unpack keys and values. CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.write(iterator->key().data(), iterator->key().size()); @@ -5366,62 +5757,103 @@ int CWallet::CountAllAnonOutputs(std::list& lOutputCounts, boo if (strType != "ao") break; + nTotalAoRead++; + CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.write(iterator->value().data(), iterator->value().size()); CAnonOutput ao; ssValue >> ao; - if (strType != "ao") - break; - - int nHeight = ao.nBlockHeight > 0 ? nBestHeight - ao.nBlockHeight : 0; + int nCompromisedHeight = 0; + if (ao.nBlockHeight) + { + // ao confirmed in blocks after the given nBlockHeight are skipped + if (ao.nBlockHeight > nBlockHeight) + { + iterator->Next(); + continue; + } + // Check if ao is compromised as mixin by ALL SPENT + std::map>::iterator it = mapCompromisedHeights.find(ao.nValue); + if (it != mapCompromisedHeights.end() && it->second.size() > 0) + nCompromisedHeight = it->second.front(); + } + bool fCompromised = ao.nCompromised != 0 || (nCompromisedHeight != 0 && nCompromisedHeight - MIN_ANON_SPEND_DEPTH >= ao.nBlockHeight); + int nDepth = ao.nBlockHeight > 0 ? nBlockHeight - ao.nBlockHeight + 1: 0; // ao confirmed in last block has depth of 1 + // maturity for spending (minDepth) depends on if the output was created in a staking transaction + int nMature = nDepth >= (ao.fCoinStake ? Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH); + // mixins defines if this ao is usable as mixin for spending. + int nMixins = nMature && !fCompromised; + // mixinsStaking defines if this ao is usable as mixin for staking. + int nMixinsStaking = nMixins && nDepth >= Params().GetAnonStakeMinConfirmations(); + + int nExists = 0, nUnconfirmed = 0; + if (ao.nBlockHeight) + nExists++; + else + nUnconfirmed++; - if (fMatureOnly - && nHeight < MIN_ANON_SPEND_DEPTH) - { - // -- skip - } else + // -- insert by nValue asc + bool fProcessed = false; + for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) { - // -- insert by nValue asc - bool fProcessed = false; - for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) + if (ao.nValue == it->nValue) { - if (ao.nValue == it->nValue) - { - it->nExists++; - it->nCompromised += ao.nCompromised; - if (it->nLeastDepth > nHeight) - it->nLeastDepth = nHeight; - fProcessed = true; - break; - }; - if (ao.nValue > it->nValue) - continue; - lOutputCounts.insert(it, CAnonOutputCount(ao.nValue, 1, 0, 0, nHeight, ao.nCompromised)); + it->nExists += nExists; + it->nUnconfirmed += nUnconfirmed; + it->nCompromised += fCompromised; + it->nMature += nMature; + it->nMixins += nMixins; + it->nMixinsStaking += nMixinsStaking; + it->nStakes += ao.fCoinStake; + if (it->nLastHeight < ao.nBlockHeight) + it->nLastHeight = ao.nBlockHeight; fProcessed = true; break; }; - if (!fProcessed) - lOutputCounts.push_back(CAnonOutputCount(ao.nValue, 1, 0, 0, nHeight, ao.nCompromised)); + if (ao.nValue > it->nValue) + continue; + lOutputCounts.insert(it, CAnonOutputCount(ao.nValue, nExists, nUnconfirmed, 0, 0, ao.nBlockHeight, fCompromised, nMature, nMixins, nMixinsStaking, ao.fCoinStake, 0)); + fProcessed = true; + break; }; + if (!fProcessed) + lOutputCounts.push_back(CAnonOutputCount(ao.nValue, nExists, nUnconfirmed, 0, 0, ao.nBlockHeight, fCompromised, nMature, nMixins, nMixinsStaking, ao.fCoinStake, 0)); + + + // add last 1000 anon blocks to mapAnonBlockStats + if (ao.nBlockHeight && nBlockHeight - ao.nBlockHeight <= nMaxAnonBlockCache) + { + CAnonBlockStat& anonBlockStat = mapAnonBlockStats[ao.nBlockHeight][ao.nValue]; + anonBlockStat.nCompromisedOutputs += fCompromised; + if (ao.fCoinStake) + anonBlockStat.nStakingOutputs++; + else + anonBlockStat.nOutputs++; + } iterator->Next(); }; + if (funcProgress) funcProgress(0, count); delete iterator; // -- count spends - iterator = pdb->NewIterator(leveldb::ReadOptions()); + iterator = pdb->NewIterator(txdb.GetReadOptions()); ssStartKey.clear(); ssStartKey << make_pair(string("ki"), pkZero); iterator->Seek(ssStartKey.str()); + count = 0; while (iterator->Valid()) - { + { + if (funcProgress && count != 0 && count % 10000 == 0) funcProgress(1, count); + count++; + CDataStream ssKey(SER_DISK, CLIENT_VERSION); ssKey.write(iterator->key().data(), iterator->key().size()); string strType; @@ -5430,34 +5862,60 @@ int CWallet::CountAllAnonOutputs(std::list& lOutputCounts, boo if (strType != "ki") break; + nTotalKiRead++; + CDataStream ssValue(SER_DISK, CLIENT_VERSION); ssValue.write(iterator->value().data(), iterator->value().size()); CKeyImageSpent kis; ssValue >> kis; - - bool fProcessed = false; - for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) + // ki in blocks after the given nBlockHeight are skipped + if (kis.nBlockHeight <= nBlockHeight) { - if (kis.nValue != it->nValue) - continue; - it->nSpends++; - fProcessed = true; - break; - }; - if (!fProcessed) - LogPrintf("WARNING: CountAllAnonOutputs found keyimage without matching anon output value.\n"); + bool fProcessed = false; + for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) + { + if (kis.nValue != it->nValue) + continue; + it->nSpends++; + fProcessed = true; + break; + }; + if (!fProcessed) + LogPrintf("WARNING: CountAllAnonOutputs found keyimage without matching anon output value.\n"); + } iterator->Next(); }; + if (funcProgress) funcProgress(1, count); delete iterator; + // set compromised anon block heights + for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) + { + std::map>::iterator itCompromisedHeights = mapCompromisedHeights.find(it->nValue); + if (itCompromisedHeights != mapCompromisedHeights.end() && itCompromisedHeights->second.size() > 0) + { + it->nCompromisedHeight = itCompromisedHeights->second.front(); +// if (fDebugRingSig) +// for (auto i = itCompromisedHeights->second.size(); i-- > 0; ) +// LogPrintf("CountAllAnonOutputs() : Compromised anon height value %d: index %d height %d\n",it->nValue, i, itCompromisedHeights->second.at(i)); + } + } + + if (fDebugRingSig) + { + auto elapsed = std::chrono::high_resolution_clock::now() - start; + LogPrintf("CountAllAnonOutputs(%d) - processed %d anons, %d keyImages in %d µs\n", nBlockHeight, nTotalAoRead, nTotalKiRead, + std::chrono::duration_cast(elapsed).count()); + } + return 0; }; -int CWallet::CountOwnedAnonOutputs(std::map& mOwnedOutputCounts, bool fMatureOnly) +int CWallet::CountOwnedAnonOutputs(std::map& mOwnedOutputCounts, MaturityFilter nFilter) { if (fDebugRingSig) LogPrintf("CountOwnedAnonOutputs()\n"); @@ -5509,83 +5967,357 @@ int CWallet::CountOwnedAnonOutputs(std::map& mOwnedOutputCounts, b //LogPrintf("[rem] mi->second.GetDepthInMainChain() %d \n", mi->second.GetDepthInMainChain()); //LogPrintf("[rem] mi->second.hashBlock %s \n", mi->second.hashBlock.ToString().c_str()); - // -- txn must be in MIN_ANON_SPEND_DEPTH deep in the blockchain to be spent - + // -- check maturity + if (nFilter != MaturityFilter::NONE) { + // maturity (minDepth) depends on if the output was created in a staking transaction or is used for staking + int minBlockHeight = mi->second.IsCoinStake() || nFilter == MaturityFilter::FOR_STAKING ? + Params().GetAnonStakeMinConfirmations() : MIN_ANON_SPEND_DEPTH; + LOCK(cs_main); - if (fMatureOnly - && mi->second.GetDepthInMainChain() < MIN_ANON_SPEND_DEPTH) - { + if (mi->second.GetDepthInMainChain() < minBlockHeight) continue; - }; + } + + // TODO: check ReadAnonOutput? + + oao.nValue = mi->second.vout[oao.outpoint.n].nValue; + + mOwnedOutputCounts[oao.nValue]++; + }; + + pcursor->close(); + return 0; +}; + +int CWallet::CountLockedAnonOutputs() +{ + if (fDebugRingSig) + { + LogPrintf("%s\n", __func__); + }; + // -- count owned anon outputs received when wallet was locked. + int result = 0; + + CWalletDB walletdb(strWalletFile, "cr+"); + Dbc *pcursor = walletdb.GetTxnCursor(); + if (!pcursor) + throw runtime_error(strprintf("%s : cannot create DB cursor.", __func__).c_str()); + + unsigned int fFlags = DB_SET_RANGE; + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + if (fFlags == DB_SET_RANGE) + ssKey << std::string("lao"); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = walletdb.ReadAtCursor(pcursor, ssKey, ssValue, fFlags); + fFlags = DB_NEXT; + if (ret == DB_NOTFOUND) + { + break; + } + else if (ret != 0) + { + pcursor->close(); + throw runtime_error(strprintf("%s : error scanning DB.", __func__).c_str()); + } + // Unserialize + string strType; + ssKey >> strType; + if (strType != "lao") + break; + + result++; + } + + pcursor->close(); + return result; +} + +uint64_t CWallet::EraseAllAnonData(std::function funcProgress) +{ + LogPrintf("EraseAllAnonData()\n"); + int64_t nStart = GetTimeMillis(); + + LOCK2(cs_main, cs_wallet); + CWalletDB walletdb(strWalletFile, "r+"); + CTxDB txdb("r+"); + + uint32_t nAo = 0; + uint32_t nKi = 0; + + LogPrintf("Erasing anon outputs.\n"); + if (funcProgress) + txdb.EraseRange(std::string("ao"), nAo, [funcProgress] (const uint32_t& nErased) -> void { + funcProgress("ATXO", nErased); + }); + else + txdb.EraseRange(std::string("ao"), nAo); + LogPrintf("Erasing spent key images.\n"); + if (funcProgress) + txdb.EraseRange(std::string("ki"), nKi, [funcProgress] (const uint32_t& nErased) -> void { + funcProgress("key image", nErased); + }); + else + txdb.EraseRange(std::string("ki"), nKi); + + LogPrintf("Erasing compromised anon heights.\n"); + txdb.EraseCompromisedAnonHeights(); + + uint32_t nLao = 0; + uint32_t nOao = 0; + uint32_t nOal = 0; + uint32_t nOol = 0; + + LogPrintf("Erasing locked anon outputs.\n"); + walletdb.EraseRange(std::string("lao"), nLao); + LogPrintf("Erasing owned anon outputs.\n"); + walletdb.EraseRange(std::string("oao"), nOao); + LogPrintf("Erasing anon output links.\n"); + walletdb.EraseRange(std::string("oal"), nOal); + LogPrintf("Erasing old output links.\n"); + walletdb.EraseRange(std::string("ool"), nOol); + + LogPrintf("EraseAllAnonData() Complete, %d %d %d %d %d %d, %15dms\n", nAo, nKi, nLao, nOao, nOal, nOol, GetTimeMillis() - nStart); + mapAnonOutputStats.clear(); + mapAnonBlockStats.clear(); + + return nAo + nKi + nLao + nOao + nOal + nOol; +}; + +bool CWallet::UpdateAnonStats(CTxDB& txdb, int nBlockHeight) +{ + if (fDebug) + LogPrintf("UpdateAnonStats(%d)\n", nBlockHeight); + + AssertLockHeld(cs_main); + + // Update anon cache (mapAnonOutputStats) with block stats (mapAnonBlockStats) + std::map & mapAnonBlockStat = mapAnonBlockStats[nBlockHeight]; + for (const auto & [nValue, anonBlockStat] : mapAnonBlockStat) + { + CAnonOutputCount& anonOutputCount = mapAnonOutputStats[nValue]; + uint16_t nNewAnons = anonBlockStat.nOutputs + anonBlockStat.nStakingOutputs; + anonOutputCount.nSpends += anonBlockStat.nSpends; + anonOutputCount.nExists += nNewAnons; + anonOutputCount.nStakes += anonBlockStat.nStakingOutputs; + if (nNewAnons > 0 && anonOutputCount.nLastHeight < nBlockHeight) + anonOutputCount.nLastHeight = nBlockHeight; + + // Persist compromised anon block height in case all anons of one denomination has been spent + if (anonOutputCount.nMature && anonBlockStat.nSpends && anonOutputCount.nMature - anonOutputCount.nSpends <= 0) + { + LogPrintf("%s: ALL SPENT of mature anon denomination %d in block height %d. -> persist compromised height.\n", + __func__, nValue, nBlockHeight); + fStaleAnonCache = true; + std::map> mapCompromisedHeights; + txdb.ReadCompromisedAnonHeights(mapCompromisedHeights); + std::vector& vCompromisedHeights = mapCompromisedHeights[nValue]; + if (std::find(vCompromisedHeights.begin(), vCompromisedHeights.end(), nBlockHeight) == vCompromisedHeights.end()) + { + // find proper position in descending order + std::vector::iterator it = std::lower_bound(vCompromisedHeights.begin(), vCompromisedHeights.end(), nBlockHeight, std::greater()); + vCompromisedHeights.insert(it, nBlockHeight); // insert before iterator it + if (!txdb.WriteCompromisedAnonHeights(mapCompromisedHeights)) + return error("%s: WriteCompromisedAnonHeights failed for anon value %s block height %d.", __func__, nValue, nBlockHeight); + } + } + } + + if (fStaleAnonCache) + return true; + + // -- Add outputs of new mature block to mapAnonBlockStats + int nMatureHeight = nBlockHeight - MIN_ANON_SPEND_DEPTH + 1; + if (nMatureHeight > 0 ) + { + auto itBlockStatMature = mapAnonBlockStats.find(nMatureHeight); + if (itBlockStatMature == mapAnonBlockStats.end()) + { + LogPrintf("UpdateAnonStats(%d) - Missing stats for block %d => fStaleAnonCache = true\n", nBlockHeight, nMatureHeight); + fStaleAnonCache = true; + return true; + } + std::map mapBlockSpending = itBlockStatMature->second; + for (const auto & [nValue, anonBlockStat] : mapBlockSpending) + { + uint16_t nMixinsUpdate = 0; + if (mapAnonOutputStats[nValue].nCompromisedHeight - MIN_ANON_SPEND_DEPTH < nMatureHeight) + { + nMixinsUpdate = anonBlockStat.nOutputs - anonBlockStat.nCompromisedOutputs; + mapAnonOutputStats[nValue].nMixins += nMixinsUpdate; + } + mapAnonOutputStats[nValue].nMature += anonBlockStat.nOutputs; + if (fDebugRingSig) + LogPrintf("UpdateAnonStats(%d) : [%d/%d] nMature+%d nMixins+%d\n", + nBlockHeight, nValue, nMatureHeight, anonBlockStat.nOutputs, nMixinsUpdate); + } + } + + // -- Add outputs of new stake mature block to mapAnonBlockStats + int nMatureStakeHeight = nBlockHeight - Params().GetAnonStakeMinConfirmations() + 1; + if (nMatureStakeHeight > 0) + { + auto itBlockStatStaking = mapAnonBlockStats.find(nMatureStakeHeight); + if (itBlockStatStaking == mapAnonBlockStats.end()) + { + LogPrintf("UpdateAnonStats(%d) - Missing stats for block %d => fStaleAnonCache = true\n", nBlockHeight, nMatureHeight); + fStaleAnonCache = true; + return true; + } + std::map mapBlockStaking = itBlockStatStaking->second; + for (const auto & [nValue, anonBlockStat] : mapBlockStaking) + { + uint16_t nMixinsUpdate = 0, nMixinsStakingUpdate = 0; + if (mapAnonOutputStats[nValue].nCompromisedHeight - MIN_ANON_SPEND_DEPTH < nMatureStakeHeight) + { + nMixinsUpdate = anonBlockStat.nStakingOutputs; + nMixinsStakingUpdate = anonBlockStat.nStakingOutputs + anonBlockStat.nOutputs - anonBlockStat.nCompromisedOutputs; + mapAnonOutputStats[nValue].nMixins += nMixinsUpdate; + mapAnonOutputStats[nValue].nMixinsStaking += nMixinsStakingUpdate; + } + mapAnonOutputStats[nValue].nMature += anonBlockStat.nStakingOutputs; + if (fDebugRingSig) + LogPrintf("UpdateAnonStats(%d) : [%d/%d] nMature+%d nMixins+%d nMixinsStaking+%d\n", + nBlockHeight, nValue, nMatureStakeHeight, anonBlockStat.nStakingOutputs, nMixinsUpdate, nMixinsStakingUpdate); } - // TODO: check ReadAnonOutput? - - oao.nValue = mi->second.vout[oao.outpoint.n].nValue; + } - mOwnedOutputCounts[oao.nValue]++; - }; + if (mapAnonBlockStats.size() > nMaxAnonBlockCache) + { + auto eraseIter = mapAnonBlockStats.begin(); + std::advance(eraseIter, mapAnonBlockStats.size() - nMaxAnonBlockCache); + mapAnonBlockStats.erase(mapAnonBlockStats.begin(), eraseIter); + } - pcursor->close(); - return 0; -}; + return true; +} -bool CWallet::EraseAllAnonData() +bool CWallet::RemoveAnonStats(CTxDB& txdb, int nBlockHeight) { - LogPrintf("EraseAllAnonData()\n"); - int64_t nStart = GetTimeMillis(); + if (fDebugRingSig) + LogPrintf("RemoveAnonStats(%d)\n", nBlockHeight); - LOCK2(cs_main, cs_wallet); - CWalletDB walletdb(strWalletFile, "r+"); - CTxDB txdb("r+"); + AssertLockHeld(cs_main); - uint32_t nAo = 0; - uint32_t nKi = 0; + // check if compromised height (ALL SPENT) must be removed + for (const auto & [nValue, anonOutputStat] : mapAnonOutputStats) + { + if (anonOutputStat.nCompromisedHeight >= nBlockHeight) + { + std::map> mapCompromisedHeights; + if (!txdb.ReadCompromisedAnonHeights(mapCompromisedHeights)) + return error("%s: ReadCompromisedAnonHeights failed on remove of block %d.", __func__, nBlockHeight); + std::vector& vCompromisedHeights = mapCompromisedHeights[nValue]; + vCompromisedHeights.erase(std::remove(vCompromisedHeights.begin(), vCompromisedHeights.end(), anonOutputStat.nCompromisedHeight), vCompromisedHeights.end()); + if (!txdb.WriteCompromisedAnonHeights(mapCompromisedHeights)) + return error("%s: WriteCompromisedAnonHeights failed on remove of block %d.", __func__, nBlockHeight); + LogPrintf("RemoveAnonStats(%d) : Removed compromised block height %d for value %d\n", nBlockHeight, anonOutputStat.nCompromisedHeight, nValue); + fStaleAnonCache = true; // force rebuild of anon cache + } + } - LogPrintf("Erasing anon outputs.\n"); - txdb.EraseRange(std::string("ao"), nAo); - LogPrintf("Erasing spent key images.\n"); - txdb.EraseRange(std::string("ki"), nKi); + if (fStaleAnonCache) + return true; - uint32_t nLao = 0; - uint32_t nOao = 0; - uint32_t nOal = 0; - uint32_t nOol = 0; + // -- Remove outputs of last mature block from mapAnonBlockStats + int nMatureHeight = nBlockHeight - MIN_ANON_SPEND_DEPTH + 1; + if (nMatureHeight > 0 ) + { + auto itBlockStatMature = mapAnonBlockStats.find(nMatureHeight); + if (itBlockStatMature == mapAnonBlockStats.end()) + { + LogPrintf("RemoveAnonStats(%d) - Missing stats for block %d => fStaleAnonCache = true\n", nBlockHeight, nMatureHeight); + fStaleAnonCache = true; + return true; + } + std::map mapBlockSpending = itBlockStatMature->second; + for (const auto & [nValue, anonBlockStat] : mapBlockSpending) + { + uint16_t nMixinsUpdate = 0; + if (mapAnonOutputStats[nValue].nCompromisedHeight - MIN_ANON_SPEND_DEPTH < nMatureHeight) + { + nMixinsUpdate = anonBlockStat.nOutputs - anonBlockStat.nCompromisedOutputs; + mapAnonOutputStats[nValue].nMixins -= nMixinsUpdate; + } + mapAnonOutputStats[nValue].nMature -= anonBlockStat.nOutputs; + if (fDebugRingSig) + LogPrintf("RemoveAnonStats(%d) : [%d/%d] nMature-%d nMixins-%d\n", + nBlockHeight, nValue, nMatureHeight, anonBlockStat.nOutputs, nMixinsUpdate); + } + } - LogPrintf("Erasing locked anon outputs.\n"); - walletdb.EraseRange(std::string("lao"), nLao); - LogPrintf("Erasing owned anon outputs.\n"); - walletdb.EraseRange(std::string("oao"), nOao); - LogPrintf("Erasing anon output links.\n"); - walletdb.EraseRange(std::string("oal"), nOal); - LogPrintf("Erasing old output links.\n"); - walletdb.EraseRange(std::string("ool"), nOol); + // -- Remove outputs of last stake mature block from mapAnonBlockStats + int nMatureStakeHeight = nBlockHeight - Params().GetAnonStakeMinConfirmations() + 1; + if (nMatureStakeHeight > 0) + { + auto itBlockStatStaking = mapAnonBlockStats.find(nMatureStakeHeight); + if (itBlockStatStaking == mapAnonBlockStats.end()) + { + LogPrintf("RemoveAnonStats(%d) - Missing stats for block %d => fStaleAnonCache = true\n", nBlockHeight, nMatureHeight); + fStaleAnonCache = true; + return true; + } + std::map mapBlockStaking = itBlockStatStaking->second; + for (const auto & [nValue, anonBlockStat] : mapBlockStaking) + { + uint16_t nMixinsUpdate = 0, nMixinsStakingUpdate = 0; + if (mapAnonOutputStats[nValue].nCompromisedHeight - MIN_ANON_SPEND_DEPTH < nMatureStakeHeight) + { + nMixinsUpdate = anonBlockStat.nStakingOutputs; + nMixinsStakingUpdate = anonBlockStat.nStakingOutputs + anonBlockStat.nOutputs - anonBlockStat.nCompromisedOutputs; + mapAnonOutputStats[nValue].nMixins -= nMixinsUpdate; + mapAnonOutputStats[nValue].nMixinsStaking -= nMixinsStakingUpdate; + } + mapAnonOutputStats[nValue].nMature -= anonBlockStat.nStakingOutputs; + if (fDebugRingSig) + LogPrintf("RemoveAnonStats(%d) : [%d/%d] nMature-%d nMixins-%d nMixinsStaking-%d\n", + nBlockHeight, nValue, nMatureStakeHeight, anonBlockStat.nStakingOutputs, nMixinsUpdate, nMixinsStakingUpdate); + } + } + + mapAnonBlockStats.erase(nBlockHeight); - LogPrintf("EraseAllAnonData() Complete, %d %d %d %d %d %d, %15dms\n", nAo, nKi, nLao, nOao, nOal, nOol, GetTimeMillis() - nStart); return true; -}; +} -bool CWallet::CacheAnonStats() +bool CWallet::CacheAnonStats(int nBlockHeight, std::function funcProgress) { if (fDebugRingSig) - LogPrintf("CacheAnonStats()\n"); + LogPrintf("CacheAnonStats(%d)\n", nBlockHeight); - mapAnonOutputStats.clear(); + AssertLockHeld(cs_main); std::list lOutputCounts; - if (CountAllAnonOutputs(lOutputCounts, false) != 0) + if (CountAllAnonOutputs(lOutputCounts, nBlockHeight, funcProgress) != 0) { LogPrintf("Error: CountAllAnonOutputs() failed.\n"); return false; }; + mapAnonOutputStats.clear(); + // initialize stats from nMinTxFee to nMaxAnonOutput + for (int64_t nValue = nMinTxFee; nValue <= nMaxAnonOutput; nValue *= 10) + { + mapAnonOutputStats[nValue].nValue = nValue; + if (nValue < nMaxAnonOutput) + { + mapAnonOutputStats[nValue*3].nValue = nValue*3; + mapAnonOutputStats[nValue*4].nValue = nValue*4; + mapAnonOutputStats[nValue*5].nValue = nValue*5; + } + } + for (std::list::iterator it = lOutputCounts.begin(); it != lOutputCounts.end(); ++it) { mapAnonOutputStats[it->nValue].set( - it->nValue, it->nExists, it->nSpends, it->nOwned, - it->nLeastDepth < 1 ? 0 : nBestHeight - it->nLeastDepth, it->nCompromised); // mapAnonOutputStats stores height in chain instead of depth + it->nValue, it->nExists, it->nUnconfirmed, it->nSpends, it->nOwned, + it->nLastHeight, it->nCompromised, it->nMature, it->nMixins, it->nMixinsStaking, it->nStakes, it->nCompromisedHeight); // mapAnonOutputStats stores height in chain instead of depth }; + fStaleAnonCache = false; return true; }; @@ -5612,12 +6344,10 @@ bool CWallet::InitBloomFilter() if (!pBloomFilter->IsWithinSizeConstraints()) { delete pBloomFilter; - pBloomFilter = NULL; + pBloomFilter = nullptr; return error("Bloom filter is too large."); }; - std::string sAnonPrefix("ao "); - // TODO: don't load addresses created from receiving stealth txns // TODO: exclude change addresses of spent outputs std::set setKeys; @@ -5626,11 +6356,11 @@ bool CWallet::InitBloomFilter() uint32_t nKeysAdded = 0; // -- need to add change addresses too - BOOST_FOREACH(const CKeyID &keyId, setKeys) + for (const CKeyID& keyId : setKeys) { // -- don't add keys generated for aonon outputs (marked with label prefix "ao ") std::map::iterator mi(mapAddressBook.find(keyId)); - if (mi != mapAddressBook.end() && mi->second.compare(0, sAnonPrefix.length(), sAnonPrefix) == 0) + if (mi != mapAddressBook.end() && IsAnonMappingLabel(mi->second)) { if (fDebugRingSig) { @@ -5673,7 +6403,7 @@ bool CWallet::InitBloomFilter() CWalletTx& wtx = (*it).second; // -- add unspent outputs to bloom filters - BOOST_FOREACH(const CTxIn& txin, wtx.vin) + for (const CTxIn& txin : wtx.vin) { if (wtx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -5714,67 +6444,85 @@ bool CWallet::InitBloomFilter() }; +bool CWallet::IsMine(CStealthAddress stealthAddress) +{ + // - check legacy stealth addresses in wallet + for (std::set::iterator it = stealthAddresses.begin(); it != stealthAddresses.end(); ++it) + { + if (it->scan_secret.size() != EC_SECRET_SIZE) + continue; // stealth address in wallet is not owned + if (it->scan_pubkey == stealthAddress.scan_pubkey && it->spend_pubkey != stealthAddress.spend_pubkey) { + return true; // scan & spend public key match, we own this address + } + }; + // - check ext account stealth keys in wallet + for ( ExtKeyAccountMap::const_iterator mi = mapExtAccounts.begin(); mi != mapExtAccounts.end(); ++mi) + { + CExtKeyAccount *ea = mi->second; + for (AccStealthKeyMap::iterator it = ea->mapStealthKeys.begin(); it != ea->mapStealthKeys.end(); ++it) + { + const CEKAStealthKey &aks = it->second; -// NovaCoin: get current stake weight posv2 -uint64_t CWallet::GetStakeWeight() const -{ - // Choose coins to use - int64_t nBalance = GetBalance(); + if (!aks.skScan.IsValid()) + continue; // stealth address in wallet is not valid - if (nBalance <= nReserveBalance) - return false; + if (aks.pkScan == stealthAddress.scan_pubkey && aks.pkSpend == stealthAddress.spend_pubkey) { + return true; // scan & spend public key match, we own this address + } + }; + }; + return false; +} - std::vector vwtxPrev; - set > setCoins; - int64_t nValueIn = 0; +// NovaCoin: get current stake weight PoSv2 or PoSv3 +uint64_t CWallet::GetStakeWeight() const +{ + int64_t nCurrentTime = GetAdjustedTime(); + uint64_t nWeight = 0; + + // -- Get XSPEC weight for staking + int64_t nBalance = GetBalance(); + if (nBalance > nReserveBalance) + { + set > setCoins; + int64_t nValueIn = 0; + if (SelectCoinsForStaking(nBalance - nReserveBalance, nCurrentTime, setCoins, nValueIn)) + nWeight += nValueIn; + } - if (!SelectCoinsForStaking(nBalance - nReserveBalance, GetTime(), setCoins, nValueIn) - || setCoins.empty()) - return false; + return nWeight; +} +uint64_t CWallet::GetSpectreStakeWeight() const +{ + int64_t nCurrentTime = GetAdjustedTime(); uint64_t nWeight = 0; - int64_t nCurrentTime = GetTime(); - CTxDB txdb("r"); - BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + // -- Get SPECTRE weight for staking + if (Params().IsForkV3(nCurrentTime)) { + int64_t nSpectreBalance = GetSpectreBalance(); + if (nSpectreBalance > nReserveBalance) { - LOCK2(cs_main, cs_wallet); - if (nNodeMode == NT_THIN) - { - // -- check txn is in chain - std::map::iterator mi (mapBlockThinIndex.find(pcoin.first->hashBlock)); - if (mi == mapBlockThinIndex.end()) - { - if (fThinFullIndex - || !pindexRear) - continue; - - CDiskBlockThinIndex diskindex; - if (!txdb.ReadBlockThinIndex(pcoin.first->hashBlock, diskindex) - || diskindex.hashNext == 0) - continue; - }; - } else - { - CTxIndex txindex; - if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex)) - continue; - } + std::list lAvailableCoins; + int64_t nAmountCheck = 0; + std::string sError; + if (ListAvailableAnonOutputs(lAvailableCoins, nAmountCheck, MIN_RING_SIZE, MaturityFilter::FOR_STAKING, sError, nSpectreBalance - nReserveBalance)) + nWeight += nAmountCheck; } - - if (nCurrentTime - pcoin.first->nTime > nStakeMinAge) - nWeight += pcoin.first->vout[pcoin.second].nValue; - }; + } return nWeight; } +boost::random::mt19937 stakingDonationRng; +boost::random::uniform_int_distribution<> stakingDonationDistribution(0, 99); + bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key) { CBlockIndex* pindexPrev = pindexBest; @@ -5810,7 +6558,7 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 int64_t nCredit = 0; CScript scriptPubKeyKernel; CTxDB txdb("r"); - BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + for (const auto& pcoin : setCoins) { boost::this_thread::interruption_point(); static int nMaxStakeSearchInterval = 60; @@ -5904,7 +6652,7 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 if (nCredit == 0 || nCredit > nBalance - nReserveBalance) return false; - BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) + for (const auto& pcoin : setCoins) { // Attempt to add more inputs // Only add coins of the same key/address as kernel @@ -5925,16 +6673,6 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 // Do not add additional significant input if (pcoin.first->vout[pcoin.second].nValue >= nStakeCombineThreshold) continue; - // Do not add input that is still too young - if (Params().IsProtocolV3(pindexPrev->nHeight)) - { - // properly handled by selection function - } - else - { - if (nTimeWeight < nStakeMinAge) - continue; - } txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second)); nCredit += pcoin.first->vout[pcoin.second].nValue; @@ -5943,13 +6681,14 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 }; // Calculate coin age reward + int64_t nReward; { - uint64_t nCoinAge; + uint64_t nCoinAge = 0; CTxDB txdb("r"); - if (!txNew.GetCoinAge(txdb, pindexPrev, nCoinAge)) + if (!Params().IsProtocolV3(pindexPrev->nHeight) && !txNew.GetCoinAge(txdb, pindexPrev, nCoinAge)) return error("CreateCoinStake : failed to calculate coin age"); - int64_t nReward = Params().GetProofOfStakeReward(pindexPrev, nCoinAge, nFees); + nReward = Params().GetProofOfStakeReward(pindexPrev, nCoinAge, nFees); if (nReward <= 0) return false; @@ -5967,9 +6706,50 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 } else txNew.vout[1].nValue = nCredit; + // (Possibly) donate the stake to developers, according to the configured probability + int sample = stakingDonationDistribution(stakingDonationRng); + LogPrintf("sample: %d, donation: %d\n", sample, nStakingDonation); + bool fSupplyIncrease = Params().IsForkV4SupplyIncrease(pindexPrev); + if (fSupplyIncrease || sample < nStakingDonation || (pindexPrev->nHeight+1) % 6 == 0) { + LogPrintf("Donating this (potential) stake to the developers\n"); + CBitcoinAddress address(fSupplyIncrease ? Params().GetSupplyIncreaseAddress() : Params().GetDevContributionAddress()); + int64_t reduction = nReward; + // reduce outputs popping as necessary until we've reduced by nReward + if (txNew.vout.size() == 3) { + LogPrintf("donating a split stake\n"); + if (txNew.vout[2].nValue <= reduction) { + // The second part of the split stake was less than or equal to the + // amount we need to reduce by, so we need to un-split the stake. + reduction -= txNew.vout[2].nValue; + txNew.vout.pop_back(); + LogPrintf("undid splitting of stake due to donation exceeding second output size\n"); + } + else { + txNew.vout[2].nValue -= reduction; + reduction = 0; + LogPrintf("successfully took donation from second output of split stake\n"); + } + } + if (reduction > 0) { + if (txNew.vout[1].nValue <= reduction) { + LogPrintf("Total of stake outputs was less than expected credit. Bailing out\n"); + return false; + } + txNew.vout[1].nValue -= reduction; + } + // push a new output donating to the developers + CScript script; + script.SetDestination(address.Get()); + txNew.vout.push_back(CTxOut(nReward, script)); + LogPrintf("donation complete\n"); + } + else { + LogPrintf("Not donating this (potential) stake to the developers\n"); + } + // Sign int nIn = 0; - BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev) + for (const CWalletTx* pcoin : vwtxPrev) { if (!SignSignature(*this, *pcoin, txNew, nIn++)) return error("CreateCoinStake : failed to sign coinstake"); @@ -5985,8 +6765,241 @@ bool CWallet::CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64 } +bool CWallet::CreateAnonCoinStake(unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key) +{ + // Ring size for staking is MIN_RING_SIZE + int nRingSize = MIN_RING_SIZE; + + CBlockIndex* pindexPrev = pindexBest; + CBigNum bnTargetPerCoinDay; + bnTargetPerCoinDay.SetCompact(nBits); + + txNew.vin.clear(); + txNew.vout.clear(); + + // Mark coin stake transaction + CScript scriptEmpty; + scriptEmpty.clear(); + txNew.vout.push_back(CTxOut(0, scriptEmpty)); + + // Choose coins to use + int64_t nBalance = GetSpectreBalance(); + if (nBalance <= nReserveBalance) + return false; + + // ------------------------------------------- + // Select coins with suitable depth + std::list lAvailableCoins; + int64_t nAmountCheck; + std::string sError; + if (!ListAvailableAnonOutputs(lAvailableCoins, nAmountCheck, nRingSize, MaturityFilter::FOR_STAKING, sError, nBalance - nReserveBalance)) + return error(("CreateAnonCoinStake : " + sError).c_str()); + if (lAvailableCoins.empty()) + return false; + + bool fKernelFound = false; + for (const auto & oao : lAvailableCoins) + { + boost::this_thread::interruption_point(); + + static int nMaxStakeSearchInterval = 60; + for (unsigned int n=0; n vPickedCoins; + vPickedCoins.push_back(&oao); + + // -- Check if stake should be split for balancing unspent ATXOs + std::vector vOutAmounts; + // find the anon denomination with the least number of unspent outputs + CAnonOutputCount* lowestAOC = nullptr; + for (auto it = mapAnonOutputStats.rbegin(); it != mapAnonOutputStats.rend(); it++) + { + if (it->first < nMinTxFee * 10) + break; + if (it->first >= oao.nValue) + continue; + if (it->second.numOfUnspends() > UNSPENT_ANON_BALANCE_MIN) + continue; + if (lowestAOC == nullptr || lowestAOC->numOfUnspends() > it->second.numOfUnspends()) + lowestAOC = &it->second; + } + if (lowestAOC) + { + vOutAmounts.push_back(lowestAOC->nValue); + nCredit += oao.nValue - lowestAOC->nValue; + LogPrintf("CreateAnonCoinStake : Split anon stake of value %d to create 1 additional ATXO of value %d which has only %d unspents\n", + oao.nValue, lowestAOC->nValue, lowestAOC->numOfUnspends()); + } + else + nCredit += oao.nValue; + + // -- Add more anon inputs for consolidation + int64_t nMaxCombineOutput = nMaxAnonStakeOutput / 10; + int64_t lastCombineValue = -1; + std::vector vConsolidateCoins; + int nMaxConsolidation = 0, nNumOfConsolidated = 0; + for (const auto & oaoc : lAvailableCoins) + { + if (oaoc.nValue > nMaxCombineOutput) + break; + // skip the input used for staking (TODO could be optimized by considering in combining inputs) + if (&oaoc == &oao) + continue; + if (lastCombineValue != oaoc.nValue) + { + vConsolidateCoins.clear(); + lastCombineValue = oaoc.nValue; + // calculate how many outputs can be consolidated considering the amount of mature unspents + nMaxConsolidation = mapAnonOutputStats[oaoc.nValue].numOfMatureUnspends() - UNSPENT_ANON_BALANCE_MAX; + nNumOfConsolidated = 0; + } + vConsolidateCoins.push_back(&oaoc); + nNumOfConsolidated++; + if (nNumOfConsolidated <= nMaxConsolidation && vConsolidateCoins.size() == 10) + { + vPickedCoins.insert(vPickedCoins.end(), vConsolidateCoins.begin(), vConsolidateCoins.end()); + vConsolidateCoins.clear(); + nCredit += oaoc.nValue * 10; + LogPrintf("CreateAnonCoinStake : Consolidate 10 additional ATXOs of value %d which has %d mature unspents\n", + oaoc.nValue, mapAnonOutputStats[oaoc.nValue].numOfMatureUnspends()); + } + // Consolidate maximal 50 inputs + if (vPickedCoins.size() == 51) + break; + } + + // -- Calculate staking reward + int64_t nReward = Params().GetProofOfAnonStakeReward(pindexPrev, nFees); + if (nReward <= 0) + return error("CreateAnonCoinStake : GetProofOfStakeReward() reward <= 0"); + + // -- Check if staking reward gets donated to developers, according to the configured probability and DCB rules + int sample = stakingDonationDistribution(stakingDonationRng); + LogPrintf("sample: %d, donation: %d\n", sample, nStakingDonation); + bool donateReward = false; + bool fSupplyIncrease = Params().IsForkV4SupplyIncrease(pindexPrev); + if (fSupplyIncrease || sample < nStakingDonation || (pindexPrev->nHeight+1) % 6 == 0) { + LogPrintf("Donating this (potential) stake to the developers\n"); + donateReward = true; + } + else { + LogPrintf("Not donating this (potential) stake to the developers\n"); + nCredit += nReward; + } + + // -- Get stealth address for creating new anon outputs. + CStealthAddress sxAddress; + if (!GetAnonStakeAddress(oao, sxAddress)) + return error("CreateAnonCoinStake : GetAnonStakeAddress() change failed"); + + // -- create anon output + CScript scriptNarration; // needed to match output id of narr + std::vector > vecSend; + std::vector vecSecShared; + std::string sNarr; + if (nCredit) + splitAmount(nCredit, vOutAmounts, nMaxAnonStakeOutput); + if (!CreateAnonOutputs(&sxAddress, vOutAmounts, sNarr, vecSend, scriptNarration, nullptr, &vecSecShared)) + return error("CreateAnonCoinStake : CreateAnonOutputs() failed"); + + // Sort anon ouputs together with corresponding ec_secret ascending by anon value + std::vector> vTxOutSecret; + vTxOutSecret.reserve(vecSend.size()); + for (uint32_t i = 0; i < vecSend.size(); ++i) + vTxOutSecret.push_back(std::make_pair(CTxOut(vecSend.at(i).second, vecSend.at(i).first), vecSecShared.at(i))); + std::sort(vTxOutSecret.begin(), vTxOutSecret.end(), [] (const auto &a, const auto &b) { + return (a.first < b.first); + }); + // Add sorted anon outputs to transaction + for (auto [txOut, secret] : vTxOutSecret) + txNew.vout.push_back(txOut); + + // -- Set one-time private key of vout[1] for signing the block + ec_secret sSpend; + ec_secret sSpendR; + memcpy(&sSpend.e[0], &sxAddress.spend_secret[0], EC_SECRET_SIZE); + if (StealthSharedToSecretSpend(vTxOutSecret.at(0).second, sSpend, sSpendR) != 0) + return error("CreateAnonCoinStake : failed to get private key of anon output"); + key.Set(&sSpendR.e[0], true); + + // -- create donation output + if (donateReward) + { + CBitcoinAddress address(fSupplyIncrease ? Params().GetSupplyIncreaseAddress() : Params().GetDevContributionAddress()); + // push a new output donating to the developers + CScript script; + script.SetDestination(address.Get()); + txNew.vout.push_back(CTxOut(nReward, script)); + LogPrintf("donation complete\n"); + } + + // -- create anon inputs + txNew.vin.resize(vPickedCoins.size()); + uint256 preimage = 0; // not needed for RING_SIG_2 + uint32_t iVin = 0; + // Initialize mixins set + CMixins mixins; + if (!InitMixins(mixins, vPickedCoins, true)) + return error("CreateAnonCoinStake() : InitMixins() failed"); + + for (const auto * pickedCoin : vPickedCoins) + { + int oaoRingIndex; + if (!AddAnonInput(mixins, txNew.vin[iVin], *pickedCoin, RING_SIG_2, nRingSize, oaoRingIndex, true, false, sError)) + return error(("CreateAnonCoinStake() : " + sError).c_str()); + + if (!GenerateRingSignature(txNew.vin[iVin], RING_SIG_2, nRingSize, oaoRingIndex, preimage, sError)) + return error(("CreateAnonCoinStake() : " + sError).c_str()); + + iVin++; + } + + // -- check if new coins already exist (in case random is broken ?) + if (!AreOutputsUnique(txNew)) + return error("CreateAnonCoinStake() : anon outputs are not unique - is random working?!"); + + if (fDebugPoS) + LogPrintf("CreateAnonCoinStake() : added kernel for keyImage %s\n", HexStr(oao.vchImage)); + + fKernelFound = true; + break; + } + } + + if (fKernelFound) + break; // if kernel is found stop searching + } + + if (!fKernelFound) + return false; + + // Limit size + unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + if (nBytes >= MAX_BLOCK_SIZE_GEN/5) + return error("CreateAnonCoinStake() : exceeded coinstake size limit"); + + // Successfully generated coinstake + return true; +} + + // Call after CreateTransaction unless you want to abort -bool CWallet::CommitTransaction(CWalletTx& wtxNew) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, const std::map * const mapPubStealth) { if (!wtxNew.CheckTransaction()) { @@ -6007,11 +7020,13 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew) walletdb.TxnBegin(); txdb.TxnBegin(); std::vector vUpdatedTxns; - if (!ProcessAnonTransaction(&walletdb, &txdb, wtxNew, wtxNew.hashBlock, fIsMine, mapNarr, vUpdatedTxns)) + std::map mapAnonBlockStat; + if (!ProcessAnonTransaction(&walletdb, &txdb, wtxNew, wtxNew.hashBlock, fIsMine, mapNarr, vUpdatedTxns, mapAnonBlockStat, mapPubStealth)) { LogPrintf("%s: ProcessAnonTransaction() failed %s.\n", __func__, wtxNew.GetHash().ToString().c_str()); walletdb.TxnAbort(); txdb.TxnAbort(); + // TODO erase keyImages in mempool return false; } else { @@ -6025,7 +7040,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew) if (!mapNarr.empty()) { - BOOST_FOREACH(const PAIRTYPE(string,string)& item, mapNarr) + for (const auto& item : mapNarr) wtxNew.mapValue[item.first] = item.second; }; @@ -6037,7 +7052,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew) // This is only to keep the database open to defeat the auto-flush for the // duration of this scope. This is the only place where this optimization // maybe makes sense; please don't do it anywhere else. - CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL; + CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : nullptr; // Take key pair from key pool so it won't be used again //reservekey.KeepKey(); // [rm] @@ -6049,7 +7064,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew) // Mark old coins as spent set setCoins; - BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) + for (const CTxIn& txin : wtxNew.vin) { if (wtxNew.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -6079,7 +7094,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew) // - look for new change addresses - BOOST_FOREACH(CTxOut txout, wtxNew.vout) + for (const CTxOut& txout : wtxNew.vout) { if (wtxNew.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) @@ -6135,7 +7150,7 @@ std::string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, std::string return "ABORTED"; if (!CommitTransaction(wtxNew)) - return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); return ""; } @@ -6151,7 +7166,7 @@ std::string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 return _("Insufficient funds"); if (sNarr.length() > 24) - return _("Narration must be 24 characters or less."); + return _("Note must be 24 characters or less."); // Parse Bitcoin address CScript scriptPubKey; @@ -6178,12 +7193,12 @@ std::string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 -DBErrors CWallet::LoadWallet() +DBErrors CWallet::LoadWallet(int& oltWalletVersion, std::function funcProgress) { if (!fFileBacked) return DB_LOAD_OK; - DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); + DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this, oltWalletVersion, funcProgress); if (nLoadWalletRet == DB_NEED_REWRITE) { if (CDB::Rewrite(strWalletFile, "\x04pool")) @@ -6217,13 +7232,6 @@ bool CWallet::SetAddressBookName(const CTxDestination& address, const string& st } // -- fAddKeyToMerkleFilters is always false when adding keys for anonoutputs - if (fOwned - && fAddKeyToMerkleFilters) - { - const CBitcoinAddress& caddress = address; - SecureMsgWalletKeyChanged(caddress.ToString(), strName, nMode); - }; - if (nMode == CT_NEW && pBloomFilter && fAddKeyToMerkleFilters) @@ -6241,7 +7249,7 @@ bool CWallet::SetAddressBookName(const CTxDestination& address, const string& st return pwdb->WriteName(CBitcoinAddress(address).ToString(), strName); } -bool CWallet::DelAddressBookName(const CTxDestination& address) +bool CWallet::DelAddressBookName(const CTxDestination& address, CWalletDB *pwdb) { if (address.type() == typeid(CStealthAddress)) { @@ -6282,17 +7290,14 @@ bool CWallet::DelAddressBookName(const CTxDestination& address) bool fOwned = IsDestMine(*this, address); string sName = ""; - if (fOwned) - { - const CBitcoinAddress& caddress = address; - SecureMsgWalletKeyChanged(caddress.ToString(), sName, CT_DELETED); - }; - NotifyAddressBookChanged(this, address, "", fOwned, CT_DELETED, true); if (!fFileBacked) return false; - return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); + + if (!pwdb) + return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); + return pwdb->EraseName(CBitcoinAddress(address).ToString()); } @@ -6358,7 +7363,7 @@ bool CWallet::NewKeyPool() { LOCK(cs_wallet); CWalletDB walletdb(strWalletFile); - BOOST_FOREACH(int64_t nIndex, setKeyPool) + for (int64_t nIndex : setKeyPool) walletdb.ErasePool(nIndex); setKeyPool.clear(); @@ -6525,7 +7530,7 @@ std::map CWallet::GetAddressBalances() { LOCK(cs_wallet); - BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + for (const auto& walletEntry : mapWallet) { CWalletTx *pcoin = &walletEntry.second; @@ -6565,14 +7570,14 @@ std::set > CWallet::GetAddressGroupings() set< set > groupings; set grouping; - BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + for (const auto& walletEntry : mapWallet) { CWalletTx *pcoin = &walletEntry.second; if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0])) { // group all input addresses with each other - BOOST_FOREACH(CTxIn txin, pcoin->vin) + for (const CTxIn& txin : pcoin->vin) { CTxDestination address; if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address)) @@ -6581,7 +7586,7 @@ std::set > CWallet::GetAddressGroupings() } // group change with input addresses - BOOST_FOREACH(CTxOut txout, pcoin->vout) + for (const CTxOut& txout : pcoin->vout) { if (IsChange(txout)) { @@ -6611,18 +7616,18 @@ std::set > CWallet::GetAddressGroupings() set< set* > uniqueGroupings; // a set of pointers to groups of addresses map< CTxDestination, set* > setmap; // map addresses to the unique group containing it - BOOST_FOREACH(set grouping, groupings) + for (const std::set& grouping : groupings) { // make a set of all the groups hit by this new group set< set* > hits; map< CTxDestination, set* >::iterator it; - BOOST_FOREACH(CTxDestination address, grouping) + for (const CTxDestination& address : grouping) if ((it = setmap.find(address)) != setmap.end()) hits.insert((*it).second); // merge all hit groups into a new single group and delete old groups set* merged = new set(grouping); - BOOST_FOREACH(set* hit, hits) + for (std::set* hit : hits) { merged->insert(hit->begin(), hit->end()); uniqueGroupings.erase(hit); @@ -6631,12 +7636,12 @@ std::set > CWallet::GetAddressGroupings() uniqueGroupings.insert(merged); // update setmap - BOOST_FOREACH(CTxDestination element, *merged) + for (const CTxDestination& element : *merged) setmap[element] = merged; }; set< set > ret; - BOOST_FOREACH(set* uniqueGrouping, uniqueGroupings) + for (std::set* uniqueGrouping : uniqueGroupings) { ret.insert(*uniqueGrouping); delete uniqueGrouping; @@ -6665,7 +7670,7 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int64_t& nBalanceInQuestion, bo vCoins.push_back(&(*it).second); CTxDB txdb("r"); - BOOST_FOREACH(CWalletTx* pcoin, vCoins) + for (CWalletTx* pcoin : vCoins) { // Find the corresponding transaction index CTxIndex txindex; @@ -6675,7 +7680,7 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int64_t& nBalanceInQuestion, bo { if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull())) { - LogPrintf("FixSpentCoins found lost coin %s SDC %s[%d], %s\n", + LogPrintf("FixSpentCoins found lost coin %s ALIAS (public) %s[%d], %s\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing"); nMismatchFound++; nBalanceInQuestion += pcoin->vout[n].nValue; @@ -6687,7 +7692,7 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int64_t& nBalanceInQuestion, bo } else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull())) { - LogPrintf("FixSpentCoins found spent coin %s SDC %s[%d], %s\n", + LogPrintf("FixSpentCoins found spent coin %s ALIAS (public) %s[%d], %s\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing"); nMismatchFound++; nBalanceInQuestion += pcoin->vout[n].nValue; @@ -6708,7 +7713,7 @@ void CWallet::DisableTransaction(const CTransaction &tx) return; // only disconnecting coinstake requires marking input unspent LOCK(cs_wallet); - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { if (tx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) @@ -6740,7 +7745,7 @@ int CWallet::GetChangeAddress(CPubKey &pk) // Don't promote the key to the main map, that will happen when the transaction is processed. CStoredExtKey *pc; - if ((pc = mi->second->ChainInternal()) == NULL) + if ((pc = mi->second->ChainInternal()) == nullptr) return errorN(1, "%s Unknown chain.", __func__); uint32_t nChild; @@ -6880,15 +7885,14 @@ int CWallet::ExtKeyImportLoose(CWalletDB *pwdb, CStoredExtKey &sekIn, bool fBip4 std::vector v; sek.mapValue[EKVT_KEY_TYPE] = SetChar(v, EKT_BIP44_MASTER); - CKeyID idRoot = sek.GetID(); CExtKey evDerivedKey; sek.kp.Derive(evDerivedKey, BIP44_PURPOSE); - evDerivedKey.Derive(evDerivedKey, Params().BIP44ID()); + evDerivedKey.Derive(evDerivedKey, ChainParamsMigration::GetBIP44ID()); v.resize(0); PushUInt32(v, BIP44_PURPOSE); - PushUInt32(v, Params().BIP44ID()); + PushUInt32(v, ChainParamsMigration::GetBIP44ID()); CStoredExtKey sekDerived; sekDerived.nFlags |= EAF_ACTIVE; @@ -7168,7 +8172,7 @@ int CWallet::ExtKeySetMaster(CWalletDB *pwdb, CKeyID &idNewMaster) return 0; }; -int CWallet::ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenerated) +int CWallet::ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenerated, CExtKey* pRootKey) { // - Must pair with ExtKeySetMaster @@ -7185,7 +8189,10 @@ int CWallet::ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenera CExtKey evRootKey; CStoredExtKey sekRoot; - if (ExtKeyNew32(evRootKey) != 0) + + if (pRootKey) + evRootKey = *pRootKey; + else if (ExtKeyNew32(evRootKey) != 0) return errorN(1, "ExtKeyNew32 failed."); std::vector v; @@ -7198,11 +8205,11 @@ int CWallet::ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenera CExtKey evMasterKey; evRootKey.Derive(evMasterKey, BIP44_PURPOSE); - evMasterKey.Derive(evMasterKey, Params().BIP44ID()); + evMasterKey.Derive(evMasterKey, ChainParamsMigration::GetBIP44ID()); std::vector vPath; PushUInt32(vPath, BIP44_PURPOSE); - PushUInt32(vPath, Params().BIP44ID()); + PushUInt32(vPath, ChainParamsMigration::GetBIP44ID()); CStoredExtKey sekMaster; sekMaster.nFlags |= EAF_ACTIVE; @@ -7257,7 +8264,7 @@ int CWallet::ExtKeyCreateAccount(CStoredExtKey *sekAccount, CKeyID &idMaster, CE ekaOut.nFlags |= EAF_HAVE_SECRET; CExtKey evExternal, evInternal, evStealth; - uint32_t nExternal, nInternal, nStealth; + uint32_t nExternal = 0, nInternal = 0, nStealth = 0; if (sekAccount->DeriveNextKey(evExternal, nExternal, false) != 0 || sekAccount->DeriveNextKey(evInternal, nInternal, false) != 0 || sekAccount->DeriveNextKey(evStealth, nStealth, true) != 0) @@ -7642,7 +8649,7 @@ int CWallet::ExtKeyUnlock(const CKeyingMaterial &vMKey) }; -int CWallet::ExtKeyCreateInitial(CWalletDB *pwdb) +int CWallet::ExtKeyCreateInitial(CWalletDB *pwdb, std::string sBip44Key) { LogPrintf("Creating intital extended master key and account.\n"); @@ -7651,7 +8658,27 @@ int CWallet::ExtKeyCreateInitial(CWalletDB *pwdb) if (!pwdb->TxnBegin()) return errorN(1, "TxnBegin failed."); - if (ExtKeyNewMaster(pwdb, idMaster, true) != 0 + CExtKey ekBip44; + if (!sBip44Key.empty()) + { + CExtKey58 eKey58; + if (eKey58.Set58(sBip44Key.c_str()) == 0) + { + if (!eKey58.IsValid(CChainParams::EXT_SECRET_KEY_BTC)) + { + pwdb->TxnAbort(); + return errorN(1, "-bip44key defines invalid key. Key must begin with Alias prefix."); + } + ekBip44 = eKey58.GetKey().GetExtKey(); + LogPrintf("Using given -bip44key for initial master key.\n"); + } else + { + pwdb->TxnAbort(); + return errorN(1, "-bip44key defines invalid key"); + }; + } + + if (ExtKeyNewMaster(pwdb, idMaster, true, ekBip44.IsValid() ? &ekBip44 : nullptr ) != 0 || ExtKeySetMaster(pwdb, idMaster) != 0) { pwdb->TxnAbort(); @@ -7683,7 +8710,7 @@ int CWallet::ExtKeyCreateInitial(CWalletDB *pwdb) } CEKAStealthKey aks; - string strLbl = "Default Stealth Address"; + string strLbl = "Default Private Address"; if (0 != NewStealthKeyFromAccount(pwdb, idDefaultAccount, strLbl, aks)) { pwdb->TxnAbort(); @@ -7696,7 +8723,7 @@ int CWallet::ExtKeyCreateInitial(CWalletDB *pwdb) return errorN(1, "TxnCommit failed."); }; - SetAddressBookName(CBitcoinAddress(newKey.GetID()).Get(), "Default Address", NULL, true, true); + SetAddressBookName(CBitcoinAddress(newKey.GetID()).Get(), "Default Public Address", nullptr, true, true); return 0; } @@ -7723,7 +8750,7 @@ int CWallet::ExtKeyLoadMaster() return 0; }; - if (ExtKeyCreateInitial(&wdb) != 0) + if (ExtKeyCreateInitial(&wdb, GetArg("-bip44key", "")) != 0) return errorN(1, "ExtKeyCreateDefaultMaster failed."); return 0; @@ -7736,14 +8763,14 @@ int CWallet::ExtKeyLoadMaster() if (!wdb.ReadExtKey(idMaster, *pEkMaster)) { delete pEkMaster; - pEkMaster = NULL; + pEkMaster = nullptr; return errorN(1, "ReadExtKey failed to read master ext key."); }; if (!pEkMaster->kp.IsValidP()) // wallet could be locked, check pk { delete pEkMaster; - pEkMaster = NULL; + pEkMaster = nullptr; return errorN(1, " Loaded master ext key is invalid %s.", pEkMaster->GetIDString58().c_str()); }; @@ -7848,7 +8875,7 @@ int CWallet::ExtKeyLoadAccounts() { addr.Set(idAccount, CChainParams::EXT_ACC_HASH); LogPrintf("WARNING: Could not read key %d of account %s\n", i, addr.ToString().c_str()); - sea->vExtKeys[i] = NULL; + sea->vExtKeys[i] = nullptr; delete sek; }; }; @@ -8270,11 +9297,15 @@ int CWallet::ExtKeyUpdateStealthAddress(CWalletDB *pwdb, CExtKeyAccount *sea, CK { if (itp->id == sxId) { - itp->aks.sLabel = sLabel; + itp->aks.sLabel = string(sLabel); if (!pwdb->WriteExtStealthKeyPack(accId, i, aksPak)) return errorN(1, "%s: WriteExtStealthKeyPack %d failed.", __func__, i); - it->second.sLabel = sLabel; + it->second.sLabel = string(sLabel); + + CStealthAddress cekaSxAddr; + if (0 == itp->aks.SetSxAddr(cekaSxAddr)) + NotifyAddressBookChanged(this, cekaSxAddr, cekaSxAddr.label, true, CT_UPDATED, true); return 0; }; @@ -8305,7 +9336,7 @@ int CWallet::NewKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, CPubKey return errorN(1, "%s Unknown account.", __func__); CExtKeyAccount *sea = mi->second; - CStoredExtKey *sek = NULL; + CStoredExtKey *sek = nullptr; uint32_t nExtKey = fInternal ? sea->nActiveInternal : sea->nActiveExternal; @@ -8316,7 +9347,7 @@ int CWallet::NewKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, CPubKey return errorN(1, "%s Unknown chain.", __func__); uint32_t nChildBkp = fHardened ? sek->nHGenerated : sek->nGenerated; - uint32_t nChildOut; + uint32_t nChildOut = 0; if (0 != sek->DeriveNextKey(pkOut, nChildOut, fHardened)) return errorN(1, "%s Derive failed.", __func__); @@ -8403,7 +9434,7 @@ int CWallet::NewStealthKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, uint32_t nChildBkp = sek->nHGenerated; CKey kScan, kSpend; - uint32_t nScanOut, nSpendOut; + uint32_t nScanOut = 0, nSpendOut = 0; if (0 != sek->DeriveNextKey(kScan, nScanOut, true)) return errorN(1, "%s Derive failed.", __func__); @@ -8515,7 +9546,7 @@ int CWallet::NewExtKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, std: CExtKey evNewKey; uint32_t nOldGen = sekAccount->GetCounter(fHardened); - uint32_t nNewChildNo; + uint32_t nNewChildNo = 0; if (sekAccount->DeriveNextKey(evNewKey, nNewChildNo, fHardened) != 0) return errorN(1, "DeriveNextKey failed."); @@ -8758,7 +9789,7 @@ int CWallet::ScanChainFromTime(int64_t nTimeStartScan) CBlockIndex *pindex = pindexGenesisBlock; - if (pindex == NULL) + if (pindex == nullptr) return errorN(1, "%s: Genesis Block is not set.", __func__); while (pindex && pindex->nTime < nTimeStartScan && pindex->pnext) @@ -8831,7 +9862,7 @@ void CWallet::GetAllReserveKeys(set& setAddress) const CWalletDB walletdb(strWalletFile); LOCK2(cs_main, cs_wallet); - BOOST_FOREACH(const int64_t& id, setKeyPool) + for (const int64_t& id : setKeyPool) { CKeyPool keypool; if (!walletdb.ReadPool(id, keypool)) @@ -8871,7 +9902,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const std::set setKeys; GetKeys(setKeys); - BOOST_FOREACH(const CKeyID &keyid, setKeys) + for (const CKeyID& keyid : setKeys) { if (mapKeyBirth.count(keyid) == 0) mapKeyFirstBlock[keyid] = pindexMax; @@ -8894,11 +9925,11 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) const { // ... which are already in a block int nHeight = blit->second->nHeight; - BOOST_FOREACH(const CTxOut &txout, wtx.vout) + for (const CTxOut& txout : wtx.vout) { // iterate over all their outputs ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected); - BOOST_FOREACH(const CKeyID &keyid, vAffected) + for (const CKeyID& keyid : vAffected) { // ... and all their affected keys std::map::iterator rit = mapKeyFirstBlock.find(keyid); @@ -8923,7 +9954,7 @@ bool IsDestMine(const CWallet &wallet, const CTxDestination &dest) static unsigned int HaveKeys(const vector& pubkeys, const CWallet& wallet) { unsigned int nResult = 0; - BOOST_FOREACH(const valtype& pubkey, pubkeys) + for (const valtype& pubkey : pubkeys) { CKeyID keyID = CPubKey(pubkey).GetID(); if (wallet.HaveKey(keyID)) @@ -8972,3 +10003,24 @@ bool IsMine(const CWallet &wallet, const CScript& scriptPubKey) return false; } +int SetupWalletData(const std::string& strWalletFile, const std::string& sBip44Key, const SecureString& strWalletPassphrase) +{ + if (fs::exists(GetDataDir() / strWalletFile)) + { + return errorN(1, "Wallet file already exists."); + } + + CWallet wallet(strWalletFile); + { + CWalletDB wdb(strWalletFile, "cr+"); + if (wallet.ExtKeyCreateInitial(&wdb, sBip44Key) != 0) + return errorN(2, "ExtKeyCreateInitial failed."); + } + + if (!wallet.EncryptWallet(strWalletPassphrase)) { + return errorN(3, "EncryptWallet failed."); + } + bitdb.Flush(false); + return 0; +} + diff --git a/src/wallet.h b/src/wallet.h index 5513119d7f..b231ae25ea 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -1,14 +1,21 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_WALLET_H #define BITCOIN_WALLET_H #include #include #include - +#include #include "main.h" #include "key.h" @@ -16,11 +23,32 @@ #include "keystore.h" #include "crypter.h" #include "script.h" -#include "ui_interface.h" +#include "interface.h" #include "util.h" #include "walletdb.h" #include "stealth.h" #include "smessage.h" +#include "currency.h" + +static const std::string sAnonPrefix = "ao "; +static const std::string sStealthPrefix = "sa "; +static const std::regex reAnonMapping("ao\\s(\\w{16})\\.{3}"); +static const std::regex reAnonOrStealthMapping("(ao|sa)\\s(\\w{16})\\.{3}"); + +static bool IsAnonMappingLabel(const std::string& address) +{ + return regex_match(address, reAnonMapping); +} + +static bool IsAnonOrStealthMappingLabel(const std::string& address) +{ + return regex_match(address, reAnonOrStealthMapping); +} + +static bool IsStealthAddressMappingLabel(const std::string& address, const bool& quickStealthTest = true) +{ + return IsAnonOrStealthMappingLabel(address) || (quickStealthTest ? address.length() == 102 : IsStealthAddress(address)); +} extern bool fWalletUnlockStakingOnly; @@ -30,6 +58,7 @@ class CWalletTx; class CReserveKey; class COutput; class CCoinControl; +class CTxDestinationDetail; typedef std::map StealthKeyMetaMap; typedef std::map mapValue_t; @@ -56,15 +85,12 @@ class CKeyPool int64_t nTime; CPubKey vchPubKey; - CKeyPool() + CKeyPool() : nTime(GetTime()) { - nTime = GetTime(); } - CKeyPool(const CPubKey& vchPubKeyIn) + CKeyPool(const CPubKey& vchPubKeyIn) : nTime(GetTime()), vchPubKey(vchPubKeyIn) { - nTime = GetTime(); - vchPubKey = vchPubKeyIn; } IMPLEMENT_SERIALIZE @@ -79,14 +105,19 @@ class CKeyPool bool IsDestMine(const CWallet &wallet, const CTxDestination &dest); bool IsMine(const CWallet& wallet, const CScript& scriptPubKey); +int SetupWalletData(const std::string& strWalletFile, const std::string& sBip44Key, const SecureString& strWalletPassphrase); + /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances, * and provides the ability to create new transactions. */ class CWallet : public CCryptoKeyStore { public: - bool SelectCoinsForStaking(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet) const; - bool SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl=NULL) const; + bool SelectCoinsForStaking(int64_t nMaxAmount, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet) const; + bool SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl=nullptr) const; + + bool GetStealthAddress(const std::string& address, CStealthAddress& addressRet) const; + bool SaveNarrationOutput(CWalletTx& wtxNew, const CScript& scriptNarration, const std::string& sNarr, std::string& sError); CWalletDB *pwalletdbEncryption; @@ -108,24 +139,24 @@ class CWallet : public CCryptoKeyStore std::set setKeyPool; std::map mapKeyMetadata; - + std::set stealthAddresses; StealthKeyMetaMap mapStealthKeyMeta; - + CStoredExtKey *pEkMaster; CKeyID idDefaultAccount; ExtKeyAccountMap mapExtAccounts; ExtKeyMap mapExtKeys; - + CBloomFilter* pBloomFilter; - + int nLastFilteredHeight; - + uint32_t nStealth, nFoundStealth; // for reporting, zero before use MasterKeyMap mapMasterKeys; unsigned int nMasterKeyMaxID; - + WalletTxMap mapWallet; int64_t nOrderPosNext; std::map mapRequestCount; @@ -135,54 +166,51 @@ class CWallet : public CCryptoKeyStore CPubKey vchDefaultKey; int64_t nTimeFirstKey; - CWallet() + CWallet() : pwalletdbEncryption(nullptr), nWalletVersion(FEATURE_BASE), nWalletMaxVersion(FEATURE_BASE), fFileBacked(false), pEkMaster(nullptr), pBloomFilter(nullptr), nLastFilteredHeight(0), nStealth(0), nFoundStealth(0), nMasterKeyMaxID(0), nOrderPosNext(0), nTimeFirstKey(0) { SetNull(); } - - CWallet(std::string strWalletFileIn) + + CWallet(std::string strWalletFileIn) : pwalletdbEncryption(nullptr), nWalletVersion(FEATURE_BASE), nWalletMaxVersion(FEATURE_BASE), fFileBacked(true), strWalletFile(strWalletFileIn), pEkMaster(nullptr), pBloomFilter(nullptr), nLastFilteredHeight(0), nStealth(0), nFoundStealth(0), nMasterKeyMaxID(0), nOrderPosNext(0), nTimeFirstKey(0) { SetNull(); - - strWalletFile = strWalletFileIn; - fFileBacked = true; } - + void SetNull() { nWalletVersion = FEATURE_BASE; nWalletMaxVersion = FEATURE_BASE; fFileBacked = false; nMasterKeyMaxID = 0; - pwalletdbEncryption = NULL; - pBloomFilter = NULL; - pEkMaster = NULL; + pwalletdbEncryption = nullptr; + pBloomFilter = nullptr; + pEkMaster = nullptr; nOrderPosNext = 0; nTimeFirstKey = 0; nLastFilteredHeight = 0; - + } - + int Finalise(); - + // check whether we are allowed to upgrade (or already support) to the named feature bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } void AvailableCoinsForStaking(std::vector& vCoins, unsigned int nSpendTime) const; - void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL) const; + void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=nullptr) const; bool SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, int64_t& nValueRet) const; // keystore implementation // Generate a new key CPubKey GenerateNewKey(); - + // Adds a key to the store, and saves it to disk. bool AddKey(const CKey &key); bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey); - + bool AddKeyInDBTxn(CWalletDB *pdb, const CKey &key); - - + + // Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } // Load metadata (used by LoadWallet) @@ -196,7 +224,7 @@ class CWallet : public CCryptoKeyStore bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); bool AddCScript(const CScript& redeemScript); bool LoadCScript(const CScript& redeemScript); - + bool Lock(); bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); @@ -208,7 +236,7 @@ class CWallet : public CCryptoKeyStore /** Increment the next transaction order id @return next transaction order id */ - int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL); + int64_t IncOrderPosNext(CWalletDB *pwalletdb = nullptr); typedef std::pair TxPair; typedef std::multimap TxItems; @@ -222,76 +250,90 @@ class CWallet : public CCryptoKeyStore void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, const uint256& hashIn); bool AddToWalletIfInvolvingMe(const CTransaction& tx, const uint256& hash, const void* pblock, bool fUpdate = false, bool fFindBlock = false); - + bool EraseFromWallet(uint256 hash); void WalletUpdateSpent(const CTransaction& prevout, bool fBlock = false); - int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); + uint32_t ClearWalletTransactions(bool onlyUnaccepted); + int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, std::function funcProgress = nullptr, int progressBatchSize=1000); + void ReacceptWalletTransactions(); void ResendWalletTransactions(bool fForce = false); int64_t GetBalance() const; - int64_t GetShadowBalance() const; - + int64_t GetSpectreBalance() const; + int64_t GetUnconfirmedBalance() const; int64_t GetImmatureBalance() const; int64_t GetStake() const; int64_t GetNewMint() const; - - bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, int64_t& nFeeRet, int32_t& nChangePos, const CCoinControl *coinControl=NULL); - bool CreateTransaction(CScript scriptPubKey, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, int64_t& nFeeRet, const CCoinControl *coinControl=NULL); - - bool CommitTransaction(CWalletTx& wtxNew); - + int64_t GetUnconfirmedSpectreBalance() const; + int64_t GetImmatureSpectreBalance() const; + int64_t GetSpectreStake() const; + + bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, int64_t& nFeeRet, int32_t& nChangePos, const CCoinControl *coinControl=nullptr); + bool CreateTransaction(CScript scriptPubKey, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, int64_t& nFeeRet, const CCoinControl *coinControl=nullptr); + + bool CommitTransaction(CWalletTx& wtxNew, const std::map * const mapPubStealth=nullptr); + uint64_t GetStakeWeight() const; + uint64_t GetSpectreStakeWeight() const; bool CreateCoinStake(unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key); + bool CreateAnonCoinStake(unsigned int nBits, int64_t nSearchInterval, int64_t nFees, CTransaction& txNew, CKey& key); std::string SendMoney(CScript scriptPubKey, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee=false); std::string SendMoneyToDestination(const CTxDestination& address, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee=false); - + bool NewStealthAddress(std::string& sError, std::string& sLabel, CStealthAddress& sxAddr); bool AddStealthAddress(CStealthAddress& sxAddr); bool UnlockStealthAddresses(const CKeyingMaterial& vMasterKeyIn); bool UpdateStealthAddress(std::string &addr, std::string &label, bool addIfNotExist); - - bool CreateStealthTransaction(CScript scriptPubKey, int64_t nValue, std::vector& P, std::vector& narr, std::string& sNarr, CWalletTx& wtxNew, int64_t& nFeeRet, const CCoinControl* coinControl=NULL); - std::string SendStealthMoney(CScript scriptPubKey, int64_t nValue, std::vector& P, std::vector& narr, std::string& sNarr, CWalletTx& wtxNew, bool fAskFee=false); - bool SendStealthMoneyToDestination(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); + bool FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNarr); - - bool UpdateAnonTransaction(CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash); - bool UndoAnonTransaction(const CTransaction& tx); - bool ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash, bool& fIsMine, mapValue_t& mapNarr, std::vector& vUpdatedTxns); - + + bool UndoAnonTransaction(const CTransaction& tx, const std::map * const mapPubStealth=nullptr, bool fEraseTx=true); + bool ProcessAnonTransaction(CWalletDB *pwdb, CTxDB *ptxdb, const CTransaction& tx, const uint256& blockHash, bool& fIsMine, mapValue_t& mapNarr, std::vector& vUpdatedTxns, std::map& mapAnonBlockStat, const std::map * const mapPubStealth=nullptr); + bool GetAnonChangeAddress(CStealthAddress& sxAddress); - bool CreateStealthOutput(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, std::map& mapNarr, std::string& sError); - bool CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration); - int PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRingSize, CWalletTx& wtxNew, int nOutputs, int nSizeOutputs, int& nExpectChangeOuts, std::list& lAvailableCoins, std::vector& vPickedCoins, std::vector >& vecChange, bool fTest, std::string& sError); + bool GetAnonStakeAddress(const COwnedAnonOutput& stakedOao, CStealthAddress& sxAddress); + bool CreateStealthOutput(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::string& sError); + bool CreateAnonOutputs(CStealthAddress* sxAddress, int64_t nValue, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::map * const mapPubStealth=nullptr, std::vector * const vecSecShared=nullptr, int64_t maxAnonOutput = nMaxAnonOutput); + bool CreateAnonOutputs(CStealthAddress* sxAddress, std::vector& vOutAmounts, std::string& sNarr, std::vector >& vecSend, CScript& scriptNarration, std::map * const mapPubStealth=nullptr, std::vector * const vecSecShared=nullptr); + int PickAnonInputs(int rsType, int64_t nValue, int64_t& nFee, int nRingSize, CWalletTx& wtxNew, int nOutputs, int nSizeOutputs, int& nExpectChangeOuts, std::list& lAvailableCoins, std::vector& vPickedCoins, std::vector >& vecChange, bool fTest, std::string& sError, int feeMode = 0); int GetTxnPreImage(CTransaction& txn, uint256& hash); - int PickHidingOutputs(int64_t nValue, int nRingSize, CPubKey& pkCoin, int skip, uint8_t* p); - bool AreOutputsUnique(CWalletTx& wtxNew); - bool AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, std::vector >&vecSend, std::vector >&vecChange, CWalletTx& wtxNew, int64_t& nFeeRequired, bool fTestOnly, std::string& sError); - bool SendSdcToAnon(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); + bool InitMixins(CMixins& mixins, const std::vector& vPickedCoins, bool fStaking); + int PickHidingOutputs(CMixins& mixins, int64_t nValue, int nRingSize, int skip, uint8_t* p); + bool AreOutputsUnique(CTransaction& txNew); + bool GenerateRingSignature(CTxIn& txin, const int& rsType, const int& nRingSize, const int& nSecretOffset, const uint256& preimage, std::string& sError); + bool AddAnonInput(CMixins& mixins, CTxIn& txin, const COwnedAnonOutput& oao, int rsType, int nRingSize, int& oaoRingIndex, bool fStaking, bool fTestOnly, std::string& sError); + bool AddAnonInputs(int rsType, int64_t nTotalOut, int nRingSize, const std::vector >&vecSend, std::vector >&vecChange, CWalletTx& wtxNew, int64_t& nFeeRequired, bool fTestOnly, std::string& sError); + + bool SendSpecToAnon(CStealthAddress& sxAddress, int64_t nValue, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); bool SendAnonToAnon(CStealthAddress& sxAddress, int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); - bool SendAnonToSdc(CStealthAddress& sxAddress, int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); - + bool SendAnonToSpec(CStealthAddress& sxAddress, int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); + bool ExpandLockedAnonOutput(CWalletDB *pdb, CKeyID &ckeyId, CLockedAnonOutput &lao, std::set &setUpdated); bool ProcessLockedAnonOutputs(); - + bool EstimateAnonFee(int64_t nValue, int nRingSize, std::string& sNarr, CWalletTx& wtxNew, int64_t& nFeeRet, std::string& sError); - - int ListUnspentAnonOutputs(std::list& lUAnonOutputs, bool fMatureOnly); - int CountAnonOutputs(std::map& mOutputCounts, bool fMatureOnly); - int CountAllAnonOutputs(std::list& lOutputCounts, bool fMatureOnly); - int CountOwnedAnonOutputs(std::map& mOwnedOutputCounts, bool fMatureOnly); - - bool EraseAllAnonData(); - - bool CacheAnonStats(); - - + + enum MaturityFilter { NONE, FOR_SPENDING, FOR_STAKING }; + int ListUnspentAnonOutputs(std::list& lUAnonOutputs, MaturityFilter nFilter) const; + bool ListAvailableAnonOutputs(std::list& lAvailableAnonOutputs, int64_t& nAmountCheck, int nRingSize, MaturityFilter nFilter, std::string& sError, int64_t nMaxAmount = MAX_MONEY) const; + int CountAnonOutputs(std::map& mOutputCounts, MaturityFilter nFilter) const; + int CountAllAnonOutputs(std::list& lOutputCounts, int nBlockHeight, std::function funcProgress = nullptr); + int CountOwnedAnonOutputs(std::map& mOwnedOutputCounts, MaturityFilter nFilter); + int CountLockedAnonOutputs(); + + uint64_t EraseAllAnonData(std::function funcProgress = nullptr); + + bool CacheAnonStats(int nBlockHeight, std::function funcProgress = nullptr); + bool UpdateAnonStats(CTxDB& txdb, int nBlockHeight); + bool RemoveAnonStats(CTxDB& txdb, int nBlockHeight); + void AddToAnonBlockStats(const std::map& mapAnonBlockStat, int nBlockHeight); + bool InitBloomFilter(); - + bool NewKeyPool(); bool TopUpKeyPool(unsigned int nSize = 0); int64_t AddReserveKey(const CKeyPool& keypool); @@ -305,11 +347,13 @@ class CWallet : public CCryptoKeyStore std::set > GetAddressGroupings(); std::map GetAddressBalances(); + bool IsMine(CStealthAddress stealthAddress); + bool IsMine(const CTxIn& txin) const; int64_t GetDebit(const CTxIn& txin) const; - int64_t GetShadowDebit(const CTxIn& txin) const; - int64_t GetShadowCredit(const CTxOut& txout) const; - + int64_t GetSpectreDebit(const CTxIn& txin) const; + int64_t GetSpectreCredit(const CTxOut& txout) const; + bool IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); @@ -329,7 +373,7 @@ class CWallet : public CCryptoKeyStore } bool IsMine(const CTransaction& tx) const { - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) if (IsMine(txout) && txout.nValue >= nMinimumInputValue) return true; return false; @@ -338,36 +382,48 @@ class CWallet : public CCryptoKeyStore { return (GetDebit(tx) > 0); } - + int64_t GetDebit(const CTransaction& tx) const { int64_t nDebit = 0; - BOOST_FOREACH(const CTxIn& txin, tx.vin) - { + for (const CTxIn& txin : tx.vin) { if (tx.nVersion == ANON_TXN_VERSION && txin.IsAnonInput()) { - nDebit += GetShadowDebit(txin); + nDebit += GetSpectreDebit(txin); } else { nDebit += GetDebit(txin); }; - + if (!MoneyRange(nDebit)) throw std::runtime_error("CWallet::GetDebit() : value out of range"); } return nDebit; } - + + bool IsForeignAnonCoinStake(const CTransaction& tx) const + { + bool fNeedsWalletUnlock = false; + int64_t nSPEC = 0, nSpectre = 0; + if (tx.IsAnonCoinStake() && GetCredit(tx, nSPEC, nSpectre) && nSpectre > 0) { + for (const CTxIn& txin : tx.vin) { + if (GetSpectreDebit(txin) == 0) + return true; + } + } + return fNeedsWalletUnlock; + } + int64_t GetCredit(const CTransaction& tx) const { int64_t nCredit = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { if (tx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { - nCredit += GetShadowCredit(txout); + nCredit += GetSpectreCredit(txout); } else nCredit += GetCredit(txout); if (!MoneyRange(nCredit)) @@ -375,30 +431,30 @@ class CWallet : public CCryptoKeyStore } return nCredit; } - - bool GetCredit(const CTransaction& tx, int64_t& nSDC, int64_t& nShadow) const + + bool GetCredit(const CTransaction& tx, int64_t& nSPEC, int64_t& nSpectre) const { - nSDC = 0; - nShadow = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + nSPEC = 0; + nSpectre = 0; + for (const CTxOut& txout : tx.vout) { if (tx.nVersion == ANON_TXN_VERSION && txout.IsAnonOutput()) { - nShadow += GetShadowCredit(txout); + nSpectre += GetSpectreCredit(txout); } else - nSDC += GetCredit(txout); - if (!MoneyRange(nSDC) - || !MoneyRange(nShadow)) + nSPEC += GetCredit(txout); + if (!MoneyRange(nSPEC) + || !MoneyRange(nSpectre)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); } return true; }; - + int64_t GetChange(const CTransaction& tx) const { int64_t nChange = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { nChange += GetChange(txout); if (!MoneyRange(nChange)) @@ -407,14 +463,14 @@ class CWallet : public CCryptoKeyStore return nChange; } void SetBestChain(const CBlockLocator& loc); - + void SetBestThinChain(const CBlockThinLocator& loc); - DBErrors LoadWallet(); + DBErrors LoadWallet(int& oltWalletVersion, std::function funcProgress); - bool SetAddressBookName(const CTxDestination& address, const std::string& strName, CWalletDB *pwdb = NULL, bool fAddKeyToMerkleFilters = true, bool fManual = false); + bool SetAddressBookName(const CTxDestination& address, const std::string& strName, CWalletDB *pwdb = nullptr, bool fAddKeyToMerkleFilters = true, bool fManual = false); - bool DelAddressBookName(const CTxDestination& address); + bool DelAddressBookName(const CTxDestination& address, CWalletDB *pwdb = nullptr); void UpdatedTransaction(const uint256 &hashTx); @@ -441,7 +497,7 @@ class CWallet : public CCryptoKeyStore bool SetDefaultKey(const CPubKey &vchPubKey); // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower - bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false); + bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = nullptr, bool fExplicit = false); // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format) bool SetMaxVersion(int nVersion); @@ -451,88 +507,88 @@ class CWallet : public CCryptoKeyStore void FixSpentCoins(int& nMismatchSpent, int64_t& nBalanceInQuestion, bool fCheckOnly = false); void DisableTransaction(const CTransaction &tx); - - + + int GetChangeAddress(CPubKey &pk); - + int ExtKeyNew32(CExtKey &out); int ExtKeyNew32(CExtKey &out, const char *sPassPhrase, int32_t nHash, const char *sSeed); int ExtKeyNew32(CExtKey &out, uint8_t *data, uint32_t lenData); - + int ExtKeyImportLoose(CWalletDB *pwdb, CStoredExtKey &sekIn, bool fBip44, bool fSaveBip44); int ExtKeyImportAccount(CWalletDB *pwdb, CStoredExtKey &sekIn, int64_t nTimeStartScan, const std::string &sLabel); - + int ExtKeySetMaster(CWalletDB *pwdb, CKeyID &idMaster); // set master to existing key, remove master key tag from old key if exists - int ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenerated = false); // make and save new root key to wallet - + int ExtKeyNewMaster(CWalletDB *pwdb, CKeyID &idMaster, bool fAutoGenerated = false, CExtKey* pRootKey = nullptr); // make and save new root key to wallet + int ExtKeyCreateAccount(CStoredExtKey *ekAccount, CKeyID &idMaster, CExtKeyAccount &ekaOut, const std::string &sLabel); int ExtKeyDeriveNewAccount(CWalletDB *pwdb, CExtKeyAccount *sea, const std::string &sLabel, const std::string &sPath=""); // derive a new account from the master key and save to wallet - - + + int ExtKeyEncrypt(CStoredExtKey *sek, const CKeyingMaterial &vMKey, bool fLockKey); int ExtKeyEncrypt(CExtKeyAccount *sea, const CKeyingMaterial &vMKey, bool fLockKey); int ExtKeyEncryptAll(CWalletDB *pwdb, const CKeyingMaterial &vMKey); int ExtKeyLock(); - + int ExtKeyUnlock(CExtKeyAccount *sea); int ExtKeyUnlock(CExtKeyAccount *sea, const CKeyingMaterial &vMKey); int ExtKeyUnlock(CStoredExtKey *sek); int ExtKeyUnlock(CStoredExtKey *sek, const CKeyingMaterial &vMKey); int ExtKeyUnlock(const CKeyingMaterial &vMKey); - - int ExtKeyCreateInitial(CWalletDB *pwdb); + + int ExtKeyCreateInitial(CWalletDB *pwdb, std::string sBip44Key = ""); int ExtKeyLoadMaster(); int ExtKeyLoadAccounts(); - + int ExtKeySaveAccountToDB(CWalletDB *pwdb, CKeyID &idAccount, CExtKeyAccount *sea); int ExtKeyAddAccountToMaps(CKeyID &idAccount, CExtKeyAccount *sea); int ExtKeyLoadAccountPacks(); - - + + int ExtKeyAppendToPack(CWalletDB *pwdb, CExtKeyAccount *sea, const CKeyID &idKey, CEKAKey &ak, bool &fUpdateAcc) const; int ExtKeyAppendToPack(CWalletDB *pwdb, CExtKeyAccount *sea, const CKeyID &idKey, CEKASCKey &asck, bool &fUpdateAcc) const; - - - + + + int ExtKeySaveKey(CWalletDB *pwdb, CExtKeyAccount *sea, const CKeyID &keyId, CEKAKey &ak) const; int ExtKeySaveKey(CExtKeyAccount *sea, const CKeyID &keyId, CEKAKey &ak) const; - + int ExtKeySaveKey(CWalletDB *pwdb, CExtKeyAccount *sea, const CKeyID &keyId, CEKASCKey &asck) const; int ExtKeySaveKey(CExtKeyAccount *sea, const CKeyID &keyId, CEKASCKey &asck) const; - + int ExtKeyUpdateStealthAddress(CWalletDB *pwdb, CExtKeyAccount *sea, CKeyID &sxId, std::string &sLabel); - + int NewKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, CPubKey &pkOut, bool fInternal, bool fHardened); int NewKeyFromAccount(CPubKey &pkOut, bool fInternal=false, bool fHardened=false); // wrapper - use default account - + int NewStealthKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, std::string &sLabel, CEKAStealthKey &akStealthOut); int NewStealthKeyFromAccount(std::string &sLabel, CEKAStealthKey &akStealthOut); // wrapper - use default account - + int NewExtKeyFromAccount(CWalletDB *pwdb, const CKeyID &idAccount, std::string &sLabel, CStoredExtKey *sekOut); int NewExtKeyFromAccount(std::string &sLabel, CStoredExtKey *sekOut); // wrapper - use default account - - + + int ExtKeyGetDestination(const CExtKeyPair &ek, CScript &scriptPubKeyOut, uint32_t &nKey); int ExtKeyUpdateLooseKey(const CExtKeyPair &ek, uint32_t nKey, bool fAddToAddressBook); - - + + bool HaveKey(const CKeyID &address) const; - + bool HaveExtKey(const CKeyID &address) const; - + bool GetKey(const CKeyID &address, CKey &keyOut) const; - + bool GetPubKey(const CKeyID &address, CPubKey &pkOut) const; - + bool HaveStealthAddress(const CStealthAddress &sxAddr) const; - + int ScanChainFromTime(int64_t nTimeStartScan); - + /** Address book entry changed. * @note called with lock cs_wallet held. */ boost::signals2::signal NotifyAddressBookChanged; - + /** Wallet transaction added, removed or updated. * @note called with lock cs_wallet held. @@ -548,10 +604,8 @@ class CReserveKey int64_t nIndex; CPubKey vchPubKey; public: - CReserveKey(CWallet* pwalletIn) + CReserveKey(CWallet* pwalletIn) : pwallet(pwalletIn), nIndex(-1) { - nIndex = -1; - pwallet = pwalletIn; } ~CReserveKey() @@ -603,43 +657,43 @@ class CWalletTx : public CMerkleTx std::string strFromAccount; std::vector vfSpent; // which outputs are already spent int64_t nOrderPos; // position in ordered transaction list - + // memory only mutable int8_t fDebitCached; // overload for force update message mutable bool fCreditCached; mutable bool fAvailableCreditCached; mutable bool fChangeCached; - mutable bool fAvailableShadowCreditCached; + mutable bool fAvailableSpectreCreditCached; mutable bool fCreditSplitCached; mutable int64_t nDebitCached; mutable int64_t nCreditCached; mutable int64_t nAvailableCreditCached; mutable int64_t nChangeCached; - mutable int64_t nAvailableShadowCreditCached; - - mutable int64_t nCredSDCCached; - mutable int64_t nCredShadowCached; - + mutable int64_t nAvailableSpectreCreditCached; + + mutable int64_t nCredSPECCached; + mutable int64_t nCredSpectreCached; + CWalletTx() { - Init(NULL); + Init(nullptr); } - + CWalletTx(const CWallet* pwalletIn) { Init(pwalletIn); } - + CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn) { Init(pwalletIn); } - + CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn) { Init(pwalletIn); } - + void Init(const CWallet* pwalletIn) { pwallet = pwalletIn; @@ -655,17 +709,17 @@ class CWalletTx : public CMerkleTx fDebitCached = false; fCreditCached = false; fAvailableCreditCached = false; - fAvailableShadowCreditCached = false; - - nCredSDCCached = 0; - nCredShadowCached = 0; + fAvailableSpectreCreditCached = false; + + nCredSPECCached = 0; + nCredSpectreCached = 0; fCreditSplitCached = false; - + fChangeCached = false; nDebitCached = 0; nCreditCached = 0; nAvailableCreditCached = 0; - nAvailableShadowCreditCached = 0; + nAvailableSpectreCreditCached = 0; nChangeCached = 0; nOrderPos = -1; } @@ -674,7 +728,7 @@ class CWalletTx : public CMerkleTx ( CWalletTx* pthis = const_cast(this); if (fRead) - pthis->Init(NULL); + pthis->Init(nullptr); char fSpent = false; if (!fRead) @@ -682,7 +736,7 @@ class CWalletTx : public CMerkleTx pthis->mapValue["fromaccount"] = pthis->strFromAccount; std::string str; - BOOST_FOREACH(char f, vfSpent) + for (char f : vfSpent) { str += (f ? '1' : '0'); if (f) @@ -711,13 +765,13 @@ class CWalletTx : public CMerkleTx if (mapValue.count("spent")) { - BOOST_FOREACH(char c, pthis->mapValue["spent"]) + for (char c : pthis->mapValue["spent"]) pthis->vfSpent.push_back(c != '0'); } else { pthis->vfSpent.assign(vout.size(), fSpent); }; - + ReadOrderPos(pthis->nOrderPos, pthis->mapValue); pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0; @@ -745,6 +799,7 @@ class CWalletTx : public CMerkleTx vfSpent[i] = true; fReturn = true; fAvailableCreditCached = false; + fAvailableSpectreCreditCached = false; }; }; return fReturn; @@ -755,12 +810,12 @@ class CWalletTx : public CMerkleTx { fCreditCached = false; fAvailableCreditCached = false; - fAvailableShadowCreditCached = false; + fAvailableSpectreCreditCached = false; fDebitCached = false; fChangeCached = false; fCreditSplitCached = false; } - + bool ForceUpdate() { return fDebitCached == 2; @@ -776,7 +831,7 @@ class CWalletTx : public CMerkleTx { if (nOut >= vout.size()) throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range"); - + vfSpent.resize(vout.size()); if (!vfSpent[nOut]) { @@ -789,7 +844,7 @@ class CWalletTx : public CMerkleTx { if (nOut >= vout.size()) throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range"); - + vfSpent.resize(vout.size()); if (vfSpent[nOut]) { @@ -811,7 +866,7 @@ class CWalletTx : public CMerkleTx { if (vin.empty()) return 0; - if (fDebitCached) + if (fDebitCached == 1) return nDebitCached; nDebitCached = pwallet->GetDebit(*this); fDebitCached = true; @@ -831,27 +886,27 @@ class CWalletTx : public CMerkleTx fCreditCached = true; return nCreditCached; } - - bool GetCredit(int64_t& nCredSDC, int64_t& nCredShadow, bool fUseCache=true) const + + bool GetCredit(int64_t& nCredSPEC, int64_t& nCredSpectre, bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) { - nCredSDC = nCredShadow = 0; + nCredSPEC = nCredSpectre = 0; return true; } - + // GetBalance can assume transactions in mapWallet won't change if (!fUseCache || !fCreditSplitCached) { - nCredSDCCached = 0; - nCredShadowCached = 0; - pwallet->GetCredit(*this, nCredSDCCached, nCredShadowCached); + nCredSPECCached = 0; + nCredSpectreCached = 0; + pwallet->GetCredit(*this, nCredSPECCached, nCredSpectreCached); fCreditSplitCached = true; }; - - nCredSDC = nCredSDCCached; - nCredShadow = nCredShadowCached; + + nCredSPEC = nCredSPECCached; + nCredSpectre = nCredSpectreCached; return true; } @@ -880,42 +935,35 @@ class CWalletTx : public CMerkleTx fAvailableCreditCached = true; return nCredit; }; - - int64_t GetAvailableShadowCredit(bool fUseCache=true) const + + int64_t GetAvailableSpectreCredit(bool fUseCache=true) const { // Must wait until coinbase is safely deep enough in the chain before valuing it if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0) return 0; - - if (fUseCache && fAvailableShadowCreditCached) - return nAvailableShadowCreditCached; - + + // SPECTRE must be MIN_ANON_SPEND_DEPTH deep in the chain before spending is possible + if (GetDepthInMainChain() < MIN_ANON_SPEND_DEPTH) + return 0; + + if (fUseCache && fAvailableSpectreCreditCached) + return nAvailableSpectreCreditCached; + int64_t nCredit = 0; - + for (unsigned int i = 0; i < vout.size(); i++) { if (!IsSpent(i)) { const CTxOut &txout = vout[i]; - - if (!txout.IsAnonOutput()) - continue; - const CScript &s = txout.scriptPubKey; - - CKeyID ckidD = CPubKey(&s[2+1], 33).GetID(); - - if (pwallet->HaveKey(ckidD)) - { - nCredit += txout.nValue; - }; - + nCredit += pwallet->GetSpectreCredit(txout); if (!MoneyRange(nCredit)) - throw std::runtime_error("CWalletTx::GetAvailableShadowCredit() : value out of range"); + throw std::runtime_error("CWalletTx::GetAvailableSpectreCredit() : value out of range"); }; }; - - nAvailableShadowCreditCached = nCredit; - fAvailableShadowCreditCached = true; + + nAvailableSpectreCreditCached = nCredit; + fAvailableSpectreCreditCached = true; return nCredit; }; @@ -929,8 +977,8 @@ class CWalletTx : public CMerkleTx return nChangeCached; } - void GetAmounts(std::list >& listReceived, - std::list >& listSent, int64_t& nFee, std::string& strSentAccount) const; + void GetDestinationDetails(std::list& listReceived, + std::list& listSent, int64_t& nFee, std::string& strSentAccount) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee) const; @@ -975,11 +1023,11 @@ class CWalletTx : public CMerkleTx if (mapPrev.empty()) { - BOOST_FOREACH(const CMerkleTx& tx, vtxPrev) + for (const CMerkleTx& tx : vtxPrev) mapPrev[tx.GetHash()] = &tx; } - BOOST_FOREACH(const CTxIn& txin, ptx->vin) + for (const CTxIn& txin : ptx->vin) { if (!mapPrev.count(txin.prevout.hash)) return false; @@ -990,6 +1038,21 @@ class CWalletTx : public CMerkleTx return true; } + bool GetNarration(const unsigned int& nOut, std::string& sNarr) const + { + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::GetNarration() : nOut out of range"); + + char cbufNarrKey[256]; + snprintf(cbufNarrKey, sizeof(cbufNarrKey), "n_%u", nOut); + mapValue_t::const_iterator mi = mapValue.find(cbufNarrKey); + if (mi != mapValue.end() && !mi->second.empty()) { + sNarr = mi->second; + return true; + } + return false; + } + bool WriteToDisk(); int64_t GetTxTime() const; @@ -1093,6 +1156,27 @@ class CAccount }; +class CTxDestinationDetail +{ +public: + CTxDestinationDetail(CTxDestination address, std::vector vAddressElements, int64_t amount, std::optional vout, Currency currency, std::string narration) : + address(address), + vAddressElements(vAddressElements), + amount(amount), + vout(vout), + currency(currency), + narration(narration) + { + } + + CTxDestination address; + std::vector vAddressElements; + int64_t amount; + std::optional vout; + Currency currency; + std::string narration; +}; + /** Internal transfers. * Database key is acentry. diff --git a/src/walletdb.cpp b/src/walletdb.cpp index af115e9aa3..08b855daa0 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -1,15 +1,20 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT #include "walletdb.h" #include "wallet.h" +#include "util/fs.h" #include -#include using namespace std; -namespace fs = boost::filesystem; static uint64_t nAccountingEntryNumber = 0; extern bool fWalletUnlockStakingOnly; @@ -155,7 +160,7 @@ int64_t CWalletDB::GetAccountCreditDebit(const string& strAccount) ListAccountCreditDebit(strAccount, entries); int64_t nCreditDebit = 0; - BOOST_FOREACH (const CAccountingEntry& entry, entries) + for (const CAccountingEntry& entry : entries) nCreditDebit += entry.nCreditDebit; return nCreditDebit; @@ -225,8 +230,7 @@ CWalletDB::ReorderTransactions(CWallet* pwallet) } list acentries; ListAccountCreditDebit("", acentries); - BOOST_FOREACH(CAccountingEntry& entry, acentries) - { + for (CAccountingEntry& entry : acentries) { txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); } @@ -251,7 +255,7 @@ CWalletDB::ReorderTransactions(CWallet* pwallet) } else { int64_t nOrderPosOff = 0; - BOOST_FOREACH(const int64_t& nOffsetStart, nOrderPosOffsets) + for (const int64_t& nOffsetStart : nOrderPosOffsets) { if (nOrderPos >= nOffsetStart) ++nOrderPosOff; @@ -561,7 +565,7 @@ static bool IsKeyType(string strType) strType == "mkey" || strType == "ckey"); } -DBErrors CWalletDB::LoadWallet(CWallet* pwallet) +DBErrors CWalletDB::LoadWallet(CWallet* pwallet, int& oldWalletVersion, std::function funcProgress) { pwallet->vchDefaultKey = CPubKey(); CWalletScanState wss; @@ -586,8 +590,12 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return DB_CORRUPT; }; + uint32_t count = 0; while (true) { + if (funcProgress && count != 0 && count % 10000 == 0) funcProgress(count); + count++; + // Read next record CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); @@ -624,6 +632,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) LogPrintf("%s\n", strErr.c_str()); }; pcursor->close(); + if (funcProgress) funcProgress(count); } catch (...) { result = DB_CORRUPT; @@ -646,15 +655,20 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta) pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value' - BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade) + for (const uint256& hash : wss.vWalletUpgrade) WriteTx(hash, pwallet->mapWallet[hash]); // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) return DB_NEED_REWRITE; - if (wss.nFileVersion < CLIENT_VERSION) // Update + if (wss.nFileVersion < CLIENT_VERSION) { // Update + oldWalletVersion = wss.nFileVersion; WriteVersion(CLIENT_VERSION); + } + + // Add Development Contribution Address to address book + pwallet->mapAddressBook[CBitcoinAddress(Params().GetDevContributionAddress()).Get()] = "Alias Foundation"; if (wss.fAnyUnordered) result = ReorderTransactions(pwallet); @@ -779,7 +793,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) int64_t now = GetTime(); std::string newFilename = strprintf("wallet.%d.bak", now); - int result = dbenv.dbenv.dbrename(NULL, filename.c_str(), NULL, + int result = dbenv.dbenv.dbrename(nullptr, filename.c_str(), nullptr, newFilename.c_str(), DB_AUTO_COMMIT); if (result == 0) { @@ -802,7 +816,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) bool fSuccess = allOK; Db* pdbCopy = new Db(&dbenv.dbenv, 0); - int ret = pdbCopy->open(NULL, // Txn pointer + int ret = pdbCopy->open(nullptr, // Txn pointer filename.c_str(), // Filename "main", // Logical db name DB_BTREE, // Database type @@ -817,7 +831,7 @@ bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) CWalletScanState wss; DbTxn* ptxn = dbenv.TxnBegin(); - BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData) + for (CDBEnv::KeyValPair& row : salvagedData) { if (fOnlyKeys) { diff --git a/src/walletdb.h b/src/walletdb.h index 1066080970..d805792883 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -1,7 +1,14 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef BITCOIN_WALLETDB_H #define BITCOIN_WALLETDB_H @@ -151,12 +158,12 @@ class COwnedAnonOutput // stored in walletdb, key is keyimage // TODO: store nValue? public: - COwnedAnonOutput() {} + COwnedAnonOutput() : nValue(0), fSpent(false) + { + } - COwnedAnonOutput(COutPoint outpoint_, bool fSpent_) + COwnedAnonOutput(COutPoint outpoint_, bool fSpent_) : outpoint(outpoint_), nValue(0), fSpent(fSpent_) { - outpoint = outpoint_; - fSpent = fSpent_; } ec_point vchImage; @@ -197,7 +204,7 @@ class CWalletDB : public CDB DbTxn* ptxnid = activeTxn; // call TxnBegin first - Dbc* pcursor = NULL; + Dbc* pcursor = nullptr; int ret = pdb->cursor(ptxnid, &pcursor, 0); if (ret != 0) return NULL; @@ -523,7 +530,7 @@ class CWalletDB : public CDB void ListAccountCreditDebit(const std::string& strAccount, std::list& acentries); DBErrors ReorderTransactions(CWallet*); - DBErrors LoadWallet(CWallet* pwallet); + DBErrors LoadWallet(CWallet* pwallet, int& oltWalletVersion, std::function funcProgress); static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys); static bool Recover(CDBEnv& dbenv, std::string filename); }; diff --git a/src/win.pri b/src/win.pri new file mode 100644 index 0000000000..0e689346c5 --- /dev/null +++ b/src/win.pri @@ -0,0 +1,116 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# +# SPDX-License-Identifier: MIT + +#Include libs the windows way, for visual studio 64 bit compiler +#static for VS +#Compile Qt from source +#Refrences for MSVC +# http://amin-ahmadi.com/2016/09/22/how-to-build-qt-5-7-statically-using-msvc14-microsoft-visual-studio-2015/ +# https://stackoverflow.com/questions/32735678/how-to-build-qt-5-5-qtwebengine-on-windows-msvc-2015 +# configure -prefix "C:\D\QtSDK\5.10.1\msvc2017_64_static" -platform win64-msvc2017 -developer-build -opensource -confirm-license -nomake examples -nomake tests -opengl desktop -debug-and-release -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -sql-sqlite -sql-odbc -make libs +# nmake +# nmake install +CONFIG += static +QMAKE_LFLAGS += -static +QMAKE_CXXFLAGS += /MT +QMAKE_CFLAGS += -O2 -MT +QMAKE_CXXFLAGS += -O2 -MT + +DEFINES -= NDEBUG +DEFINES += _WINSOCKAPI_ + + +CONFIG(release, debug|release) { + message( "release" ) + LIBSPATH = $$PWD/../packages64bit/lib +} +CONFIG(debug, debug|release) { + message( "debug" ) + LIBSPATH = $$PWD/../packages64bit/debug/lib +} + + +HEADERS += $$PWD/win/unistd.h +INCLUDEPATH += $$PWD/win + +#Command to install dependencies (Static) +#vcpkg.exe install boost:x64-windows-static berkeleydb:x64-windows-static leveldb:x64-windows-static libevent:x64-windows-static lua:x64-windows-static openssl:x64-windows-static zlib:x64-windows-static +#Command to install dependencies (Dynamic) +#vcpkg.exe install boost:x64-windows berkeleydb:x64-windows leveldb:x64-windows libevent:x64-windows lua:x64-windows openssl:x64-windows zlib:x64-windows +DEFINES += BOOST_ASIO_ENABLE_OLD_SERVICES BOOST_SPIRIT_THREADSAFE BOOST_THREAD_USE_LIB +#DEFINES += BOOST_DISABLE_CURRENT_FUNCTION + + + +INCLUDEPATH += $$PWD/../packages64bit/include +DEPENDPATH += $$PWD/../packages64bit/include + +LIBS += -L$${LIBSPATH}/ -llua +PRE_TARGETDEPS += $${LIBSPATH}/lua.lib +LIBS += -L$${LIBSPATH} -lboost_chrono-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_chrono-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lboost_filesystem-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_filesystem-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lboost_program_options-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_program_options-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lboost_system-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_system-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lboost_thread-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_thread-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lboost_unit_test_framework-vc140-mt +PRE_TARGETDEPS += $${LIBSPATH}/boost_unit_test_framework-vc140-mt.lib +LIBS += -L$${LIBSPATH}/ -lzlib +PRE_TARGETDEPS += $${LIBSPATH}/zlib.lib +LIBS += -L$${LIBSPATH}/ -llibcryptoMD +PRE_TARGETDEPS += $${LIBSPATH}/libcryptoMD.lib +LIBS += -L$${LIBSPATH}/ -llibsslMD +PRE_TARGETDEPS += $${LIBSPATH}/libsslMD.lib +LIBS += -L$${LIBSPATH}/ -levent +PRE_TARGETDEPS += $${LIBSPATH}/event.lib +LIBS += -L$${LIBSPATH}/ -levent_core +PRE_TARGETDEPS += $${LIBSPATH}/event_core.lib +LIBS += -L$${LIBSPATH}/ -levent_extra +PRE_TARGETDEPS += $${LIBSPATH}/event_extra.lib +LIBS += -L$${LIBSPATH}/ -lWS2_32 +PRE_TARGETDEPS += $${LIBSPATH}/WS2_32.lib +LIBS += -L$${LIBSPATH}/ -lAdvAPI32 +PRE_TARGETDEPS += $${LIBSPATH}/AdvAPI32.lib +LIBS += -L$${LIBSPATH}/ -lshell32 +PRE_TARGETDEPS += $${LIBSPATH}/shell32.lib +LIBS += -L$${LIBSPATH}/ -lUser32 +PRE_TARGETDEPS += $${LIBSPATH}/User32.lib +LIBS += -L$${LIBSPATH}/ -lCrypt32 +PRE_TARGETDEPS += $${LIBSPATH}/Crypt32.lib +#ShLwApi +LIBS += -L$${LIBSPATH}/ -lShLwApi +PRE_TARGETDEPS += $${LIBSPATH}/ShLwApi.lib + +#LevelDB from VCPKG +LIBS += -L$${LIBSPATH}/ -llibleveldb +PRE_TARGETDEPS += $${LIBSPATH}/libleveldb.lib +#BerklyDB4.8 from our project repo (VCPKG version is not supported) +LIBS += -L$${LIBSPATH}/ -llibdb48 +PRE_TARGETDEPS += $${LIBSPATH}/libdb48.lib +#libdb_stl48.lib (We need both libdb and libdbstl (Standered library) +LIBS += -L$${LIBSPATH}/ -llibdb_stl48 +PRE_TARGETDEPS += $${LIBSPATH}/libdb_stl48.lib + +#LIBS += -L$$PWD/../tor/ -ltorlib +#PRE_TARGETDEPS += $$PWD/../tor/torlib.lib +#LIBS += -L$$PWD/../leveldb/ -lleveldblib +#PRE_TARGETDEPS += $$PWD/../leveldb/leveldblib.lib +#LIBS += -L$$PWD/../db4.8/ -lberkeleydblib +#PRE_TARGETDEPS += $$PWD/../db4.8/berkeleydblib.lib + +QMAKE_CFLAGS_WARN_ON -= -W3 +QMAKE_CFLAGS_WARN_ON += -W2 + +QMAKE_CXXFLAGS_WARN_ON -= -W3 +QMAKE_CXXFLAGS_WARN_ON += -W2 + +QMAKE_CXXFLAGS += -O2 -D_FORTIFY_SOURCE=1 +QMAKE_CFLAGS += /std:c++17 +QMAKE_CXXFLAGS += /std:c++17 diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt new file mode 100644 index 0000000000..7087e01deb --- /dev/null +++ b/src/win/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(aliaswallet_lib + PUBLIC + "${CMAKE_CURRENT_LIST_DIR}/unistd.h" +) \ No newline at end of file diff --git a/src/win/README.txt b/src/win/README.txt new file mode 100644 index 0000000000..0118404c7f --- /dev/null +++ b/src/win/README.txt @@ -0,0 +1,6 @@ +SPDX-FileCopyrightText: © 2025 ALIAS Developers +SPDX-FileCopyrightText: © 2020 Alias Developers +SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +SPDX-License-Identifier: MIT + +Keep this file here, only include on Windows builds, if you include the directory in will cause the app to not compile because of BOOST THREADS, so just include this on Windows and keep it in it's own isolated folder, DO NOT MIX IT WITH OTHER FILES BEFORE TRYING TO COMPILE ON ALL PLATFORMS diff --git a/src/win/torrc-defaults b/src/win/torrc-defaults new file mode 100644 index 0000000000..fb0bc0d4ab --- /dev/null +++ b/src/win/torrc-defaults @@ -0,0 +1,27 @@ +# torrc-defaults for Spectrecoin +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# DO NOT EDIT THIS FILE +# +# This file is distributed with Spectrecoin within the tor folder and SHOULD NOT be modified +# (it may be overwritten during the next Spectrecoin update). +# To customize your Tor configuration, shut down Spectrecoin and edit the torrc file. +# +# If non-zero, try to write to disk less frequently than we would otherwise. +AvoidDiskWrites 1 + +# If non-zero, try to use built-in (static) crypto hardware acceleration when available. +HardwareAccel 1 + +## fteproxy configuration +ClientTransportPlugin fte exec PluggableTransports\fteproxy.exe --managed + +## obfs4proxy configuration +ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec PluggableTransports\obfs4proxy.exe + +## meek configuration +#ClientTransportPlugin meek exec PluggableTransports\terminateprocess-buffer.exe PluggableTransports\meek-client-torbrowser.exe -- PluggableTransports\meek-client.exe \ No newline at end of file diff --git a/src/win/torrc-defaults_obfs4 b/src/win/torrc-defaults_obfs4 new file mode 100644 index 0000000000..860f7497ef --- /dev/null +++ b/src/win/torrc-defaults_obfs4 @@ -0,0 +1,57 @@ +# torrc-defaults for Spectrecoin +# +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +# SPDX-License-Identifier: MIT +# +# DO NOT EDIT THIS FILE +# +# This file is distributed with Spectrecoin within the tor folder and SHOULD NOT be modified +# (it may be overwritten during the next Spectrecoin update). +# To customize your Tor configuration, shut down Spectrecoin and edit the torrc file. +# +# If non-zero, try to write to disk less frequently than we would otherwise. +AvoidDiskWrites 1 + +# If non-zero, try to use built-in (static) crypto hardware acceleration when available. +HardwareAccel 1 + +## fteproxy configuration +ClientTransportPlugin fte exec PluggableTransports\fteproxy.exe --managed + +## obfs4proxy configuration +ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec PluggableTransports\obfs4proxy.exe + +## meek configuration +#ClientTransportPlugin meek exec PluggableTransports\terminateprocess-buffer.exe PluggableTransports\meek-client-torbrowser.exe -- PluggableTransports\meek-client.exe + +## preconfigured OBFS4 bridges +Bridge obfs4 154.35.22.9:12166 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 154.35.22.9:443 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1 +Bridge obfs4 154.35.22.13:443 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 +Bridge obfs4 192.99.11.54:443 7B126FAB960E5AC6A629C729434FF84FB5074EC2 cert=VW5f8+IBUWpPFxF+rsiVy2wXkyTQG7vEd+rHeN2jV5LIDNu8wMNEOqZXPwHdwMVEBdqXEw iat-mode=0 +Bridge obfs4 154.35.22.12:80 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 85.17.30.79:443 FC259A04A328A07FED1413E9FC6526530D9FD87A cert=RutxZlu8BtyP+y0NX7bAVD41+J/qXNhHUrKjFkRSdiBAhIHIQLhKQ2HxESAKZprn/lR3KA iat-mode=0 +Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 216.252.162.21:46089 0DB8799466902192B6C7576D58D4F7F714EC87C1 cert=XPUwcQPxEXExHfJYX58gZXN7mYpos7VNAHbkgERNFg+FCVNzuYo1Wp+uMscl3aR9hO2DRQ iat-mode=0 +Bridge obfs4 109.105.109.147:13764 BBB28DF0F201E706BE564EFE690FE9577DD8386D cert=KfMQN/tNMFdda61hMgpiMI7pbwU1T+wxjTulYnfw+4sgvG0zSH7N7fwT10BI8MUdAD7iJA iat-mode=2 +Bridge obfs4 154.35.22.10:80 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.11:443 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 83.212.101.3:50002 A09D536DD1752D542E1FBB3C9CE4449D51298239 cert=lPRQ/MXdD1t5SRZ9MquYQNT9m5DV757jtdXdlePmRCudUU9CFUOX1Tm7/meFSyPOsud7Cw iat-mode=0 +Bridge obfs4 109.105.109.165:10527 8DFCD8FB3285E855F5A55EDDA35696C743ABFC4E cert=Bvg/itxeL4TWKLP6N1MaQzSOC6tcRIBv6q57DYAZc3b2AzuM+/TfB7mqTFEfXILCjEwzVA iat-mode=1 +Bridge obfs4 154.35.22.11:80 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.12:4304 00DC6C4FA49A65BD1472993CF6730D54F11E0DBB cert=N86E9hKXXXVz6G7w2z8wFfhIDztDAzZ/3poxVePHEYjbKDWzjkRDccFMAnhK75fc65pYSg iat-mode=0 +Bridge obfs4 154.35.22.11:16488 A832D176ECD5C7C6B58825AE22FC4C90FA249637 cert=YPbQqXPiqTUBfjGFLpm9JYEFTBvnzEJDKJxXG5Sxzrr/v2qrhGU4Jls9lHjLAhqpXaEfZw iat-mode=0 +Bridge obfs4 154.35.22.9:80 C73ADBAC8ADFDBF0FC0F3F4E8091C0107D093716 cert=gEGKc5WN/bSjFa6UkG9hOcft1tuK+cV8hbZ0H6cqXiMPLqSbCh2Q3PHe5OOr6oMVORhoJA iat-mode=0 +Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 +Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 +Bridge obfs4 154.35.22.10:443 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 154.35.22.13:16815 FE7840FE1E21FE0A0639ED176EDA00A3ECA1E34D cert=fKnzxr+m+jWXXQGCaXe4f2gGoPXMzbL+bTBbXMYXuK0tMotd+nXyS33y2mONZWU29l81CA iat-mode=0 +Bridge obfs4 [2001:470:b381:bfff:216:3eff:fe23:d6c3]:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +Bridge obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWODcgqIdPJ+rRupg4GGvVGfh25FWaIXZkit206OSngsp7GAIiGIXOJJROMxEqFKJg iat-mode=1 +Bridge obfs4 154.35.22.10:15937 8FB9F4319E89E5C6223052AA525A192AFBC85D55 cert=GGGS1TX4R81m3r0HBl79wKy1OtPPNR2CZUIrHjkRg65Vc2VR8fOyo64f9kmT1UAFG7j0HQ iat-mode=0 +Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 +UseBridges 1 \ No newline at end of file diff --git a/src/win/unistd.h b/src/win/unistd.h new file mode 100644 index 0000000000..5a0597b290 --- /dev/null +++ b/src/win/unistd.h @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2010 Satoshi Nakamoto +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#ifdef _MSC_VER +#ifndef UNISTD_H +#define UNISTD_H + +/* This is intended as a drop-in replacement for unistd.h on Windows. + * Please add functionality as neeeded. + * https://stackoverflow.com/a/826027/1202830 + */ + +#include +#include +//#include /* getopt at: https://gist.github.com/ashelly/7776712 */ +#include /* for getpid() and the exec..() family */ +#include /* for _getcwd() and _chdir() */ + +#define srandom srand +#define random rand + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +//#define X_OK 1 /* execute permission - unsupported in windows*/ +#define F_OK 0 /* Test for existence. */ + +#define access _access +#define dup2 _dup2 +#define execve _execve +#define ftruncate _chsize +#define unlink _unlink +#define fileno _fileno +#define getcwd _getcwd +#define chdir _chdir +#define isatty _isatty +#define lseek _lseek +/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ + +#ifdef _WIN64 +#define ssize_t __int64 +#else +#define ssize_t long +#endif + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +/* should be in some equivalent to */ +//typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +#endif // UNISTD_H +#endif diff --git a/src/wordlists/CMakeLists.txt b/src/wordlists/CMakeLists.txt new file mode 100644 index 0000000000..cd37a0c5d1 --- /dev/null +++ b/src/wordlists/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(aliaswallet_lib + PUBLIC + "${CMAKE_CURRENT_LIST_DIR}/chinese_simplified.h" + "${CMAKE_CURRENT_LIST_DIR}/chinese_traditional.h" + "${CMAKE_CURRENT_LIST_DIR}/english.h" + "${CMAKE_CURRENT_LIST_DIR}/french.h" + "${CMAKE_CURRENT_LIST_DIR}/japanese.h" + "${CMAKE_CURRENT_LIST_DIR}/spanish.h" +) \ No newline at end of file diff --git a/src/wordlists/chinese_simplified.h b/src/wordlists/chinese_simplified.h index 5fb9531522..ebcb8d461c 100644 --- a/src/wordlists/chinese_simplified.h +++ b/src/wordlists/chinese_simplified.h @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + unsigned char chinese_simplified_txt[] = { 0xe7, 0x9a, 0x84, 0x0a, 0xe4, 0xb8, 0x80, 0x0a, 0xe6, 0x98, 0xaf, 0x0a, 0xe5, 0x9c, 0xa8, 0x0a, 0xe4, 0xb8, 0x8d, 0x0a, 0xe4, 0xba, 0x86, 0x0a, diff --git a/src/wordlists/chinese_traditional.h b/src/wordlists/chinese_traditional.h index 468fb3ebb2..1ec95a39bf 100644 --- a/src/wordlists/chinese_traditional.h +++ b/src/wordlists/chinese_traditional.h @@ -1,686 +1,289 @@ -unsigned char chinese_traditional_txt[] = { - 0xe7, 0x9a, 0x84, 0x0a, 0xe4, 0xb8, 0x80, 0x0a, 0xe6, 0x98, 0xaf, 0x0a, - 0xe5, 0x9c, 0xa8, 0x0a, 0xe4, 0xb8, 0x8d, 0x0a, 0xe4, 0xba, 0x86, 0x0a, - 0xe6, 0x9c, 0x89, 0x0a, 0xe5, 0x92, 0x8c, 0x0a, 0xe4, 0xba, 0xba, 0x0a, - 0xe9, 0x80, 0x99, 0x0a, 0xe4, 0xb8, 0xad, 0x0a, 0xe5, 0xa4, 0xa7, 0x0a, - 0xe7, 0x82, 0xba, 0x0a, 0xe4, 0xb8, 0x8a, 0x0a, 0xe5, 0x80, 0x8b, 0x0a, - 0xe5, 0x9c, 0x8b, 0x0a, 0xe6, 0x88, 0x91, 0x0a, 0xe4, 0xbb, 0xa5, 0x0a, - 0xe8, 0xa6, 0x81, 0x0a, 0xe4, 0xbb, 0x96, 0x0a, 0xe6, 0x99, 0x82, 0x0a, - 0xe4, 0xbe, 0x86, 0x0a, 0xe7, 0x94, 0xa8, 0x0a, 0xe5, 0x80, 0x91, 0x0a, - 0xe7, 0x94, 0x9f, 0x0a, 0xe5, 0x88, 0xb0, 0x0a, 0xe4, 0xbd, 0x9c, 0x0a, - 0xe5, 0x9c, 0xb0, 0x0a, 0xe6, 0x96, 0xbc, 0x0a, 0xe5, 0x87, 0xba, 0x0a, - 0xe5, 0xb0, 0xb1, 0x0a, 0xe5, 0x88, 0x86, 0x0a, 0xe5, 0xb0, 0x8d, 0x0a, - 0xe6, 0x88, 0x90, 0x0a, 0xe6, 0x9c, 0x83, 0x0a, 0xe5, 0x8f, 0xaf, 0x0a, - 0xe4, 0xb8, 0xbb, 0x0a, 0xe7, 0x99, 0xbc, 0x0a, 0xe5, 0xb9, 0xb4, 0x0a, - 0xe5, 0x8b, 0x95, 0x0a, 0xe5, 0x90, 0x8c, 0x0a, 0xe5, 0xb7, 0xa5, 0x0a, - 0xe4, 0xb9, 0x9f, 0x0a, 0xe8, 0x83, 0xbd, 0x0a, 0xe4, 0xb8, 0x8b, 0x0a, - 0xe9, 0x81, 0x8e, 0x0a, 0xe5, 0xad, 0x90, 0x0a, 0xe8, 0xaa, 0xaa, 0x0a, - 0xe7, 0x94, 0xa2, 0x0a, 0xe7, 0xa8, 0xae, 0x0a, 0xe9, 0x9d, 0xa2, 0x0a, - 0xe8, 0x80, 0x8c, 0x0a, 0xe6, 0x96, 0xb9, 0x0a, 0xe5, 0xbe, 0x8c, 0x0a, - 0xe5, 0xa4, 0x9a, 0x0a, 0xe5, 0xae, 0x9a, 0x0a, 0xe8, 0xa1, 0x8c, 0x0a, - 0xe5, 0xad, 0xb8, 0x0a, 0xe6, 0xb3, 0x95, 0x0a, 0xe6, 0x89, 0x80, 0x0a, - 0xe6, 0xb0, 0x91, 0x0a, 0xe5, 0xbe, 0x97, 0x0a, 0xe7, 0xb6, 0x93, 0x0a, - 0xe5, 0x8d, 0x81, 0x0a, 0xe4, 0xb8, 0x89, 0x0a, 0xe4, 0xb9, 0x8b, 0x0a, - 0xe9, 0x80, 0xb2, 0x0a, 0xe8, 0x91, 0x97, 0x0a, 0xe7, 0xad, 0x89, 0x0a, - 0xe9, 0x83, 0xa8, 0x0a, 0xe5, 0xba, 0xa6, 0x0a, 0xe5, 0xae, 0xb6, 0x0a, - 0xe9, 0x9b, 0xbb, 0x0a, 0xe5, 0x8a, 0x9b, 0x0a, 0xe8, 0xa3, 0xa1, 0x0a, - 0xe5, 0xa6, 0x82, 0x0a, 0xe6, 0xb0, 0xb4, 0x0a, 0xe5, 0x8c, 0x96, 0x0a, - 0xe9, 0xab, 0x98, 0x0a, 0xe8, 0x87, 0xaa, 0x0a, 0xe4, 0xba, 0x8c, 0x0a, - 0xe7, 0x90, 0x86, 0x0a, 0xe8, 0xb5, 0xb7, 0x0a, 0xe5, 0xb0, 0x8f, 0x0a, - 0xe7, 0x89, 0xa9, 0x0a, 0xe7, 0x8f, 0xbe, 0x0a, 0xe5, 0xaf, 0xa6, 0x0a, - 0xe5, 0x8a, 0xa0, 0x0a, 0xe9, 0x87, 0x8f, 0x0a, 0xe9, 0x83, 0xbd, 0x0a, - 0xe5, 0x85, 0xa9, 0x0a, 0xe9, 0xab, 0x94, 0x0a, 0xe5, 0x88, 0xb6, 0x0a, - 0xe6, 0xa9, 0x9f, 0x0a, 0xe7, 0x95, 0xb6, 0x0a, 0xe4, 0xbd, 0xbf, 0x0a, - 0xe9, 0xbb, 0x9e, 0x0a, 0xe5, 0xbe, 0x9e, 0x0a, 0xe6, 0xa5, 0xad, 0x0a, - 0xe6, 0x9c, 0xac, 0x0a, 0xe5, 0x8e, 0xbb, 0x0a, 0xe6, 0x8a, 0x8a, 0x0a, - 0xe6, 0x80, 0xa7, 0x0a, 0xe5, 0xa5, 0xbd, 0x0a, 0xe6, 0x87, 0x89, 0x0a, - 0xe9, 0x96, 0x8b, 0x0a, 0xe5, 0xae, 0x83, 0x0a, 0xe5, 0x90, 0x88, 0x0a, - 0xe9, 0x82, 0x84, 0x0a, 0xe5, 0x9b, 0xa0, 0x0a, 0xe7, 0x94, 0xb1, 0x0a, - 0xe5, 0x85, 0xb6, 0x0a, 0xe4, 0xba, 0x9b, 0x0a, 0xe7, 0x84, 0xb6, 0x0a, - 0xe5, 0x89, 0x8d, 0x0a, 0xe5, 0xa4, 0x96, 0x0a, 0xe5, 0xa4, 0xa9, 0x0a, - 0xe6, 0x94, 0xbf, 0x0a, 0xe5, 0x9b, 0x9b, 0x0a, 0xe6, 0x97, 0xa5, 0x0a, - 0xe9, 0x82, 0xa3, 0x0a, 0xe7, 0xa4, 0xbe, 0x0a, 0xe7, 0xbe, 0xa9, 0x0a, - 0xe4, 0xba, 0x8b, 0x0a, 0xe5, 0xb9, 0xb3, 0x0a, 0xe5, 0xbd, 0xa2, 0x0a, - 0xe7, 0x9b, 0xb8, 0x0a, 0xe5, 0x85, 0xa8, 0x0a, 0xe8, 0xa1, 0xa8, 0x0a, - 0xe9, 0x96, 0x93, 0x0a, 0xe6, 0xa8, 0xa3, 0x0a, 0xe8, 0x88, 0x87, 0x0a, - 0xe9, 0x97, 0x9c, 0x0a, 0xe5, 0x90, 0x84, 0x0a, 0xe9, 0x87, 0x8d, 0x0a, - 0xe6, 0x96, 0xb0, 0x0a, 0xe7, 0xb7, 0x9a, 0x0a, 0xe5, 0x85, 0xa7, 0x0a, - 0xe6, 0x95, 0xb8, 0x0a, 0xe6, 0xad, 0xa3, 0x0a, 0xe5, 0xbf, 0x83, 0x0a, - 0xe5, 0x8f, 0x8d, 0x0a, 0xe4, 0xbd, 0xa0, 0x0a, 0xe6, 0x98, 0x8e, 0x0a, - 0xe7, 0x9c, 0x8b, 0x0a, 0xe5, 0x8e, 0x9f, 0x0a, 0xe5, 0x8f, 0x88, 0x0a, - 0xe9, 0xba, 0xbc, 0x0a, 0xe5, 0x88, 0xa9, 0x0a, 0xe6, 0xaf, 0x94, 0x0a, - 0xe6, 0x88, 0x96, 0x0a, 0xe4, 0xbd, 0x86, 0x0a, 0xe8, 0xb3, 0xaa, 0x0a, - 0xe6, 0xb0, 0xa3, 0x0a, 0xe7, 0xac, 0xac, 0x0a, 0xe5, 0x90, 0x91, 0x0a, - 0xe9, 0x81, 0x93, 0x0a, 0xe5, 0x91, 0xbd, 0x0a, 0xe6, 0xad, 0xa4, 0x0a, - 0xe8, 0xae, 0x8a, 0x0a, 0xe6, 0xa2, 0x9d, 0x0a, 0xe5, 0x8f, 0xaa, 0x0a, - 0xe6, 0xb2, 0x92, 0x0a, 0xe7, 0xb5, 0x90, 0x0a, 0xe8, 0xa7, 0xa3, 0x0a, - 0xe5, 0x95, 0x8f, 0x0a, 0xe6, 0x84, 0x8f, 0x0a, 0xe5, 0xbb, 0xba, 0x0a, - 0xe6, 0x9c, 0x88, 0x0a, 0xe5, 0x85, 0xac, 0x0a, 0xe7, 0x84, 0xa1, 0x0a, - 0xe7, 0xb3, 0xbb, 0x0a, 0xe8, 0xbb, 0x8d, 0x0a, 0xe5, 0xbe, 0x88, 0x0a, - 0xe6, 0x83, 0x85, 0x0a, 0xe8, 0x80, 0x85, 0x0a, 0xe6, 0x9c, 0x80, 0x0a, - 0xe7, 0xab, 0x8b, 0x0a, 0xe4, 0xbb, 0xa3, 0x0a, 0xe6, 0x83, 0xb3, 0x0a, - 0xe5, 0xb7, 0xb2, 0x0a, 0xe9, 0x80, 0x9a, 0x0a, 0xe4, 0xb8, 0xa6, 0x0a, - 0xe6, 0x8f, 0x90, 0x0a, 0xe7, 0x9b, 0xb4, 0x0a, 0xe9, 0xa1, 0x8c, 0x0a, - 0xe9, 0xbb, 0xa8, 0x0a, 0xe7, 0xa8, 0x8b, 0x0a, 0xe5, 0xb1, 0x95, 0x0a, - 0xe4, 0xba, 0x94, 0x0a, 0xe6, 0x9e, 0x9c, 0x0a, 0xe6, 0x96, 0x99, 0x0a, - 0xe8, 0xb1, 0xa1, 0x0a, 0xe5, 0x93, 0xa1, 0x0a, 0xe9, 0x9d, 0xa9, 0x0a, - 0xe4, 0xbd, 0x8d, 0x0a, 0xe5, 0x85, 0xa5, 0x0a, 0xe5, 0xb8, 0xb8, 0x0a, - 0xe6, 0x96, 0x87, 0x0a, 0xe7, 0xb8, 0xbd, 0x0a, 0xe6, 0xac, 0xa1, 0x0a, - 0xe5, 0x93, 0x81, 0x0a, 0xe5, 0xbc, 0x8f, 0x0a, 0xe6, 0xb4, 0xbb, 0x0a, - 0xe8, 0xa8, 0xad, 0x0a, 0xe5, 0x8f, 0x8a, 0x0a, 0xe7, 0xae, 0xa1, 0x0a, - 0xe7, 0x89, 0xb9, 0x0a, 0xe4, 0xbb, 0xb6, 0x0a, 0xe9, 0x95, 0xb7, 0x0a, - 0xe6, 0xb1, 0x82, 0x0a, 0xe8, 0x80, 0x81, 0x0a, 0xe9, 0xa0, 0xad, 0x0a, - 0xe5, 0x9f, 0xba, 0x0a, 0xe8, 0xb3, 0x87, 0x0a, 0xe9, 0x82, 0x8a, 0x0a, - 0xe6, 0xb5, 0x81, 0x0a, 0xe8, 0xb7, 0xaf, 0x0a, 0xe7, 0xb4, 0x9a, 0x0a, - 0xe5, 0xb0, 0x91, 0x0a, 0xe5, 0x9c, 0x96, 0x0a, 0xe5, 0xb1, 0xb1, 0x0a, - 0xe7, 0xb5, 0xb1, 0x0a, 0xe6, 0x8e, 0xa5, 0x0a, 0xe7, 0x9f, 0xa5, 0x0a, - 0xe8, 0xbc, 0x83, 0x0a, 0xe5, 0xb0, 0x87, 0x0a, 0xe7, 0xb5, 0x84, 0x0a, - 0xe8, 0xa6, 0x8b, 0x0a, 0xe8, 0xa8, 0x88, 0x0a, 0xe5, 0x88, 0xa5, 0x0a, - 0xe5, 0xa5, 0xb9, 0x0a, 0xe6, 0x89, 0x8b, 0x0a, 0xe8, 0xa7, 0x92, 0x0a, - 0xe6, 0x9c, 0x9f, 0x0a, 0xe6, 0xa0, 0xb9, 0x0a, 0xe8, 0xab, 0x96, 0x0a, - 0xe9, 0x81, 0x8b, 0x0a, 0xe8, 0xbe, 0xb2, 0x0a, 0xe6, 0x8c, 0x87, 0x0a, - 0xe5, 0xb9, 0xbe, 0x0a, 0xe4, 0xb9, 0x9d, 0x0a, 0xe5, 0x8d, 0x80, 0x0a, - 0xe5, 0xbc, 0xb7, 0x0a, 0xe6, 0x94, 0xbe, 0x0a, 0xe6, 0xb1, 0xba, 0x0a, - 0xe8, 0xa5, 0xbf, 0x0a, 0xe8, 0xa2, 0xab, 0x0a, 0xe5, 0xb9, 0xb9, 0x0a, - 0xe5, 0x81, 0x9a, 0x0a, 0xe5, 0xbf, 0x85, 0x0a, 0xe6, 0x88, 0xb0, 0x0a, - 0xe5, 0x85, 0x88, 0x0a, 0xe5, 0x9b, 0x9e, 0x0a, 0xe5, 0x89, 0x87, 0x0a, - 0xe4, 0xbb, 0xbb, 0x0a, 0xe5, 0x8f, 0x96, 0x0a, 0xe6, 0x93, 0x9a, 0x0a, - 0xe8, 0x99, 0x95, 0x0a, 0xe9, 0x9a, 0x8a, 0x0a, 0xe5, 0x8d, 0x97, 0x0a, - 0xe7, 0xb5, 0xa6, 0x0a, 0xe8, 0x89, 0xb2, 0x0a, 0xe5, 0x85, 0x89, 0x0a, - 0xe9, 0x96, 0x80, 0x0a, 0xe5, 0x8d, 0xb3, 0x0a, 0xe4, 0xbf, 0x9d, 0x0a, - 0xe6, 0xb2, 0xbb, 0x0a, 0xe5, 0x8c, 0x97, 0x0a, 0xe9, 0x80, 0xa0, 0x0a, - 0xe7, 0x99, 0xbe, 0x0a, 0xe8, 0xa6, 0x8f, 0x0a, 0xe7, 0x86, 0xb1, 0x0a, - 0xe9, 0xa0, 0x98, 0x0a, 0xe4, 0xb8, 0x83, 0x0a, 0xe6, 0xb5, 0xb7, 0x0a, - 0xe5, 0x8f, 0xa3, 0x0a, 0xe6, 0x9d, 0xb1, 0x0a, 0xe5, 0xb0, 0x8e, 0x0a, - 0xe5, 0x99, 0xa8, 0x0a, 0xe5, 0xa3, 0x93, 0x0a, 0xe5, 0xbf, 0x97, 0x0a, - 0xe4, 0xb8, 0x96, 0x0a, 0xe9, 0x87, 0x91, 0x0a, 0xe5, 0xa2, 0x9e, 0x0a, - 0xe7, 0x88, 0xad, 0x0a, 0xe6, 0xbf, 0x9f, 0x0a, 0xe9, 0x9a, 0x8e, 0x0a, - 0xe6, 0xb2, 0xb9, 0x0a, 0xe6, 0x80, 0x9d, 0x0a, 0xe8, 0xa1, 0x93, 0x0a, - 0xe6, 0xa5, 0xb5, 0x0a, 0xe4, 0xba, 0xa4, 0x0a, 0xe5, 0x8f, 0x97, 0x0a, - 0xe8, 0x81, 0xaf, 0x0a, 0xe4, 0xbb, 0x80, 0x0a, 0xe8, 0xaa, 0x8d, 0x0a, - 0xe5, 0x85, 0xad, 0x0a, 0xe5, 0x85, 0xb1, 0x0a, 0xe6, 0xac, 0x8a, 0x0a, - 0xe6, 0x94, 0xb6, 0x0a, 0xe8, 0xad, 0x89, 0x0a, 0xe6, 0x94, 0xb9, 0x0a, - 0xe6, 0xb8, 0x85, 0x0a, 0xe7, 0xbe, 0x8e, 0x0a, 0xe5, 0x86, 0x8d, 0x0a, - 0xe6, 0x8e, 0xa1, 0x0a, 0xe8, 0xbd, 0x89, 0x0a, 0xe6, 0x9b, 0xb4, 0x0a, - 0xe5, 0x96, 0xae, 0x0a, 0xe9, 0xa2, 0xa8, 0x0a, 0xe5, 0x88, 0x87, 0x0a, - 0xe6, 0x89, 0x93, 0x0a, 0xe7, 0x99, 0xbd, 0x0a, 0xe6, 0x95, 0x99, 0x0a, - 0xe9, 0x80, 0x9f, 0x0a, 0xe8, 0x8a, 0xb1, 0x0a, 0xe5, 0xb8, 0xb6, 0x0a, - 0xe5, 0xae, 0x89, 0x0a, 0xe5, 0xa0, 0xb4, 0x0a, 0xe8, 0xba, 0xab, 0x0a, - 0xe8, 0xbb, 0x8a, 0x0a, 0xe4, 0xbe, 0x8b, 0x0a, 0xe7, 0x9c, 0x9f, 0x0a, - 0xe5, 0x8b, 0x99, 0x0a, 0xe5, 0x85, 0xb7, 0x0a, 0xe8, 0x90, 0xac, 0x0a, - 0xe6, 0xaf, 0x8f, 0x0a, 0xe7, 0x9b, 0xae, 0x0a, 0xe8, 0x87, 0xb3, 0x0a, - 0xe9, 0x81, 0x94, 0x0a, 0xe8, 0xb5, 0xb0, 0x0a, 0xe7, 0xa9, 0x8d, 0x0a, - 0xe7, 0xa4, 0xba, 0x0a, 0xe8, 0xad, 0xb0, 0x0a, 0xe8, 0x81, 0xb2, 0x0a, - 0xe5, 0xa0, 0xb1, 0x0a, 0xe9, 0xac, 0xa5, 0x0a, 0xe5, 0xae, 0x8c, 0x0a, - 0xe9, 0xa1, 0x9e, 0x0a, 0xe5, 0x85, 0xab, 0x0a, 0xe9, 0x9b, 0xa2, 0x0a, - 0xe8, 0x8f, 0xaf, 0x0a, 0xe5, 0x90, 0x8d, 0x0a, 0xe7, 0xa2, 0xba, 0x0a, - 0xe6, 0x89, 0x8d, 0x0a, 0xe7, 0xa7, 0x91, 0x0a, 0xe5, 0xbc, 0xb5, 0x0a, - 0xe4, 0xbf, 0xa1, 0x0a, 0xe9, 0xa6, 0xac, 0x0a, 0xe7, 0xaf, 0x80, 0x0a, - 0xe8, 0xa9, 0xb1, 0x0a, 0xe7, 0xb1, 0xb3, 0x0a, 0xe6, 0x95, 0xb4, 0x0a, - 0xe7, 0xa9, 0xba, 0x0a, 0xe5, 0x85, 0x83, 0x0a, 0xe6, 0xb3, 0x81, 0x0a, - 0xe4, 0xbb, 0x8a, 0x0a, 0xe9, 0x9b, 0x86, 0x0a, 0xe6, 0xba, 0xab, 0x0a, - 0xe5, 0x82, 0xb3, 0x0a, 0xe5, 0x9c, 0x9f, 0x0a, 0xe8, 0xa8, 0xb1, 0x0a, - 0xe6, 0xad, 0xa5, 0x0a, 0xe7, 0xbe, 0xa4, 0x0a, 0xe5, 0xbb, 0xa3, 0x0a, - 0xe7, 0x9f, 0xb3, 0x0a, 0xe8, 0xa8, 0x98, 0x0a, 0xe9, 0x9c, 0x80, 0x0a, - 0xe6, 0xae, 0xb5, 0x0a, 0xe7, 0xa0, 0x94, 0x0a, 0xe7, 0x95, 0x8c, 0x0a, - 0xe6, 0x8b, 0x89, 0x0a, 0xe6, 0x9e, 0x97, 0x0a, 0xe5, 0xbe, 0x8b, 0x0a, - 0xe5, 0x8f, 0xab, 0x0a, 0xe4, 0xb8, 0x94, 0x0a, 0xe7, 0xa9, 0xb6, 0x0a, - 0xe8, 0xa7, 0x80, 0x0a, 0xe8, 0xb6, 0x8a, 0x0a, 0xe7, 0xb9, 0x94, 0x0a, - 0xe8, 0xa3, 0x9d, 0x0a, 0xe5, 0xbd, 0xb1, 0x0a, 0xe7, 0xae, 0x97, 0x0a, - 0xe4, 0xbd, 0x8e, 0x0a, 0xe6, 0x8c, 0x81, 0x0a, 0xe9, 0x9f, 0xb3, 0x0a, - 0xe7, 0x9c, 0xbe, 0x0a, 0xe6, 0x9b, 0xb8, 0x0a, 0xe5, 0xb8, 0x83, 0x0a, - 0xe5, 0xa4, 0x8d, 0x0a, 0xe5, 0xae, 0xb9, 0x0a, 0xe5, 0x85, 0x92, 0x0a, - 0xe9, 0xa0, 0x88, 0x0a, 0xe9, 0x9a, 0x9b, 0x0a, 0xe5, 0x95, 0x86, 0x0a, - 0xe9, 0x9d, 0x9e, 0x0a, 0xe9, 0xa9, 0x97, 0x0a, 0xe9, 0x80, 0xa3, 0x0a, - 0xe6, 0x96, 0xb7, 0x0a, 0xe6, 0xb7, 0xb1, 0x0a, 0xe9, 0x9b, 0xa3, 0x0a, - 0xe8, 0xbf, 0x91, 0x0a, 0xe7, 0xa4, 0xa6, 0x0a, 0xe5, 0x8d, 0x83, 0x0a, - 0xe9, 0x80, 0xb1, 0x0a, 0xe5, 0xa7, 0x94, 0x0a, 0xe7, 0xb4, 0xa0, 0x0a, - 0xe6, 0x8a, 0x80, 0x0a, 0xe5, 0x82, 0x99, 0x0a, 0xe5, 0x8d, 0x8a, 0x0a, - 0xe8, 0xbe, 0xa6, 0x0a, 0xe9, 0x9d, 0x92, 0x0a, 0xe7, 0x9c, 0x81, 0x0a, - 0xe5, 0x88, 0x97, 0x0a, 0xe7, 0xbf, 0x92, 0x0a, 0xe9, 0x9f, 0xbf, 0x0a, - 0xe7, 0xb4, 0x84, 0x0a, 0xe6, 0x94, 0xaf, 0x0a, 0xe8, 0x88, 0xac, 0x0a, - 0xe5, 0x8f, 0xb2, 0x0a, 0xe6, 0x84, 0x9f, 0x0a, 0xe5, 0x8b, 0x9e, 0x0a, - 0xe4, 0xbe, 0xbf, 0x0a, 0xe5, 0x9c, 0x98, 0x0a, 0xe5, 0xbe, 0x80, 0x0a, - 0xe9, 0x85, 0xb8, 0x0a, 0xe6, 0xad, 0xb7, 0x0a, 0xe5, 0xb8, 0x82, 0x0a, - 0xe5, 0x85, 0x8b, 0x0a, 0xe4, 0xbd, 0x95, 0x0a, 0xe9, 0x99, 0xa4, 0x0a, - 0xe6, 0xb6, 0x88, 0x0a, 0xe6, 0xa7, 0x8b, 0x0a, 0xe5, 0xba, 0x9c, 0x0a, - 0xe7, 0xa8, 0xb1, 0x0a, 0xe5, 0xa4, 0xaa, 0x0a, 0xe6, 0xba, 0x96, 0x0a, - 0xe7, 0xb2, 0xbe, 0x0a, 0xe5, 0x80, 0xbc, 0x0a, 0xe8, 0x99, 0x9f, 0x0a, - 0xe7, 0x8e, 0x87, 0x0a, 0xe6, 0x97, 0x8f, 0x0a, 0xe7, 0xb6, 0xad, 0x0a, - 0xe5, 0x8a, 0x83, 0x0a, 0xe9, 0x81, 0xb8, 0x0a, 0xe6, 0xa8, 0x99, 0x0a, - 0xe5, 0xaf, 0xab, 0x0a, 0xe5, 0xad, 0x98, 0x0a, 0xe5, 0x80, 0x99, 0x0a, - 0xe6, 0xaf, 0x9b, 0x0a, 0xe8, 0xa6, 0xaa, 0x0a, 0xe5, 0xbf, 0xab, 0x0a, - 0xe6, 0x95, 0x88, 0x0a, 0xe6, 0x96, 0xaf, 0x0a, 0xe9, 0x99, 0xa2, 0x0a, - 0xe6, 0x9f, 0xa5, 0x0a, 0xe6, 0xb1, 0x9f, 0x0a, 0xe5, 0x9e, 0x8b, 0x0a, - 0xe7, 0x9c, 0xbc, 0x0a, 0xe7, 0x8e, 0x8b, 0x0a, 0xe6, 0x8c, 0x89, 0x0a, - 0xe6, 0xa0, 0xbc, 0x0a, 0xe9, 0xa4, 0x8a, 0x0a, 0xe6, 0x98, 0x93, 0x0a, - 0xe7, 0xbd, 0xae, 0x0a, 0xe6, 0xb4, 0xbe, 0x0a, 0xe5, 0xb1, 0xa4, 0x0a, - 0xe7, 0x89, 0x87, 0x0a, 0xe5, 0xa7, 0x8b, 0x0a, 0xe5, 0x8d, 0xbb, 0x0a, - 0xe5, 0xb0, 0x88, 0x0a, 0xe7, 0x8b, 0x80, 0x0a, 0xe8, 0x82, 0xb2, 0x0a, - 0xe5, 0xbb, 0xa0, 0x0a, 0xe4, 0xba, 0xac, 0x0a, 0xe8, 0xad, 0x98, 0x0a, - 0xe9, 0x81, 0xa9, 0x0a, 0xe5, 0xb1, 0xac, 0x0a, 0xe5, 0x9c, 0x93, 0x0a, - 0xe5, 0x8c, 0x85, 0x0a, 0xe7, 0x81, 0xab, 0x0a, 0xe4, 0xbd, 0x8f, 0x0a, - 0xe8, 0xaa, 0xbf, 0x0a, 0xe6, 0xbb, 0xbf, 0x0a, 0xe7, 0xb8, 0xa3, 0x0a, - 0xe5, 0xb1, 0x80, 0x0a, 0xe7, 0x85, 0xa7, 0x0a, 0xe5, 0x8f, 0x83, 0x0a, - 0xe7, 0xb4, 0x85, 0x0a, 0xe7, 0xb4, 0xb0, 0x0a, 0xe5, 0xbc, 0x95, 0x0a, - 0xe8, 0x81, 0xbd, 0x0a, 0xe8, 0xa9, 0xb2, 0x0a, 0xe9, 0x90, 0xb5, 0x0a, - 0xe5, 0x83, 0xb9, 0x0a, 0xe5, 0x9a, 0xb4, 0x0a, 0xe9, 0xa6, 0x96, 0x0a, - 0xe5, 0xba, 0x95, 0x0a, 0xe6, 0xb6, 0xb2, 0x0a, 0xe5, 0xae, 0x98, 0x0a, - 0xe5, 0xbe, 0xb7, 0x0a, 0xe9, 0x9a, 0xa8, 0x0a, 0xe7, 0x97, 0x85, 0x0a, - 0xe8, 0x98, 0x87, 0x0a, 0xe5, 0xa4, 0xb1, 0x0a, 0xe7, 0x88, 0xbe, 0x0a, - 0xe6, 0xad, 0xbb, 0x0a, 0xe8, 0xac, 0x9b, 0x0a, 0xe9, 0x85, 0x8d, 0x0a, - 0xe5, 0xa5, 0xb3, 0x0a, 0xe9, 0xbb, 0x83, 0x0a, 0xe6, 0x8e, 0xa8, 0x0a, - 0xe9, 0xa1, 0xaf, 0x0a, 0xe8, 0xab, 0x87, 0x0a, 0xe7, 0xbd, 0xaa, 0x0a, - 0xe7, 0xa5, 0x9e, 0x0a, 0xe8, 0x97, 0x9d, 0x0a, 0xe5, 0x91, 0xa2, 0x0a, - 0xe5, 0xb8, 0xad, 0x0a, 0xe5, 0x90, 0xab, 0x0a, 0xe4, 0xbc, 0x81, 0x0a, - 0xe6, 0x9c, 0x9b, 0x0a, 0xe5, 0xaf, 0x86, 0x0a, 0xe6, 0x89, 0xb9, 0x0a, - 0xe7, 0x87, 0x9f, 0x0a, 0xe9, 0xa0, 0x85, 0x0a, 0xe9, 0x98, 0xb2, 0x0a, - 0xe8, 0x88, 0x89, 0x0a, 0xe7, 0x90, 0x83, 0x0a, 0xe8, 0x8b, 0xb1, 0x0a, - 0xe6, 0xb0, 0xa7, 0x0a, 0xe5, 0x8b, 0xa2, 0x0a, 0xe5, 0x91, 0x8a, 0x0a, - 0xe6, 0x9d, 0x8e, 0x0a, 0xe5, 0x8f, 0xb0, 0x0a, 0xe8, 0x90, 0xbd, 0x0a, - 0xe6, 0x9c, 0xa8, 0x0a, 0xe5, 0xb9, 0xab, 0x0a, 0xe8, 0xbc, 0xaa, 0x0a, - 0xe7, 0xa0, 0xb4, 0x0a, 0xe4, 0xba, 0x9e, 0x0a, 0xe5, 0xb8, 0xab, 0x0a, - 0xe5, 0x9c, 0x8d, 0x0a, 0xe6, 0xb3, 0xa8, 0x0a, 0xe9, 0x81, 0xa0, 0x0a, - 0xe5, 0xad, 0x97, 0x0a, 0xe6, 0x9d, 0x90, 0x0a, 0xe6, 0x8e, 0x92, 0x0a, - 0xe4, 0xbe, 0x9b, 0x0a, 0xe6, 0xb2, 0xb3, 0x0a, 0xe6, 0x85, 0x8b, 0x0a, - 0xe5, 0xb0, 0x81, 0x0a, 0xe5, 0x8f, 0xa6, 0x0a, 0xe6, 0x96, 0xbd, 0x0a, - 0xe6, 0xb8, 0x9b, 0x0a, 0xe6, 0xa8, 0xb9, 0x0a, 0xe6, 0xba, 0xb6, 0x0a, - 0xe6, 0x80, 0x8e, 0x0a, 0xe6, 0xad, 0xa2, 0x0a, 0xe6, 0xa1, 0x88, 0x0a, - 0xe8, 0xa8, 0x80, 0x0a, 0xe5, 0xa3, 0xab, 0x0a, 0xe5, 0x9d, 0x87, 0x0a, - 0xe6, 0xad, 0xa6, 0x0a, 0xe5, 0x9b, 0xba, 0x0a, 0xe8, 0x91, 0x89, 0x0a, - 0xe9, 0xad, 0x9a, 0x0a, 0xe6, 0xb3, 0xa2, 0x0a, 0xe8, 0xa6, 0x96, 0x0a, - 0xe5, 0x83, 0x85, 0x0a, 0xe8, 0xb2, 0xbb, 0x0a, 0xe7, 0xb7, 0x8a, 0x0a, - 0xe6, 0x84, 0x9b, 0x0a, 0xe5, 0xb7, 0xa6, 0x0a, 0xe7, 0xab, 0xa0, 0x0a, - 0xe6, 0x97, 0xa9, 0x0a, 0xe6, 0x9c, 0x9d, 0x0a, 0xe5, 0xae, 0xb3, 0x0a, - 0xe7, 0xba, 0x8c, 0x0a, 0xe8, 0xbc, 0x95, 0x0a, 0xe6, 0x9c, 0x8d, 0x0a, - 0xe8, 0xa9, 0xa6, 0x0a, 0xe9, 0xa3, 0x9f, 0x0a, 0xe5, 0x85, 0x85, 0x0a, - 0xe5, 0x85, 0xb5, 0x0a, 0xe6, 0xba, 0x90, 0x0a, 0xe5, 0x88, 0xa4, 0x0a, - 0xe8, 0xad, 0xb7, 0x0a, 0xe5, 0x8f, 0xb8, 0x0a, 0xe8, 0xb6, 0xb3, 0x0a, - 0xe6, 0x9f, 0x90, 0x0a, 0xe7, 0xb7, 0xb4, 0x0a, 0xe5, 0xb7, 0xae, 0x0a, - 0xe8, 0x87, 0xb4, 0x0a, 0xe6, 0x9d, 0xbf, 0x0a, 0xe7, 0x94, 0xb0, 0x0a, - 0xe9, 0x99, 0x8d, 0x0a, 0xe9, 0xbb, 0x91, 0x0a, 0xe7, 0x8a, 0xaf, 0x0a, - 0xe8, 0xb2, 0xa0, 0x0a, 0xe6, 0x93, 0x8a, 0x0a, 0xe8, 0x8c, 0x83, 0x0a, - 0xe7, 0xb9, 0xbc, 0x0a, 0xe8, 0x88, 0x88, 0x0a, 0xe4, 0xbc, 0xbc, 0x0a, - 0xe9, 0xa4, 0x98, 0x0a, 0xe5, 0xa0, 0x85, 0x0a, 0xe6, 0x9b, 0xb2, 0x0a, - 0xe8, 0xbc, 0xb8, 0x0a, 0xe4, 0xbf, 0xae, 0x0a, 0xe6, 0x95, 0x85, 0x0a, - 0xe5, 0x9f, 0x8e, 0x0a, 0xe5, 0xa4, 0xab, 0x0a, 0xe5, 0xa4, 0xa0, 0x0a, - 0xe9, 0x80, 0x81, 0x0a, 0xe7, 0xad, 0x86, 0x0a, 0xe8, 0x88, 0xb9, 0x0a, - 0xe4, 0xbd, 0x94, 0x0a, 0xe5, 0x8f, 0xb3, 0x0a, 0xe8, 0xb2, 0xa1, 0x0a, - 0xe5, 0x90, 0x83, 0x0a, 0xe5, 0xaf, 0x8c, 0x0a, 0xe6, 0x98, 0xa5, 0x0a, - 0xe8, 0x81, 0xb7, 0x0a, 0xe8, 0xa6, 0xba, 0x0a, 0xe6, 0xbc, 0xa2, 0x0a, - 0xe7, 0x95, 0xab, 0x0a, 0xe5, 0x8a, 0x9f, 0x0a, 0xe5, 0xb7, 0xb4, 0x0a, - 0xe8, 0xb7, 0x9f, 0x0a, 0xe9, 0x9b, 0x96, 0x0a, 0xe9, 0x9b, 0x9c, 0x0a, - 0xe9, 0xa3, 0x9b, 0x0a, 0xe6, 0xaa, 0xa2, 0x0a, 0xe5, 0x90, 0xb8, 0x0a, - 0xe5, 0x8a, 0xa9, 0x0a, 0xe6, 0x98, 0x87, 0x0a, 0xe9, 0x99, 0xbd, 0x0a, - 0xe4, 0xba, 0x92, 0x0a, 0xe5, 0x88, 0x9d, 0x0a, 0xe5, 0x89, 0xb5, 0x0a, - 0xe6, 0x8a, 0x97, 0x0a, 0xe8, 0x80, 0x83, 0x0a, 0xe6, 0x8a, 0x95, 0x0a, - 0xe5, 0xa3, 0x9e, 0x0a, 0xe7, 0xad, 0x96, 0x0a, 0xe5, 0x8f, 0xa4, 0x0a, - 0xe5, 0xbe, 0x91, 0x0a, 0xe6, 0x8f, 0x9b, 0x0a, 0xe6, 0x9c, 0xaa, 0x0a, - 0xe8, 0xb7, 0x91, 0x0a, 0xe7, 0x95, 0x99, 0x0a, 0xe9, 0x8b, 0xbc, 0x0a, - 0xe6, 0x9b, 0xbe, 0x0a, 0xe7, 0xab, 0xaf, 0x0a, 0xe8, 0xb2, 0xac, 0x0a, - 0xe7, 0xab, 0x99, 0x0a, 0xe7, 0xb0, 0xa1, 0x0a, 0xe8, 0xbf, 0xb0, 0x0a, - 0xe9, 0x8c, 0xa2, 0x0a, 0xe5, 0x89, 0xaf, 0x0a, 0xe7, 0x9b, 0xa1, 0x0a, - 0xe5, 0xb8, 0x9d, 0x0a, 0xe5, 0xb0, 0x84, 0x0a, 0xe8, 0x8d, 0x89, 0x0a, - 0xe8, 0xa1, 0x9d, 0x0a, 0xe6, 0x89, 0xbf, 0x0a, 0xe7, 0x8d, 0xa8, 0x0a, - 0xe4, 0xbb, 0xa4, 0x0a, 0xe9, 0x99, 0x90, 0x0a, 0xe9, 0x98, 0xbf, 0x0a, - 0xe5, 0xae, 0xa3, 0x0a, 0xe7, 0x92, 0xb0, 0x0a, 0xe9, 0x9b, 0x99, 0x0a, - 0xe8, 0xab, 0x8b, 0x0a, 0xe8, 0xb6, 0x85, 0x0a, 0xe5, 0xbe, 0xae, 0x0a, - 0xe8, 0xae, 0x93, 0x0a, 0xe6, 0x8e, 0xa7, 0x0a, 0xe5, 0xb7, 0x9e, 0x0a, - 0xe8, 0x89, 0xaf, 0x0a, 0xe8, 0xbb, 0xb8, 0x0a, 0xe6, 0x89, 0xbe, 0x0a, - 0xe5, 0x90, 0xa6, 0x0a, 0xe7, 0xb4, 0x80, 0x0a, 0xe7, 0x9b, 0x8a, 0x0a, - 0xe4, 0xbe, 0x9d, 0x0a, 0xe5, 0x84, 0xaa, 0x0a, 0xe9, 0xa0, 0x82, 0x0a, - 0xe7, 0xa4, 0x8e, 0x0a, 0xe8, 0xbc, 0x89, 0x0a, 0xe5, 0x80, 0x92, 0x0a, - 0xe6, 0x88, 0xbf, 0x0a, 0xe7, 0xaa, 0x81, 0x0a, 0xe5, 0x9d, 0x90, 0x0a, - 0xe7, 0xb2, 0x89, 0x0a, 0xe6, 0x95, 0xb5, 0x0a, 0xe7, 0x95, 0xa5, 0x0a, - 0xe5, 0xae, 0xa2, 0x0a, 0xe8, 0xa2, 0x81, 0x0a, 0xe5, 0x86, 0xb7, 0x0a, - 0xe5, 0x8b, 0x9d, 0x0a, 0xe7, 0xb5, 0x95, 0x0a, 0xe6, 0x9e, 0x90, 0x0a, - 0xe5, 0xa1, 0x8a, 0x0a, 0xe5, 0x8a, 0x91, 0x0a, 0xe6, 0xb8, 0xac, 0x0a, - 0xe7, 0xb5, 0xb2, 0x0a, 0xe5, 0x8d, 0x94, 0x0a, 0xe8, 0xa8, 0xb4, 0x0a, - 0xe5, 0xbf, 0xb5, 0x0a, 0xe9, 0x99, 0xb3, 0x0a, 0xe4, 0xbb, 0x8d, 0x0a, - 0xe7, 0xbe, 0x85, 0x0a, 0xe9, 0xb9, 0xbd, 0x0a, 0xe5, 0x8f, 0x8b, 0x0a, - 0xe6, 0xb4, 0x8b, 0x0a, 0xe9, 0x8c, 0xaf, 0x0a, 0xe8, 0x8b, 0xa6, 0x0a, - 0xe5, 0xa4, 0x9c, 0x0a, 0xe5, 0x88, 0x91, 0x0a, 0xe7, 0xa7, 0xbb, 0x0a, - 0xe9, 0xa0, 0xbb, 0x0a, 0xe9, 0x80, 0x90, 0x0a, 0xe9, 0x9d, 0xa0, 0x0a, - 0xe6, 0xb7, 0xb7, 0x0a, 0xe6, 0xaf, 0x8d, 0x0a, 0xe7, 0x9f, 0xad, 0x0a, - 0xe7, 0x9a, 0xae, 0x0a, 0xe7, 0xb5, 0x82, 0x0a, 0xe8, 0x81, 0x9a, 0x0a, - 0xe6, 0xb1, 0xbd, 0x0a, 0xe6, 0x9d, 0x91, 0x0a, 0xe9, 0x9b, 0xb2, 0x0a, - 0xe5, 0x93, 0xaa, 0x0a, 0xe6, 0x97, 0xa2, 0x0a, 0xe8, 0xb7, 0x9d, 0x0a, - 0xe8, 0xa1, 0x9b, 0x0a, 0xe5, 0x81, 0x9c, 0x0a, 0xe7, 0x83, 0x88, 0x0a, - 0xe5, 0xa4, 0xae, 0x0a, 0xe5, 0xaf, 0x9f, 0x0a, 0xe7, 0x87, 0x92, 0x0a, - 0xe8, 0xbf, 0x85, 0x0a, 0xe5, 0xa2, 0x83, 0x0a, 0xe8, 0x8b, 0xa5, 0x0a, - 0xe5, 0x8d, 0xb0, 0x0a, 0xe6, 0xb4, 0xb2, 0x0a, 0xe5, 0x88, 0xbb, 0x0a, - 0xe6, 0x8b, 0xac, 0x0a, 0xe6, 0xbf, 0x80, 0x0a, 0xe5, 0xad, 0x94, 0x0a, - 0xe6, 0x90, 0x9e, 0x0a, 0xe7, 0x94, 0x9a, 0x0a, 0xe5, 0xae, 0xa4, 0x0a, - 0xe5, 0xbe, 0x85, 0x0a, 0xe6, 0xa0, 0xb8, 0x0a, 0xe6, 0xa0, 0xa1, 0x0a, - 0xe6, 0x95, 0xa3, 0x0a, 0xe4, 0xbe, 0xb5, 0x0a, 0xe5, 0x90, 0xa7, 0x0a, - 0xe7, 0x94, 0xb2, 0x0a, 0xe9, 0x81, 0x8a, 0x0a, 0xe4, 0xb9, 0x85, 0x0a, - 0xe8, 0x8f, 0x9c, 0x0a, 0xe5, 0x91, 0xb3, 0x0a, 0xe8, 0x88, 0x8a, 0x0a, - 0xe6, 0xa8, 0xa1, 0x0a, 0xe6, 0xb9, 0x96, 0x0a, 0xe8, 0xb2, 0xa8, 0x0a, - 0xe6, 0x90, 0x8d, 0x0a, 0xe9, 0xa0, 0x90, 0x0a, 0xe9, 0x98, 0xbb, 0x0a, - 0xe6, 0xaf, 0xab, 0x0a, 0xe6, 0x99, 0xae, 0x0a, 0xe7, 0xa9, 0xa9, 0x0a, - 0xe4, 0xb9, 0x99, 0x0a, 0xe5, 0xaa, 0xbd, 0x0a, 0xe6, 0xa4, 0x8d, 0x0a, - 0xe6, 0x81, 0xaf, 0x0a, 0xe6, 0x93, 0xb4, 0x0a, 0xe9, 0x8a, 0x80, 0x0a, - 0xe8, 0xaa, 0x9e, 0x0a, 0xe6, 0x8f, 0xae, 0x0a, 0xe9, 0x85, 0x92, 0x0a, - 0xe5, 0xae, 0x88, 0x0a, 0xe6, 0x8b, 0xbf, 0x0a, 0xe5, 0xba, 0x8f, 0x0a, - 0xe7, 0xb4, 0x99, 0x0a, 0xe9, 0x86, 0xab, 0x0a, 0xe7, 0xbc, 0xba, 0x0a, - 0xe9, 0x9b, 0xa8, 0x0a, 0xe5, 0x97, 0x8e, 0x0a, 0xe9, 0x87, 0x9d, 0x0a, - 0xe5, 0x8a, 0x89, 0x0a, 0xe5, 0x95, 0x8a, 0x0a, 0xe6, 0x80, 0xa5, 0x0a, - 0xe5, 0x94, 0xb1, 0x0a, 0xe8, 0xaa, 0xa4, 0x0a, 0xe8, 0xa8, 0x93, 0x0a, - 0xe9, 0xa1, 0x98, 0x0a, 0xe5, 0xaf, 0xa9, 0x0a, 0xe9, 0x99, 0x84, 0x0a, - 0xe7, 0x8d, 0xb2, 0x0a, 0xe8, 0x8c, 0xb6, 0x0a, 0xe9, 0xae, 0xae, 0x0a, - 0xe7, 0xb3, 0xa7, 0x0a, 0xe6, 0x96, 0xa4, 0x0a, 0xe5, 0xad, 0xa9, 0x0a, - 0xe8, 0x84, 0xab, 0x0a, 0xe7, 0xa1, 0xab, 0x0a, 0xe8, 0x82, 0xa5, 0x0a, - 0xe5, 0x96, 0x84, 0x0a, 0xe9, 0xbe, 0x8d, 0x0a, 0xe6, 0xbc, 0x94, 0x0a, - 0xe7, 0x88, 0xb6, 0x0a, 0xe6, 0xbc, 0xb8, 0x0a, 0xe8, 0xa1, 0x80, 0x0a, - 0xe6, 0xad, 0xa1, 0x0a, 0xe6, 0xa2, 0xb0, 0x0a, 0xe6, 0x8e, 0x8c, 0x0a, - 0xe6, 0xad, 0x8c, 0x0a, 0xe6, 0xb2, 0x99, 0x0a, 0xe5, 0x89, 0x9b, 0x0a, - 0xe6, 0x94, 0xbb, 0x0a, 0xe8, 0xac, 0x82, 0x0a, 0xe7, 0x9b, 0xbe, 0x0a, - 0xe8, 0xa8, 0x8e, 0x0a, 0xe6, 0x99, 0x9a, 0x0a, 0xe7, 0xb2, 0x92, 0x0a, - 0xe4, 0xba, 0x82, 0x0a, 0xe7, 0x87, 0x83, 0x0a, 0xe7, 0x9f, 0x9b, 0x0a, - 0xe4, 0xb9, 0x8e, 0x0a, 0xe6, 0xae, 0xba, 0x0a, 0xe8, 0x97, 0xa5, 0x0a, - 0xe5, 0xaf, 0xa7, 0x0a, 0xe9, 0xad, 0xaf, 0x0a, 0xe8, 0xb2, 0xb4, 0x0a, - 0xe9, 0x90, 0x98, 0x0a, 0xe7, 0x85, 0xa4, 0x0a, 0xe8, 0xae, 0x80, 0x0a, - 0xe7, 0x8f, 0xad, 0x0a, 0xe4, 0xbc, 0xaf, 0x0a, 0xe9, 0xa6, 0x99, 0x0a, - 0xe4, 0xbb, 0x8b, 0x0a, 0xe8, 0xbf, 0xab, 0x0a, 0xe5, 0x8f, 0xa5, 0x0a, - 0xe8, 0xb1, 0x90, 0x0a, 0xe5, 0x9f, 0xb9, 0x0a, 0xe6, 0x8f, 0xa1, 0x0a, - 0xe8, 0x98, 0xad, 0x0a, 0xe6, 0x93, 0x94, 0x0a, 0xe5, 0xbc, 0xa6, 0x0a, - 0xe8, 0x9b, 0x8b, 0x0a, 0xe6, 0xb2, 0x89, 0x0a, 0xe5, 0x81, 0x87, 0x0a, - 0xe7, 0xa9, 0xbf, 0x0a, 0xe5, 0x9f, 0xb7, 0x0a, 0xe7, 0xad, 0x94, 0x0a, - 0xe6, 0xa8, 0x82, 0x0a, 0xe8, 0xaa, 0xb0, 0x0a, 0xe9, 0xa0, 0x86, 0x0a, - 0xe7, 0x85, 0x99, 0x0a, 0xe7, 0xb8, 0xae, 0x0a, 0xe5, 0xbe, 0xb5, 0x0a, - 0xe8, 0x87, 0x89, 0x0a, 0xe5, 0x96, 0x9c, 0x0a, 0xe6, 0x9d, 0xbe, 0x0a, - 0xe8, 0x85, 0xb3, 0x0a, 0xe5, 0x9b, 0xb0, 0x0a, 0xe7, 0x95, 0xb0, 0x0a, - 0xe5, 0x85, 0x8d, 0x0a, 0xe8, 0x83, 0x8c, 0x0a, 0xe6, 0x98, 0x9f, 0x0a, - 0xe7, 0xa6, 0x8f, 0x0a, 0xe8, 0xb2, 0xb7, 0x0a, 0xe6, 0x9f, 0x93, 0x0a, - 0xe4, 0xba, 0x95, 0x0a, 0xe6, 0xa6, 0x82, 0x0a, 0xe6, 0x85, 0xa2, 0x0a, - 0xe6, 0x80, 0x95, 0x0a, 0xe7, 0xa3, 0x81, 0x0a, 0xe5, 0x80, 0x8d, 0x0a, - 0xe7, 0xa5, 0x96, 0x0a, 0xe7, 0x9a, 0x87, 0x0a, 0xe4, 0xbf, 0x83, 0x0a, - 0xe9, 0x9d, 0x9c, 0x0a, 0xe8, 0xa3, 0x9c, 0x0a, 0xe8, 0xa9, 0x95, 0x0a, - 0xe7, 0xbf, 0xbb, 0x0a, 0xe8, 0x82, 0x89, 0x0a, 0xe8, 0xb8, 0x90, 0x0a, - 0xe5, 0xb0, 0xbc, 0x0a, 0xe8, 0xa1, 0xa3, 0x0a, 0xe5, 0xaf, 0xac, 0x0a, - 0xe6, 0x8f, 0x9a, 0x0a, 0xe6, 0xa3, 0x89, 0x0a, 0xe5, 0xb8, 0x8c, 0x0a, - 0xe5, 0x82, 0xb7, 0x0a, 0xe6, 0x93, 0x8d, 0x0a, 0xe5, 0x9e, 0x82, 0x0a, - 0xe7, 0xa7, 0x8b, 0x0a, 0xe5, 0xae, 0x9c, 0x0a, 0xe6, 0xb0, 0xab, 0x0a, - 0xe5, 0xa5, 0x97, 0x0a, 0xe7, 0x9d, 0xa3, 0x0a, 0xe6, 0x8c, 0xaf, 0x0a, - 0xe6, 0x9e, 0xb6, 0x0a, 0xe4, 0xba, 0xae, 0x0a, 0xe6, 0x9c, 0xab, 0x0a, - 0xe6, 0x86, 0xb2, 0x0a, 0xe6, 0x85, 0xb6, 0x0a, 0xe7, 0xb7, 0xa8, 0x0a, - 0xe7, 0x89, 0x9b, 0x0a, 0xe8, 0xa7, 0xb8, 0x0a, 0xe6, 0x98, 0xa0, 0x0a, - 0xe9, 0x9b, 0xb7, 0x0a, 0xe9, 0x8a, 0xb7, 0x0a, 0xe8, 0xa9, 0xa9, 0x0a, - 0xe5, 0xba, 0xa7, 0x0a, 0xe5, 0xb1, 0x85, 0x0a, 0xe6, 0x8a, 0x93, 0x0a, - 0xe8, 0xa3, 0x82, 0x0a, 0xe8, 0x83, 0x9e, 0x0a, 0xe5, 0x91, 0xbc, 0x0a, - 0xe5, 0xa8, 0x98, 0x0a, 0xe6, 0x99, 0xaf, 0x0a, 0xe5, 0xa8, 0x81, 0x0a, - 0xe7, 0xb6, 0xa0, 0x0a, 0xe6, 0x99, 0xb6, 0x0a, 0xe5, 0x8e, 0x9a, 0x0a, - 0xe7, 0x9b, 0x9f, 0x0a, 0xe8, 0xa1, 0xa1, 0x0a, 0xe9, 0x9b, 0x9e, 0x0a, - 0xe5, 0xad, 0xab, 0x0a, 0xe5, 0xbb, 0xb6, 0x0a, 0xe5, 0x8d, 0xb1, 0x0a, - 0xe8, 0x86, 0xa0, 0x0a, 0xe5, 0xb1, 0x8b, 0x0a, 0xe9, 0x84, 0x89, 0x0a, - 0xe8, 0x87, 0xa8, 0x0a, 0xe9, 0x99, 0xb8, 0x0a, 0xe9, 0xa1, 0xa7, 0x0a, - 0xe6, 0x8e, 0x89, 0x0a, 0xe5, 0x91, 0x80, 0x0a, 0xe7, 0x87, 0x88, 0x0a, - 0xe6, 0xad, 0xb2, 0x0a, 0xe6, 0x8e, 0xaa, 0x0a, 0xe6, 0x9d, 0x9f, 0x0a, - 0xe8, 0x80, 0x90, 0x0a, 0xe5, 0x8a, 0x87, 0x0a, 0xe7, 0x8e, 0x89, 0x0a, - 0xe8, 0xb6, 0x99, 0x0a, 0xe8, 0xb7, 0xb3, 0x0a, 0xe5, 0x93, 0xa5, 0x0a, - 0xe5, 0xad, 0xa3, 0x0a, 0xe8, 0xaa, 0xb2, 0x0a, 0xe5, 0x87, 0xb1, 0x0a, - 0xe8, 0x83, 0xa1, 0x0a, 0xe9, 0xa1, 0x8d, 0x0a, 0xe6, 0xac, 0xbe, 0x0a, - 0xe7, 0xb4, 0xb9, 0x0a, 0xe5, 0x8d, 0xb7, 0x0a, 0xe9, 0xbd, 0x8a, 0x0a, - 0xe5, 0x81, 0x89, 0x0a, 0xe8, 0x92, 0xb8, 0x0a, 0xe6, 0xae, 0x96, 0x0a, - 0xe6, 0xb0, 0xb8, 0x0a, 0xe5, 0xae, 0x97, 0x0a, 0xe8, 0x8b, 0x97, 0x0a, - 0xe5, 0xb7, 0x9d, 0x0a, 0xe7, 0x88, 0x90, 0x0a, 0xe5, 0xb2, 0xa9, 0x0a, - 0xe5, 0xbc, 0xb1, 0x0a, 0xe9, 0x9b, 0xb6, 0x0a, 0xe6, 0xa5, 0x8a, 0x0a, - 0xe5, 0xa5, 0x8f, 0x0a, 0xe6, 0xb2, 0xbf, 0x0a, 0xe9, 0x9c, 0xb2, 0x0a, - 0xe6, 0xa1, 0xbf, 0x0a, 0xe6, 0x8e, 0xa2, 0x0a, 0xe6, 0xbb, 0x91, 0x0a, - 0xe9, 0x8e, 0xae, 0x0a, 0xe9, 0xa3, 0xaf, 0x0a, 0xe6, 0xbf, 0x83, 0x0a, - 0xe8, 0x88, 0xaa, 0x0a, 0xe6, 0x87, 0xb7, 0x0a, 0xe8, 0xb6, 0x95, 0x0a, - 0xe5, 0xba, 0xab, 0x0a, 0xe5, 0xa5, 0xaa, 0x0a, 0xe4, 0xbc, 0x8a, 0x0a, - 0xe9, 0x9d, 0x88, 0x0a, 0xe7, 0xa8, 0x85, 0x0a, 0xe9, 0x80, 0x94, 0x0a, - 0xe6, 0xbb, 0x85, 0x0a, 0xe8, 0xb3, 0xbd, 0x0a, 0xe6, 0xad, 0xb8, 0x0a, - 0xe5, 0x8f, 0xac, 0x0a, 0xe9, 0xbc, 0x93, 0x0a, 0xe6, 0x92, 0xad, 0x0a, - 0xe7, 0x9b, 0xa4, 0x0a, 0xe8, 0xa3, 0x81, 0x0a, 0xe9, 0x9a, 0xaa, 0x0a, - 0xe5, 0xba, 0xb7, 0x0a, 0xe5, 0x94, 0xaf, 0x0a, 0xe9, 0x8c, 0x84, 0x0a, - 0xe8, 0x8f, 0x8c, 0x0a, 0xe7, 0xb4, 0x94, 0x0a, 0xe5, 0x80, 0x9f, 0x0a, - 0xe7, 0xb3, 0x96, 0x0a, 0xe8, 0x93, 0x8b, 0x0a, 0xe6, 0xa9, 0xab, 0x0a, - 0xe7, 0xac, 0xa6, 0x0a, 0xe7, 0xa7, 0x81, 0x0a, 0xe5, 0x8a, 0xaa, 0x0a, - 0xe5, 0xa0, 0x82, 0x0a, 0xe5, 0x9f, 0x9f, 0x0a, 0xe6, 0xa7, 0x8d, 0x0a, - 0xe6, 0xbd, 0xa4, 0x0a, 0xe5, 0xb9, 0x85, 0x0a, 0xe5, 0x93, 0x88, 0x0a, - 0xe7, 0xab, 0x9f, 0x0a, 0xe7, 0x86, 0x9f, 0x0a, 0xe8, 0x9f, 0xb2, 0x0a, - 0xe6, 0xbe, 0xa4, 0x0a, 0xe8, 0x85, 0xa6, 0x0a, 0xe5, 0xa3, 0xa4, 0x0a, - 0xe7, 0xa2, 0xb3, 0x0a, 0xe6, 0xad, 0x90, 0x0a, 0xe9, 0x81, 0x8d, 0x0a, - 0xe5, 0x81, 0xb4, 0x0a, 0xe5, 0xaf, 0xa8, 0x0a, 0xe6, 0x95, 0xa2, 0x0a, - 0xe5, 0xbe, 0xb9, 0x0a, 0xe6, 0x85, 0xae, 0x0a, 0xe6, 0x96, 0x9c, 0x0a, - 0xe8, 0x96, 0x84, 0x0a, 0xe5, 0xba, 0xad, 0x0a, 0xe7, 0xb4, 0x8d, 0x0a, - 0xe5, 0xbd, 0x88, 0x0a, 0xe9, 0xa3, 0xbc, 0x0a, 0xe4, 0xbc, 0xb8, 0x0a, - 0xe6, 0x8a, 0x98, 0x0a, 0xe9, 0xba, 0xa5, 0x0a, 0xe6, 0xbf, 0x95, 0x0a, - 0xe6, 0x9a, 0x97, 0x0a, 0xe8, 0x8d, 0xb7, 0x0a, 0xe7, 0x93, 0xa6, 0x0a, - 0xe5, 0xa1, 0x9e, 0x0a, 0xe5, 0xba, 0x8a, 0x0a, 0xe7, 0xaf, 0x89, 0x0a, - 0xe6, 0x83, 0xa1, 0x0a, 0xe6, 0x88, 0xb6, 0x0a, 0xe8, 0xa8, 0xaa, 0x0a, - 0xe5, 0xa1, 0x94, 0x0a, 0xe5, 0xa5, 0x87, 0x0a, 0xe9, 0x80, 0x8f, 0x0a, - 0xe6, 0xa2, 0x81, 0x0a, 0xe5, 0x88, 0x80, 0x0a, 0xe6, 0x97, 0x8b, 0x0a, - 0xe8, 0xb7, 0xa1, 0x0a, 0xe5, 0x8d, 0xa1, 0x0a, 0xe6, 0xb0, 0xaf, 0x0a, - 0xe9, 0x81, 0x87, 0x0a, 0xe4, 0xbb, 0xbd, 0x0a, 0xe6, 0xaf, 0x92, 0x0a, - 0xe6, 0xb3, 0xa5, 0x0a, 0xe9, 0x80, 0x80, 0x0a, 0xe6, 0xb4, 0x97, 0x0a, - 0xe6, 0x93, 0xba, 0x0a, 0xe7, 0x81, 0xb0, 0x0a, 0xe5, 0xbd, 0xa9, 0x0a, - 0xe8, 0xb3, 0xa3, 0x0a, 0xe8, 0x80, 0x97, 0x0a, 0xe5, 0xa4, 0x8f, 0x0a, - 0xe6, 0x93, 0x87, 0x0a, 0xe5, 0xbf, 0x99, 0x0a, 0xe9, 0x8a, 0x85, 0x0a, - 0xe7, 0x8d, 0xbb, 0x0a, 0xe7, 0xa1, 0xac, 0x0a, 0xe4, 0xba, 0x88, 0x0a, - 0xe7, 0xb9, 0x81, 0x0a, 0xe5, 0x9c, 0x88, 0x0a, 0xe9, 0x9b, 0xaa, 0x0a, - 0xe5, 0x87, 0xbd, 0x0a, 0xe4, 0xba, 0xa6, 0x0a, 0xe6, 0x8a, 0xbd, 0x0a, - 0xe7, 0xaf, 0x87, 0x0a, 0xe9, 0x99, 0xa3, 0x0a, 0xe9, 0x99, 0xb0, 0x0a, - 0xe4, 0xb8, 0x81, 0x0a, 0xe5, 0xb0, 0xba, 0x0a, 0xe8, 0xbf, 0xbd, 0x0a, - 0xe5, 0xa0, 0x86, 0x0a, 0xe9, 0x9b, 0x84, 0x0a, 0xe8, 0xbf, 0x8e, 0x0a, - 0xe6, 0xb3, 0x9b, 0x0a, 0xe7, 0x88, 0xb8, 0x0a, 0xe6, 0xa8, 0x93, 0x0a, - 0xe9, 0x81, 0xbf, 0x0a, 0xe8, 0xac, 0x80, 0x0a, 0xe5, 0x99, 0xb8, 0x0a, - 0xe9, 0x87, 0x8e, 0x0a, 0xe8, 0xb1, 0xac, 0x0a, 0xe6, 0x97, 0x97, 0x0a, - 0xe7, 0xb4, 0xaf, 0x0a, 0xe5, 0x81, 0x8f, 0x0a, 0xe5, 0x85, 0xb8, 0x0a, - 0xe9, 0xa4, 0xa8, 0x0a, 0xe7, 0xb4, 0xa2, 0x0a, 0xe7, 0xa7, 0xa6, 0x0a, - 0xe8, 0x84, 0x82, 0x0a, 0xe6, 0xbd, 0xae, 0x0a, 0xe7, 0x88, 0xba, 0x0a, - 0xe8, 0xb1, 0x86, 0x0a, 0xe5, 0xbf, 0xbd, 0x0a, 0xe6, 0x89, 0x98, 0x0a, - 0xe9, 0xa9, 0x9a, 0x0a, 0xe5, 0xa1, 0x91, 0x0a, 0xe9, 0x81, 0xba, 0x0a, - 0xe6, 0x84, 0x88, 0x0a, 0xe6, 0x9c, 0xb1, 0x0a, 0xe6, 0x9b, 0xbf, 0x0a, - 0xe7, 0xba, 0x96, 0x0a, 0xe7, 0xb2, 0x97, 0x0a, 0xe5, 0x82, 0xbe, 0x0a, - 0xe5, 0xb0, 0x9a, 0x0a, 0xe7, 0x97, 0x9b, 0x0a, 0xe6, 0xa5, 0x9a, 0x0a, - 0xe8, 0xac, 0x9d, 0x0a, 0xe5, 0xa5, 0xae, 0x0a, 0xe8, 0xb3, 0xbc, 0x0a, - 0xe7, 0xa3, 0xa8, 0x0a, 0xe5, 0x90, 0x9b, 0x0a, 0xe6, 0xb1, 0xa0, 0x0a, - 0xe6, 0x97, 0x81, 0x0a, 0xe7, 0xa2, 0x8e, 0x0a, 0xe9, 0xaa, 0xa8, 0x0a, - 0xe7, 0x9b, 0xa3, 0x0a, 0xe6, 0x8d, 0x95, 0x0a, 0xe5, 0xbc, 0x9f, 0x0a, - 0xe6, 0x9a, 0xb4, 0x0a, 0xe5, 0x89, 0xb2, 0x0a, 0xe8, 0xb2, 0xab, 0x0a, - 0xe6, 0xae, 0x8a, 0x0a, 0xe9, 0x87, 0x8b, 0x0a, 0xe8, 0xa9, 0x9e, 0x0a, - 0xe4, 0xba, 0xa1, 0x0a, 0xe5, 0xa3, 0x81, 0x0a, 0xe9, 0xa0, 0x93, 0x0a, - 0xe5, 0xaf, 0xb6, 0x0a, 0xe5, 0x8d, 0x88, 0x0a, 0xe5, 0xa1, 0xb5, 0x0a, - 0xe8, 0x81, 0x9e, 0x0a, 0xe6, 0x8f, 0xad, 0x0a, 0xe7, 0x82, 0xae, 0x0a, - 0xe6, 0xae, 0x98, 0x0a, 0xe5, 0x86, 0xac, 0x0a, 0xe6, 0xa9, 0x8b, 0x0a, - 0xe5, 0xa9, 0xa6, 0x0a, 0xe8, 0xad, 0xa6, 0x0a, 0xe7, 0xb6, 0x9c, 0x0a, - 0xe6, 0x8b, 0x9b, 0x0a, 0xe5, 0x90, 0xb3, 0x0a, 0xe4, 0xbb, 0x98, 0x0a, - 0xe6, 0xb5, 0xae, 0x0a, 0xe9, 0x81, 0xad, 0x0a, 0xe5, 0xbe, 0x90, 0x0a, - 0xe6, 0x82, 0xa8, 0x0a, 0xe6, 0x90, 0x96, 0x0a, 0xe8, 0xb0, 0xb7, 0x0a, - 0xe8, 0xb4, 0x8a, 0x0a, 0xe7, 0xae, 0xb1, 0x0a, 0xe9, 0x9a, 0x94, 0x0a, - 0xe8, 0xa8, 0x82, 0x0a, 0xe7, 0x94, 0xb7, 0x0a, 0xe5, 0x90, 0xb9, 0x0a, - 0xe5, 0x9c, 0x92, 0x0a, 0xe7, 0xb4, 0x9b, 0x0a, 0xe5, 0x94, 0x90, 0x0a, - 0xe6, 0x95, 0x97, 0x0a, 0xe5, 0xae, 0x8b, 0x0a, 0xe7, 0x8e, 0xbb, 0x0a, - 0xe5, 0xb7, 0xa8, 0x0a, 0xe8, 0x80, 0x95, 0x0a, 0xe5, 0x9d, 0xa6, 0x0a, - 0xe6, 0xa6, 0xae, 0x0a, 0xe9, 0x96, 0x89, 0x0a, 0xe7, 0x81, 0xa3, 0x0a, - 0xe9, 0x8d, 0xb5, 0x0a, 0xe5, 0x87, 0xa1, 0x0a, 0xe9, 0xa7, 0x90, 0x0a, - 0xe9, 0x8d, 0x8b, 0x0a, 0xe6, 0x95, 0x91, 0x0a, 0xe6, 0x81, 0xa9, 0x0a, - 0xe5, 0x89, 0x9d, 0x0a, 0xe5, 0x87, 0x9d, 0x0a, 0xe9, 0xb9, 0xbc, 0x0a, - 0xe9, 0xbd, 0x92, 0x0a, 0xe6, 0x88, 0xaa, 0x0a, 0xe7, 0x85, 0x89, 0x0a, - 0xe9, 0xba, 0xbb, 0x0a, 0xe7, 0xb4, 0xa1, 0x0a, 0xe7, 0xa6, 0x81, 0x0a, - 0xe5, 0xbb, 0xa2, 0x0a, 0xe7, 0x9b, 0x9b, 0x0a, 0xe7, 0x89, 0x88, 0x0a, - 0xe7, 0xb7, 0xa9, 0x0a, 0xe6, 0xb7, 0xa8, 0x0a, 0xe7, 0x9d, 0x9b, 0x0a, - 0xe6, 0x98, 0x8c, 0x0a, 0xe5, 0xa9, 0x9a, 0x0a, 0xe6, 0xb6, 0x89, 0x0a, - 0xe7, 0xad, 0x92, 0x0a, 0xe5, 0x98, 0xb4, 0x0a, 0xe6, 0x8f, 0x92, 0x0a, - 0xe5, 0xb2, 0xb8, 0x0a, 0xe6, 0x9c, 0x97, 0x0a, 0xe8, 0x8e, 0x8a, 0x0a, - 0xe8, 0xa1, 0x97, 0x0a, 0xe8, 0x97, 0x8f, 0x0a, 0xe5, 0xa7, 0x91, 0x0a, - 0xe8, 0xb2, 0xbf, 0x0a, 0xe8, 0x85, 0x90, 0x0a, 0xe5, 0xa5, 0xb4, 0x0a, - 0xe5, 0x95, 0xa6, 0x0a, 0xe6, 0x85, 0xa3, 0x0a, 0xe4, 0xb9, 0x98, 0x0a, - 0xe5, 0xa4, 0xa5, 0x0a, 0xe6, 0x81, 0xa2, 0x0a, 0xe5, 0x8b, 0xbb, 0x0a, - 0xe7, 0xb4, 0x97, 0x0a, 0xe6, 0x89, 0x8e, 0x0a, 0xe8, 0xbe, 0xaf, 0x0a, - 0xe8, 0x80, 0xb3, 0x0a, 0xe5, 0xbd, 0xaa, 0x0a, 0xe8, 0x87, 0xa3, 0x0a, - 0xe5, 0x84, 0x84, 0x0a, 0xe7, 0x92, 0x83, 0x0a, 0xe6, 0x8a, 0xb5, 0x0a, - 0xe8, 0x84, 0x88, 0x0a, 0xe7, 0xa7, 0x80, 0x0a, 0xe8, 0x96, 0xa9, 0x0a, - 0xe4, 0xbf, 0x84, 0x0a, 0xe7, 0xb6, 0xb2, 0x0a, 0xe8, 0x88, 0x9e, 0x0a, - 0xe5, 0xba, 0x97, 0x0a, 0xe5, 0x99, 0xb4, 0x0a, 0xe7, 0xb8, 0xb1, 0x0a, - 0xe5, 0xaf, 0xb8, 0x0a, 0xe6, 0xb1, 0x97, 0x0a, 0xe6, 0x8e, 0x9b, 0x0a, - 0xe6, 0xb4, 0xaa, 0x0a, 0xe8, 0xb3, 0x80, 0x0a, 0xe9, 0x96, 0x83, 0x0a, - 0xe6, 0x9f, 0xac, 0x0a, 0xe7, 0x88, 0x86, 0x0a, 0xe7, 0x83, 0xaf, 0x0a, - 0xe6, 0xb4, 0xa5, 0x0a, 0xe7, 0xa8, 0xbb, 0x0a, 0xe7, 0x89, 0x86, 0x0a, - 0xe8, 0xbb, 0x9f, 0x0a, 0xe5, 0x8b, 0x87, 0x0a, 0xe5, 0x83, 0x8f, 0x0a, - 0xe6, 0xbb, 0xbe, 0x0a, 0xe5, 0x8e, 0x98, 0x0a, 0xe8, 0x92, 0x99, 0x0a, - 0xe8, 0x8a, 0xb3, 0x0a, 0xe8, 0x82, 0xaf, 0x0a, 0xe5, 0x9d, 0xa1, 0x0a, - 0xe6, 0x9f, 0xb1, 0x0a, 0xe7, 0x9b, 0xaa, 0x0a, 0xe8, 0x85, 0xbf, 0x0a, - 0xe5, 0x84, 0x80, 0x0a, 0xe6, 0x97, 0x85, 0x0a, 0xe5, 0xb0, 0xbe, 0x0a, - 0xe8, 0xbb, 0x8b, 0x0a, 0xe5, 0x86, 0xb0, 0x0a, 0xe8, 0xb2, 0xa2, 0x0a, - 0xe7, 0x99, 0xbb, 0x0a, 0xe9, 0xbb, 0x8e, 0x0a, 0xe5, 0x89, 0x8a, 0x0a, - 0xe9, 0x91, 0xbd, 0x0a, 0xe5, 0x8b, 0x92, 0x0a, 0xe9, 0x80, 0x83, 0x0a, - 0xe9, 0x9a, 0x9c, 0x0a, 0xe6, 0xb0, 0xa8, 0x0a, 0xe9, 0x83, 0xad, 0x0a, - 0xe5, 0xb3, 0xb0, 0x0a, 0xe5, 0xb9, 0xa3, 0x0a, 0xe6, 0xb8, 0xaf, 0x0a, - 0xe4, 0xbc, 0x8f, 0x0a, 0xe8, 0xbb, 0x8c, 0x0a, 0xe7, 0x95, 0x9d, 0x0a, - 0xe7, 0x95, 0xa2, 0x0a, 0xe6, 0x93, 0xa6, 0x0a, 0xe8, 0x8e, 0xab, 0x0a, - 0xe5, 0x88, 0xba, 0x0a, 0xe6, 0xb5, 0xaa, 0x0a, 0xe7, 0xa7, 0x98, 0x0a, - 0xe6, 0x8f, 0xb4, 0x0a, 0xe6, 0xa0, 0xaa, 0x0a, 0xe5, 0x81, 0xa5, 0x0a, - 0xe5, 0x94, 0xae, 0x0a, 0xe8, 0x82, 0xa1, 0x0a, 0xe5, 0xb3, 0xb6, 0x0a, - 0xe7, 0x94, 0x98, 0x0a, 0xe6, 0xb3, 0xa1, 0x0a, 0xe7, 0x9d, 0xa1, 0x0a, - 0xe7, 0xab, 0xa5, 0x0a, 0xe9, 0x91, 0x84, 0x0a, 0xe6, 0xb9, 0xaf, 0x0a, - 0xe9, 0x96, 0xa5, 0x0a, 0xe4, 0xbc, 0x91, 0x0a, 0xe5, 0x8c, 0xaf, 0x0a, - 0xe8, 0x88, 0x8d, 0x0a, 0xe7, 0x89, 0xa7, 0x0a, 0xe7, 0xb9, 0x9e, 0x0a, - 0xe7, 0x82, 0xb8, 0x0a, 0xe5, 0x93, 0xb2, 0x0a, 0xe7, 0xa3, 0xb7, 0x0a, - 0xe7, 0xb8, 0xbe, 0x0a, 0xe6, 0x9c, 0x8b, 0x0a, 0xe6, 0xb7, 0xa1, 0x0a, - 0xe5, 0xb0, 0x96, 0x0a, 0xe5, 0x95, 0x9f, 0x0a, 0xe9, 0x99, 0xb7, 0x0a, - 0xe6, 0x9f, 0xb4, 0x0a, 0xe5, 0x91, 0x88, 0x0a, 0xe5, 0xbe, 0x92, 0x0a, - 0xe9, 0xa1, 0x8f, 0x0a, 0xe6, 0xb7, 0x9a, 0x0a, 0xe7, 0xa8, 0x8d, 0x0a, - 0xe5, 0xbf, 0x98, 0x0a, 0xe6, 0xb3, 0xb5, 0x0a, 0xe8, 0x97, 0x8d, 0x0a, - 0xe6, 0x8b, 0x96, 0x0a, 0xe6, 0xb4, 0x9e, 0x0a, 0xe6, 0x8e, 0x88, 0x0a, - 0xe9, 0x8f, 0xa1, 0x0a, 0xe8, 0xbe, 0x9b, 0x0a, 0xe5, 0xa3, 0xaf, 0x0a, - 0xe9, 0x8b, 0x92, 0x0a, 0xe8, 0xb2, 0xa7, 0x0a, 0xe8, 0x99, 0x9b, 0x0a, - 0xe5, 0xbd, 0x8e, 0x0a, 0xe6, 0x91, 0xa9, 0x0a, 0xe6, 0xb3, 0xb0, 0x0a, - 0xe5, 0xb9, 0xbc, 0x0a, 0xe5, 0xbb, 0xb7, 0x0a, 0xe5, 0xb0, 0x8a, 0x0a, - 0xe7, 0xaa, 0x97, 0x0a, 0xe7, 0xb6, 0xb1, 0x0a, 0xe5, 0xbc, 0x84, 0x0a, - 0xe9, 0x9a, 0xb8, 0x0a, 0xe7, 0x96, 0x91, 0x0a, 0xe6, 0xb0, 0x8f, 0x0a, - 0xe5, 0xae, 0xae, 0x0a, 0xe5, 0xa7, 0x90, 0x0a, 0xe9, 0x9c, 0x87, 0x0a, - 0xe7, 0x91, 0x9e, 0x0a, 0xe6, 0x80, 0xaa, 0x0a, 0xe5, 0xb0, 0xa4, 0x0a, - 0xe7, 0x90, 0xb4, 0x0a, 0xe5, 0xbe, 0xaa, 0x0a, 0xe6, 0x8f, 0x8f, 0x0a, - 0xe8, 0x86, 0x9c, 0x0a, 0xe9, 0x81, 0x95, 0x0a, 0xe5, 0xa4, 0xbe, 0x0a, - 0xe8, 0x85, 0xb0, 0x0a, 0xe7, 0xb7, 0xa3, 0x0a, 0xe7, 0x8f, 0xa0, 0x0a, - 0xe7, 0xaa, 0xae, 0x0a, 0xe6, 0xa3, 0xae, 0x0a, 0xe6, 0x9e, 0x9d, 0x0a, - 0xe7, 0xab, 0xb9, 0x0a, 0xe6, 0xba, 0x9d, 0x0a, 0xe5, 0x82, 0xac, 0x0a, - 0xe7, 0xb9, 0xa9, 0x0a, 0xe6, 0x86, 0xb6, 0x0a, 0xe9, 0x82, 0xa6, 0x0a, - 0xe5, 0x89, 0xa9, 0x0a, 0xe5, 0xb9, 0xb8, 0x0a, 0xe6, 0xbc, 0xbf, 0x0a, - 0xe6, 0xac, 0x84, 0x0a, 0xe6, 0x93, 0x81, 0x0a, 0xe7, 0x89, 0x99, 0x0a, - 0xe8, 0xb2, 0xaf, 0x0a, 0xe7, 0xa6, 0xae, 0x0a, 0xe6, 0xbf, 0xbe, 0x0a, - 0xe9, 0x88, 0x89, 0x0a, 0xe7, 0xb4, 0x8b, 0x0a, 0xe7, 0xbd, 0xb7, 0x0a, - 0xe6, 0x8b, 0x8d, 0x0a, 0xe5, 0x92, 0xb1, 0x0a, 0xe5, 0x96, 0x8a, 0x0a, - 0xe8, 0xa2, 0x96, 0x0a, 0xe5, 0x9f, 0x83, 0x0a, 0xe5, 0x8b, 0xa4, 0x0a, - 0xe7, 0xbd, 0xb0, 0x0a, 0xe7, 0x84, 0xa6, 0x0a, 0xe6, 0xbd, 0x9b, 0x0a, - 0xe4, 0xbc, 0x8d, 0x0a, 0xe5, 0xa2, 0xa8, 0x0a, 0xe6, 0xac, 0xb2, 0x0a, - 0xe7, 0xb8, 0xab, 0x0a, 0xe5, 0xa7, 0x93, 0x0a, 0xe5, 0x88, 0x8a, 0x0a, - 0xe9, 0xa3, 0xbd, 0x0a, 0xe4, 0xbb, 0xbf, 0x0a, 0xe7, 0x8d, 0x8e, 0x0a, - 0xe9, 0x8b, 0x81, 0x0a, 0xe9, 0xac, 0xbc, 0x0a, 0xe9, 0xba, 0x97, 0x0a, - 0xe8, 0xb7, 0xa8, 0x0a, 0xe9, 0xbb, 0x98, 0x0a, 0xe6, 0x8c, 0x96, 0x0a, - 0xe9, 0x8f, 0x88, 0x0a, 0xe6, 0x8e, 0x83, 0x0a, 0xe5, 0x96, 0x9d, 0x0a, - 0xe8, 0xa2, 0x8b, 0x0a, 0xe7, 0x82, 0xad, 0x0a, 0xe6, 0xb1, 0xa1, 0x0a, - 0xe5, 0xb9, 0x95, 0x0a, 0xe8, 0xab, 0xb8, 0x0a, 0xe5, 0xbc, 0xa7, 0x0a, - 0xe5, 0x8b, 0xb5, 0x0a, 0xe6, 0xa2, 0x85, 0x0a, 0xe5, 0xa5, 0xb6, 0x0a, - 0xe6, 0xbd, 0x94, 0x0a, 0xe7, 0x81, 0xbd, 0x0a, 0xe8, 0x88, 0x9f, 0x0a, - 0xe9, 0x91, 0x91, 0x0a, 0xe8, 0x8b, 0xaf, 0x0a, 0xe8, 0xa8, 0x9f, 0x0a, - 0xe6, 0x8a, 0xb1, 0x0a, 0xe6, 0xaf, 0x80, 0x0a, 0xe6, 0x87, 0x82, 0x0a, - 0xe5, 0xaf, 0x92, 0x0a, 0xe6, 0x99, 0xba, 0x0a, 0xe5, 0x9f, 0x94, 0x0a, - 0xe5, 0xaf, 0x84, 0x0a, 0xe5, 0xb1, 0x86, 0x0a, 0xe8, 0xba, 0x8d, 0x0a, - 0xe6, 0xb8, 0xa1, 0x0a, 0xe6, 0x8c, 0x91, 0x0a, 0xe4, 0xb8, 0xb9, 0x0a, - 0xe8, 0x89, 0xb1, 0x0a, 0xe8, 0xb2, 0x9d, 0x0a, 0xe7, 0xa2, 0xb0, 0x0a, - 0xe6, 0x8b, 0x94, 0x0a, 0xe7, 0x88, 0xb9, 0x0a, 0xe6, 0x88, 0xb4, 0x0a, - 0xe7, 0xa2, 0xbc, 0x0a, 0xe5, 0xa4, 0xa2, 0x0a, 0xe8, 0x8a, 0xbd, 0x0a, - 0xe7, 0x86, 0x94, 0x0a, 0xe8, 0xb5, 0xa4, 0x0a, 0xe6, 0xbc, 0x81, 0x0a, - 0xe5, 0x93, 0xad, 0x0a, 0xe6, 0x95, 0xac, 0x0a, 0xe9, 0xa1, 0x86, 0x0a, - 0xe5, 0xa5, 0x94, 0x0a, 0xe9, 0x89, 0x9b, 0x0a, 0xe4, 0xbb, 0xb2, 0x0a, - 0xe8, 0x99, 0x8e, 0x0a, 0xe7, 0xa8, 0x80, 0x0a, 0xe5, 0xa6, 0xb9, 0x0a, - 0xe4, 0xb9, 0x8f, 0x0a, 0xe7, 0x8f, 0x8d, 0x0a, 0xe7, 0x94, 0xb3, 0x0a, - 0xe6, 0xa1, 0x8c, 0x0a, 0xe9, 0x81, 0xb5, 0x0a, 0xe5, 0x85, 0x81, 0x0a, - 0xe9, 0x9a, 0x86, 0x0a, 0xe8, 0x9e, 0xba, 0x0a, 0xe5, 0x80, 0x89, 0x0a, - 0xe9, 0xad, 0x8f, 0x0a, 0xe9, 0x8a, 0xb3, 0x0a, 0xe6, 0x9b, 0x89, 0x0a, - 0xe6, 0xb0, 0xae, 0x0a, 0xe5, 0x85, 0xbc, 0x0a, 0xe9, 0x9a, 0xb1, 0x0a, - 0xe7, 0xa4, 0x99, 0x0a, 0xe8, 0xb5, 0xab, 0x0a, 0xe6, 0x92, 0xa5, 0x0a, - 0xe5, 0xbf, 0xa0, 0x0a, 0xe8, 0x82, 0x85, 0x0a, 0xe7, 0xbc, 0xb8, 0x0a, - 0xe7, 0x89, 0xbd, 0x0a, 0xe6, 0x90, 0xb6, 0x0a, 0xe5, 0x8d, 0x9a, 0x0a, - 0xe5, 0xb7, 0xa7, 0x0a, 0xe6, 0xae, 0xbc, 0x0a, 0xe5, 0x85, 0x84, 0x0a, - 0xe6, 0x9d, 0x9c, 0x0a, 0xe8, 0xa8, 0x8a, 0x0a, 0xe8, 0xaa, 0xa0, 0x0a, - 0xe7, 0xa2, 0xa7, 0x0a, 0xe7, 0xa5, 0xa5, 0x0a, 0xe6, 0x9f, 0xaf, 0x0a, - 0xe9, 0xa0, 0x81, 0x0a, 0xe5, 0xb7, 0xa1, 0x0a, 0xe7, 0x9f, 0xa9, 0x0a, - 0xe6, 0x82, 0xb2, 0x0a, 0xe7, 0x81, 0x8c, 0x0a, 0xe9, 0xbd, 0xa1, 0x0a, - 0xe5, 0x80, 0xab, 0x0a, 0xe7, 0xa5, 0xa8, 0x0a, 0xe5, 0xb0, 0x8b, 0x0a, - 0xe6, 0xa1, 0x82, 0x0a, 0xe9, 0x8b, 0xaa, 0x0a, 0xe8, 0x81, 0x96, 0x0a, - 0xe6, 0x81, 0x90, 0x0a, 0xe6, 0x81, 0xb0, 0x0a, 0xe9, 0x84, 0xad, 0x0a, - 0xe8, 0xb6, 0xa3, 0x0a, 0xe6, 0x8a, 0xac, 0x0a, 0xe8, 0x8d, 0x92, 0x0a, - 0xe9, 0xa8, 0xb0, 0x0a, 0xe8, 0xb2, 0xbc, 0x0a, 0xe6, 0x9f, 0x94, 0x0a, - 0xe6, 0xbb, 0xb4, 0x0a, 0xe7, 0x8c, 0x9b, 0x0a, 0xe9, 0x97, 0x8a, 0x0a, - 0xe8, 0xbc, 0x9b, 0x0a, 0xe5, 0xa6, 0xbb, 0x0a, 0xe5, 0xa1, 0xab, 0x0a, - 0xe6, 0x92, 0xa4, 0x0a, 0xe5, 0x84, 0xb2, 0x0a, 0xe7, 0xb0, 0xbd, 0x0a, - 0xe9, 0xac, 0xa7, 0x0a, 0xe6, 0x93, 0xbe, 0x0a, 0xe7, 0xb4, 0xab, 0x0a, - 0xe7, 0xa0, 0x82, 0x0a, 0xe9, 0x81, 0x9e, 0x0a, 0xe6, 0x88, 0xb2, 0x0a, - 0xe5, 0x90, 0x8a, 0x0a, 0xe9, 0x99, 0xb6, 0x0a, 0xe4, 0xbc, 0x90, 0x0a, - 0xe9, 0xa4, 0xb5, 0x0a, 0xe7, 0x99, 0x82, 0x0a, 0xe7, 0x93, 0xb6, 0x0a, - 0xe5, 0xa9, 0x86, 0x0a, 0xe6, 0x92, 0xab, 0x0a, 0xe8, 0x87, 0x82, 0x0a, - 0xe6, 0x91, 0xb8, 0x0a, 0xe5, 0xbf, 0x8d, 0x0a, 0xe8, 0x9d, 0xa6, 0x0a, - 0xe8, 0xa0, 0x9f, 0x0a, 0xe9, 0x84, 0xb0, 0x0a, 0xe8, 0x83, 0xb8, 0x0a, - 0xe9, 0x9e, 0x8f, 0x0a, 0xe6, 0x93, 0xa0, 0x0a, 0xe5, 0x81, 0xb6, 0x0a, - 0xe6, 0xa3, 0x84, 0x0a, 0xe6, 0xa7, 0xbd, 0x0a, 0xe5, 0x8b, 0x81, 0x0a, - 0xe4, 0xb9, 0xb3, 0x0a, 0xe9, 0x84, 0xa7, 0x0a, 0xe5, 0x90, 0x89, 0x0a, - 0xe4, 0xbb, 0x81, 0x0a, 0xe7, 0x88, 0x9b, 0x0a, 0xe7, 0xa3, 0x9a, 0x0a, - 0xe7, 0xa7, 0x9f, 0x0a, 0xe7, 0x83, 0x8f, 0x0a, 0xe8, 0x89, 0xa6, 0x0a, - 0xe4, 0xbc, 0xb4, 0x0a, 0xe7, 0x93, 0x9c, 0x0a, 0xe6, 0xb7, 0xba, 0x0a, - 0xe4, 0xb8, 0x99, 0x0a, 0xe6, 0x9a, 0xab, 0x0a, 0xe7, 0x87, 0xa5, 0x0a, - 0xe6, 0xa9, 0xa1, 0x0a, 0xe6, 0x9f, 0xb3, 0x0a, 0xe8, 0xbf, 0xb7, 0x0a, - 0xe6, 0x9a, 0x96, 0x0a, 0xe7, 0x89, 0x8c, 0x0a, 0xe7, 0xa7, 0xa7, 0x0a, - 0xe8, 0x86, 0xbd, 0x0a, 0xe8, 0xa9, 0xb3, 0x0a, 0xe7, 0xb0, 0xa7, 0x0a, - 0xe8, 0xb8, 0x8f, 0x0a, 0xe7, 0x93, 0xb7, 0x0a, 0xe8, 0xad, 0x9c, 0x0a, - 0xe5, 0x91, 0x86, 0x0a, 0xe8, 0xb3, 0x93, 0x0a, 0xe7, 0xb3, 0x8a, 0x0a, - 0xe6, 0xb4, 0x9b, 0x0a, 0xe8, 0xbc, 0x9d, 0x0a, 0xe6, 0x86, 0xa4, 0x0a, - 0xe7, 0xab, 0xb6, 0x0a, 0xe9, 0x9a, 0x99, 0x0a, 0xe6, 0x80, 0x92, 0x0a, - 0xe7, 0xb2, 0x98, 0x0a, 0xe4, 0xb9, 0x83, 0x0a, 0xe7, 0xb7, 0x92, 0x0a, - 0xe8, 0x82, 0xa9, 0x0a, 0xe7, 0xb1, 0x8d, 0x0a, 0xe6, 0x95, 0x8f, 0x0a, - 0xe5, 0xa1, 0x97, 0x0a, 0xe7, 0x86, 0x99, 0x0a, 0xe7, 0x9a, 0x86, 0x0a, - 0xe5, 0x81, 0xb5, 0x0a, 0xe6, 0x87, 0xb8, 0x0a, 0xe6, 0x8e, 0x98, 0x0a, - 0xe4, 0xba, 0xab, 0x0a, 0xe7, 0xb3, 0xbe, 0x0a, 0xe9, 0x86, 0x92, 0x0a, - 0xe7, 0x8b, 0x82, 0x0a, 0xe9, 0x8e, 0x96, 0x0a, 0xe6, 0xb7, 0x80, 0x0a, - 0xe6, 0x81, 0xa8, 0x0a, 0xe7, 0x89, 0xb2, 0x0a, 0xe9, 0x9c, 0xb8, 0x0a, - 0xe7, 0x88, 0xac, 0x0a, 0xe8, 0xb3, 0x9e, 0x0a, 0xe9, 0x80, 0x86, 0x0a, - 0xe7, 0x8e, 0xa9, 0x0a, 0xe9, 0x99, 0xb5, 0x0a, 0xe7, 0xa5, 0x9d, 0x0a, - 0xe7, 0xa7, 0x92, 0x0a, 0xe6, 0xb5, 0x99, 0x0a, 0xe8, 0xb2, 0x8c, 0x0a, - 0xe5, 0xbd, 0xb9, 0x0a, 0xe5, 0xbd, 0xbc, 0x0a, 0xe6, 0x82, 0x89, 0x0a, - 0xe9, 0xb4, 0xa8, 0x0a, 0xe8, 0xb6, 0xa8, 0x0a, 0xe9, 0xb3, 0xb3, 0x0a, - 0xe6, 0x99, 0xa8, 0x0a, 0xe7, 0x95, 0x9c, 0x0a, 0xe8, 0xbc, 0xa9, 0x0a, - 0xe7, 0xa7, 0xa9, 0x0a, 0xe5, 0x8d, 0xb5, 0x0a, 0xe7, 0xbd, 0xb2, 0x0a, - 0xe6, 0xa2, 0xaf, 0x0a, 0xe7, 0x82, 0x8e, 0x0a, 0xe7, 0x81, 0x98, 0x0a, - 0xe6, 0xa3, 0x8b, 0x0a, 0xe9, 0xa9, 0x85, 0x0a, 0xe7, 0xaf, 0xa9, 0x0a, - 0xe5, 0xb3, 0xbd, 0x0a, 0xe5, 0x86, 0x92, 0x0a, 0xe5, 0x95, 0xa5, 0x0a, - 0xe5, 0xa3, 0xbd, 0x0a, 0xe8, 0xad, 0xaf, 0x0a, 0xe6, 0xb5, 0xb8, 0x0a, - 0xe6, 0xb3, 0x89, 0x0a, 0xe5, 0xb8, 0xbd, 0x0a, 0xe9, 0x81, 0xb2, 0x0a, - 0xe7, 0x9f, 0xbd, 0x0a, 0xe7, 0x96, 0x86, 0x0a, 0xe8, 0xb2, 0xb8, 0x0a, - 0xe6, 0xbc, 0x8f, 0x0a, 0xe7, 0xa8, 0xbf, 0x0a, 0xe5, 0x86, 0xa0, 0x0a, - 0xe5, 0xab, 0xa9, 0x0a, 0xe8, 0x84, 0x85, 0x0a, 0xe8, 0x8a, 0xaf, 0x0a, - 0xe7, 0x89, 0xa2, 0x0a, 0xe5, 0x8f, 0x9b, 0x0a, 0xe8, 0x9d, 0x95, 0x0a, - 0xe5, 0xa5, 0xa7, 0x0a, 0xe9, 0xb3, 0xb4, 0x0a, 0xe5, 0xb6, 0xba, 0x0a, - 0xe7, 0xbe, 0x8a, 0x0a, 0xe6, 0x86, 0x91, 0x0a, 0xe4, 0xb8, 0xb2, 0x0a, - 0xe5, 0xa1, 0x98, 0x0a, 0xe7, 0xb9, 0xaa, 0x0a, 0xe9, 0x85, 0xb5, 0x0a, - 0xe8, 0x9e, 0x8d, 0x0a, 0xe7, 0x9b, 0x86, 0x0a, 0xe9, 0x8c, 0xab, 0x0a, - 0xe5, 0xbb, 0x9f, 0x0a, 0xe7, 0xb1, 0x8c, 0x0a, 0xe5, 0x87, 0x8d, 0x0a, - 0xe8, 0xbc, 0x94, 0x0a, 0xe6, 0x94, 0x9d, 0x0a, 0xe8, 0xa5, 0xb2, 0x0a, - 0xe7, 0xad, 0x8b, 0x0a, 0xe6, 0x8b, 0x92, 0x0a, 0xe5, 0x83, 0x9a, 0x0a, - 0xe6, 0x97, 0xb1, 0x0a, 0xe9, 0x89, 0x80, 0x0a, 0xe9, 0xb3, 0xa5, 0x0a, - 0xe6, 0xbc, 0x86, 0x0a, 0xe6, 0xb2, 0x88, 0x0a, 0xe7, 0x9c, 0x89, 0x0a, - 0xe7, 0x96, 0x8f, 0x0a, 0xe6, 0xb7, 0xbb, 0x0a, 0xe6, 0xa3, 0x92, 0x0a, - 0xe7, 0xa9, 0x97, 0x0a, 0xe7, 0xa1, 0x9d, 0x0a, 0xe9, 0x9f, 0x93, 0x0a, - 0xe9, 0x80, 0xbc, 0x0a, 0xe6, 0x89, 0xad, 0x0a, 0xe5, 0x83, 0x91, 0x0a, - 0xe6, 0xb6, 0xbc, 0x0a, 0xe6, 0x8c, 0xba, 0x0a, 0xe7, 0xa2, 0x97, 0x0a, - 0xe6, 0xa0, 0xbd, 0x0a, 0xe7, 0x82, 0x92, 0x0a, 0xe6, 0x9d, 0xaf, 0x0a, - 0xe6, 0x82, 0xa3, 0x0a, 0xe9, 0xa4, 0xbe, 0x0a, 0xe5, 0x8b, 0xb8, 0x0a, - 0xe8, 0xb1, 0xaa, 0x0a, 0xe9, 0x81, 0xbc, 0x0a, 0xe5, 0x8b, 0x83, 0x0a, - 0xe9, 0xb4, 0xbb, 0x0a, 0xe6, 0x97, 0xa6, 0x0a, 0xe5, 0x90, 0x8f, 0x0a, - 0xe6, 0x8b, 0x9c, 0x0a, 0xe7, 0x8b, 0x97, 0x0a, 0xe5, 0x9f, 0x8b, 0x0a, - 0xe8, 0xbc, 0xa5, 0x0a, 0xe6, 0x8e, 0xa9, 0x0a, 0xe9, 0xa3, 0xb2, 0x0a, - 0xe6, 0x90, 0xac, 0x0a, 0xe7, 0xbd, 0xb5, 0x0a, 0xe8, 0xbe, 0xad, 0x0a, - 0xe5, 0x8b, 0xbe, 0x0a, 0xe6, 0x89, 0xa3, 0x0a, 0xe4, 0xbc, 0xb0, 0x0a, - 0xe8, 0x94, 0xa3, 0x0a, 0xe7, 0xb5, 0xa8, 0x0a, 0xe9, 0x9c, 0xa7, 0x0a, - 0xe4, 0xb8, 0x88, 0x0a, 0xe6, 0x9c, 0xb5, 0x0a, 0xe5, 0xa7, 0x86, 0x0a, - 0xe6, 0x93, 0xac, 0x0a, 0xe5, 0xae, 0x87, 0x0a, 0xe8, 0xbc, 0xaf, 0x0a, - 0xe9, 0x99, 0x9d, 0x0a, 0xe9, 0x9b, 0x95, 0x0a, 0xe5, 0x84, 0x9f, 0x0a, - 0xe8, 0x93, 0x84, 0x0a, 0xe5, 0xb4, 0x87, 0x0a, 0xe5, 0x89, 0xaa, 0x0a, - 0xe5, 0x80, 0xa1, 0x0a, 0xe5, 0xbb, 0xb3, 0x0a, 0xe5, 0x92, 0xac, 0x0a, - 0xe9, 0xa7, 0x9b, 0x0a, 0xe8, 0x96, 0xaf, 0x0a, 0xe5, 0x88, 0xb7, 0x0a, - 0xe6, 0x96, 0xa5, 0x0a, 0xe7, 0x95, 0xaa, 0x0a, 0xe8, 0xb3, 0xa6, 0x0a, - 0xe5, 0xa5, 0x89, 0x0a, 0xe4, 0xbd, 0x9b, 0x0a, 0xe6, 0xbe, 0x86, 0x0a, - 0xe6, 0xbc, 0xab, 0x0a, 0xe6, 0x9b, 0xbc, 0x0a, 0xe6, 0x89, 0x87, 0x0a, - 0xe9, 0x88, 0xa3, 0x0a, 0xe6, 0xa1, 0x83, 0x0a, 0xe6, 0x89, 0xb6, 0x0a, - 0xe4, 0xbb, 0x94, 0x0a, 0xe8, 0xbf, 0x94, 0x0a, 0xe4, 0xbf, 0x97, 0x0a, - 0xe8, 0x99, 0xa7, 0x0a, 0xe8, 0x85, 0x94, 0x0a, 0xe9, 0x9e, 0x8b, 0x0a, - 0xe6, 0xa3, 0xb1, 0x0a, 0xe8, 0xa6, 0x86, 0x0a, 0xe6, 0xa1, 0x86, 0x0a, - 0xe6, 0x82, 0x84, 0x0a, 0xe5, 0x8f, 0x94, 0x0a, 0xe6, 0x92, 0x9e, 0x0a, - 0xe9, 0xa8, 0x99, 0x0a, 0xe5, 0x8b, 0x98, 0x0a, 0xe6, 0x97, 0xba, 0x0a, - 0xe6, 0xb2, 0xb8, 0x0a, 0xe5, 0xad, 0xa4, 0x0a, 0xe5, 0x90, 0x90, 0x0a, - 0xe5, 0xad, 0x9f, 0x0a, 0xe6, 0xb8, 0xa0, 0x0a, 0xe5, 0xb1, 0x88, 0x0a, - 0xe7, 0x96, 0xbe, 0x0a, 0xe5, 0xa6, 0x99, 0x0a, 0xe6, 0x83, 0x9c, 0x0a, - 0xe4, 0xbb, 0xb0, 0x0a, 0xe7, 0x8b, 0xa0, 0x0a, 0xe8, 0x84, 0xb9, 0x0a, - 0xe8, 0xab, 0xa7, 0x0a, 0xe6, 0x8b, 0x8b, 0x0a, 0xe9, 0xbb, 0xb4, 0x0a, - 0xe6, 0xa1, 0x91, 0x0a, 0xe5, 0xb4, 0x97, 0x0a, 0xe5, 0x98, 0x9b, 0x0a, - 0xe8, 0xa1, 0xb0, 0x0a, 0xe7, 0x9b, 0x9c, 0x0a, 0xe6, 0xbb, 0xb2, 0x0a, - 0xe8, 0x87, 0x9f, 0x0a, 0xe8, 0xb3, 0xb4, 0x0a, 0xe6, 0xb9, 0xa7, 0x0a, - 0xe7, 0x94, 0x9c, 0x0a, 0xe6, 0x9b, 0xb9, 0x0a, 0xe9, 0x96, 0xb1, 0x0a, - 0xe8, 0x82, 0x8c, 0x0a, 0xe5, 0x93, 0xa9, 0x0a, 0xe5, 0x8e, 0xb2, 0x0a, - 0xe7, 0x83, 0xb4, 0x0a, 0xe7, 0xb7, 0xaf, 0x0a, 0xe6, 0xaf, 0x85, 0x0a, - 0xe6, 0x98, 0xa8, 0x0a, 0xe5, 0x81, 0xbd, 0x0a, 0xe7, 0x97, 0x87, 0x0a, - 0xe7, 0x85, 0xae, 0x0a, 0xe5, 0x98, 0x86, 0x0a, 0xe9, 0x87, 0x98, 0x0a, - 0xe6, 0x90, 0xad, 0x0a, 0xe8, 0x8e, 0x96, 0x0a, 0xe7, 0xb1, 0xa0, 0x0a, - 0xe9, 0x85, 0xb7, 0x0a, 0xe5, 0x81, 0xb7, 0x0a, 0xe5, 0xbc, 0x93, 0x0a, - 0xe9, 0x8c, 0x90, 0x0a, 0xe6, 0x81, 0x86, 0x0a, 0xe5, 0x82, 0x91, 0x0a, - 0xe5, 0x9d, 0x91, 0x0a, 0xe9, 0xbc, 0xbb, 0x0a, 0xe7, 0xbf, 0xbc, 0x0a, - 0xe7, 0xb6, 0xb8, 0x0a, 0xe6, 0x95, 0x98, 0x0a, 0xe7, 0x8d, 0x84, 0x0a, - 0xe9, 0x80, 0xae, 0x0a, 0xe7, 0xbd, 0x90, 0x0a, 0xe7, 0xb5, 0xa1, 0x0a, - 0xe6, 0xa3, 0x9a, 0x0a, 0xe6, 0x8a, 0x91, 0x0a, 0xe8, 0x86, 0xa8, 0x0a, - 0xe8, 0x94, 0xac, 0x0a, 0xe5, 0xaf, 0xba, 0x0a, 0xe9, 0xa9, 0x9f, 0x0a, - 0xe7, 0xa9, 0x86, 0x0a, 0xe5, 0x86, 0xb6, 0x0a, 0xe6, 0x9e, 0xaf, 0x0a, - 0xe5, 0x86, 0x8a, 0x0a, 0xe5, 0xb1, 0x8d, 0x0a, 0xe5, 0x87, 0xb8, 0x0a, - 0xe7, 0xb4, 0xb3, 0x0a, 0xe5, 0x9d, 0xaf, 0x0a, 0xe7, 0x8a, 0xa7, 0x0a, - 0xe7, 0x84, 0xb0, 0x0a, 0xe8, 0xbd, 0x9f, 0x0a, 0xe6, 0xac, 0xa3, 0x0a, - 0xe6, 0x99, 0x89, 0x0a, 0xe7, 0x98, 0xa6, 0x0a, 0xe7, 0xa6, 0xa6, 0x0a, - 0xe9, 0x8c, 0xa0, 0x0a, 0xe9, 0x8c, 0xa6, 0x0a, 0xe5, 0x96, 0xaa, 0x0a, - 0xe6, 0x97, 0xac, 0x0a, 0xe9, 0x8d, 0x9b, 0x0a, 0xe5, 0xa3, 0x9f, 0x0a, - 0xe6, 0x90, 0x9c, 0x0a, 0xe6, 0x92, 0xb2, 0x0a, 0xe9, 0x82, 0x80, 0x0a, - 0xe4, 0xba, 0xad, 0x0a, 0xe9, 0x85, 0xaf, 0x0a, 0xe9, 0x82, 0x81, 0x0a, - 0xe8, 0x88, 0x92, 0x0a, 0xe8, 0x84, 0x86, 0x0a, 0xe9, 0x85, 0xb6, 0x0a, - 0xe9, 0x96, 0x92, 0x0a, 0xe6, 0x86, 0x82, 0x0a, 0xe9, 0x85, 0x9a, 0x0a, - 0xe9, 0xa0, 0x91, 0x0a, 0xe7, 0xbe, 0xbd, 0x0a, 0xe6, 0xbc, 0xb2, 0x0a, - 0xe5, 0x8d, 0xb8, 0x0a, 0xe4, 0xbb, 0x97, 0x0a, 0xe9, 0x99, 0xaa, 0x0a, - 0xe9, 0x97, 0xa2, 0x0a, 0xe6, 0x87, 0xb2, 0x0a, 0xe6, 0x9d, 0xad, 0x0a, - 0xe5, 0xa7, 0x9a, 0x0a, 0xe8, 0x82, 0x9a, 0x0a, 0xe6, 0x8d, 0x89, 0x0a, - 0xe9, 0xa3, 0x84, 0x0a, 0xe6, 0xbc, 0x82, 0x0a, 0xe6, 0x98, 0x86, 0x0a, - 0xe6, 0xac, 0xba, 0x0a, 0xe5, 0x90, 0xbe, 0x0a, 0xe9, 0x83, 0x8e, 0x0a, - 0xe7, 0x83, 0xb7, 0x0a, 0xe6, 0xb1, 0x81, 0x0a, 0xe5, 0x91, 0xb5, 0x0a, - 0xe9, 0xa3, 0xbe, 0x0a, 0xe8, 0x95, 0xad, 0x0a, 0xe9, 0x9b, 0x85, 0x0a, - 0xe9, 0x83, 0xb5, 0x0a, 0xe9, 0x81, 0xb7, 0x0a, 0xe7, 0x87, 0x95, 0x0a, - 0xe6, 0x92, 0x92, 0x0a, 0xe5, 0xa7, 0xbb, 0x0a, 0xe8, 0xb5, 0xb4, 0x0a, - 0xe5, 0xae, 0xb4, 0x0a, 0xe7, 0x85, 0xa9, 0x0a, 0xe5, 0x82, 0xb5, 0x0a, - 0xe5, 0xb8, 0xb3, 0x0a, 0xe6, 0x96, 0x91, 0x0a, 0xe9, 0x88, 0xb4, 0x0a, - 0xe6, 0x97, 0xa8, 0x0a, 0xe9, 0x86, 0x87, 0x0a, 0xe8, 0x91, 0xa3, 0x0a, - 0xe9, 0xa4, 0x85, 0x0a, 0xe9, 0x9b, 0x9b, 0x0a, 0xe5, 0xa7, 0xbf, 0x0a, - 0xe6, 0x8b, 0x8c, 0x0a, 0xe5, 0x82, 0x85, 0x0a, 0xe8, 0x85, 0xb9, 0x0a, - 0xe5, 0xa6, 0xa5, 0x0a, 0xe6, 0x8f, 0x89, 0x0a, 0xe8, 0xb3, 0xa2, 0x0a, - 0xe6, 0x8b, 0x86, 0x0a, 0xe6, 0xad, 0xaa, 0x0a, 0xe8, 0x91, 0xa1, 0x0a, - 0xe8, 0x83, 0xba, 0x0a, 0xe4, 0xb8, 0x9f, 0x0a, 0xe6, 0xb5, 0xa9, 0x0a, - 0xe5, 0xbe, 0xbd, 0x0a, 0xe6, 0x98, 0x82, 0x0a, 0xe5, 0xa2, 0x8a, 0x0a, - 0xe6, 0x93, 0x8b, 0x0a, 0xe8, 0xa6, 0xbd, 0x0a, 0xe8, 0xb2, 0xaa, 0x0a, - 0xe6, 0x85, 0xb0, 0x0a, 0xe7, 0xb9, 0xb3, 0x0a, 0xe6, 0xb1, 0xaa, 0x0a, - 0xe6, 0x85, 0x8c, 0x0a, 0xe9, 0xa6, 0xae, 0x0a, 0xe8, 0xab, 0xbe, 0x0a, - 0xe5, 0xa7, 0x9c, 0x0a, 0xe8, 0xaa, 0xbc, 0x0a, 0xe5, 0x85, 0x87, 0x0a, - 0xe5, 0x8a, 0xa3, 0x0a, 0xe8, 0xaa, 0xa3, 0x0a, 0xe8, 0x80, 0x80, 0x0a, - 0xe6, 0x98, 0x8f, 0x0a, 0xe8, 0xba, 0xba, 0x0a, 0xe7, 0x9b, 0x88, 0x0a, - 0xe9, 0xa8, 0x8e, 0x0a, 0xe5, 0x96, 0xac, 0x0a, 0xe6, 0xba, 0xaa, 0x0a, - 0xe5, 0x8f, 0xa2, 0x0a, 0xe7, 0x9b, 0xa7, 0x0a, 0xe6, 0x8a, 0xb9, 0x0a, - 0xe6, 0x82, 0xb6, 0x0a, 0xe8, 0xab, 0xae, 0x0a, 0xe5, 0x88, 0xae, 0x0a, - 0xe9, 0xa7, 0x95, 0x0a, 0xe7, 0xba, 0x9c, 0x0a, 0xe6, 0x82, 0x9f, 0x0a, - 0xe6, 0x91, 0x98, 0x0a, 0xe9, 0x89, 0xba, 0x0a, 0xe6, 0x93, 0xb2, 0x0a, - 0xe9, 0xa0, 0x97, 0x0a, 0xe5, 0xb9, 0xbb, 0x0a, 0xe6, 0x9f, 0x84, 0x0a, - 0xe6, 0x83, 0xa0, 0x0a, 0xe6, 0x85, 0x98, 0x0a, 0xe4, 0xbd, 0xb3, 0x0a, - 0xe4, 0xbb, 0x87, 0x0a, 0xe8, 0x87, 0x98, 0x0a, 0xe7, 0xaa, 0xa9, 0x0a, - 0xe6, 0xbb, 0x8c, 0x0a, 0xe5, 0x8a, 0x8d, 0x0a, 0xe7, 0x9e, 0xa7, 0x0a, - 0xe5, 0xa0, 0xa1, 0x0a, 0xe6, 0xbd, 0x91, 0x0a, 0xe8, 0x94, 0xa5, 0x0a, - 0xe7, 0xbd, 0xa9, 0x0a, 0xe9, 0x9c, 0x8d, 0x0a, 0xe6, 0x92, 0x88, 0x0a, - 0xe8, 0x83, 0x8e, 0x0a, 0xe8, 0x92, 0xbc, 0x0a, 0xe6, 0xbf, 0xb1, 0x0a, - 0xe5, 0x80, 0x86, 0x0a, 0xe6, 0x8d, 0x85, 0x0a, 0xe6, 0xb9, 0x98, 0x0a, - 0xe7, 0xa0, 0x8d, 0x0a, 0xe9, 0x9c, 0x9e, 0x0a, 0xe9, 0x82, 0xb5, 0x0a, - 0xe8, 0x90, 0x84, 0x0a, 0xe7, 0x98, 0x8b, 0x0a, 0xe6, 0xb7, 0xae, 0x0a, - 0xe9, 0x81, 0x82, 0x0a, 0xe7, 0x86, 0x8a, 0x0a, 0xe7, 0xb3, 0x9e, 0x0a, - 0xe7, 0x83, 0x98, 0x0a, 0xe5, 0xae, 0xbf, 0x0a, 0xe6, 0xaa, 0x94, 0x0a, - 0xe6, 0x88, 0x88, 0x0a, 0xe9, 0xa7, 0x81, 0x0a, 0xe5, 0xab, 0x82, 0x0a, - 0xe8, 0xa3, 0x95, 0x0a, 0xe5, 0xbe, 0x99, 0x0a, 0xe7, 0xae, 0xad, 0x0a, - 0xe6, 0x8d, 0x90, 0x0a, 0xe8, 0x85, 0xb8, 0x0a, 0xe6, 0x92, 0x90, 0x0a, - 0xe6, 0x9b, 0xac, 0x0a, 0xe8, 0xbe, 0xa8, 0x0a, 0xe6, 0xae, 0xbf, 0x0a, - 0xe8, 0x93, 0xae, 0x0a, 0xe6, 0x94, 0xa4, 0x0a, 0xe6, 0x94, 0xaa, 0x0a, - 0xe9, 0x86, 0xac, 0x0a, 0xe5, 0xb1, 0x8f, 0x0a, 0xe7, 0x96, 0xab, 0x0a, - 0xe5, 0x93, 0x80, 0x0a, 0xe8, 0x94, 0xa1, 0x0a, 0xe5, 0xa0, 0xb5, 0x0a, - 0xe6, 0xb2, 0xab, 0x0a, 0xe7, 0x9a, 0xba, 0x0a, 0xe6, 0x9a, 0xa2, 0x0a, - 0xe7, 0x96, 0x8a, 0x0a, 0xe9, 0x96, 0xa3, 0x0a, 0xe8, 0x90, 0x8a, 0x0a, - 0xe6, 0x95, 0xb2, 0x0a, 0xe8, 0xbd, 0x84, 0x0a, 0xe9, 0x89, 0xa4, 0x0a, - 0xe7, 0x97, 0x95, 0x0a, 0xe5, 0xa3, 0xa9, 0x0a, 0xe5, 0xb7, 0xb7, 0x0a, - 0xe9, 0xa4, 0x93, 0x0a, 0xe7, 0xa6, 0x8d, 0x0a, 0xe4, 0xb8, 0x98, 0x0a, - 0xe7, 0x8e, 0x84, 0x0a, 0xe6, 0xba, 0x9c, 0x0a, 0xe6, 0x9b, 0xb0, 0x0a, - 0xe9, 0x82, 0x8f, 0x0a, 0xe5, 0xbd, 0xad, 0x0a, 0xe5, 0x98, 0x97, 0x0a, - 0xe5, 0x8d, 0xbf, 0x0a, 0xe5, 0xa6, 0xa8, 0x0a, 0xe8, 0x89, 0x87, 0x0a, - 0xe5, 0x90, 0x9e, 0x0a, 0xe9, 0x9f, 0x8b, 0x0a, 0xe6, 0x80, 0xa8, 0x0a, - 0xe7, 0x9f, 0xae, 0x0a, 0xe6, 0xad, 0x87, 0x0a +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers. +// SPDX-FileCopyrightText: © Google, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef BITCOIN_LEVELDB_H +#define BITCOIN_LEVELDB_H + +#include "main.h" + +#include +#include +#include + + +#include +#include + +#include "ringsig.h" + +/* +prefixes + ao + ki + version + tx + bidx + bhdx + hashBestChain + hashBestHeaderChain + bnBestInvalidTrust + hashSyncCheckpoint + strCheckpointPubKey + + + old: + blockindex +*/ + +// Class that provides access to a LevelDB. Note that this class is frequently +// instantiated on the stack and then destroyed again, so instantiation has to +// be very cheap. Unfortunately that means, a CTxDB instance is actually just a +// wrapper around some global state. +// +// A LevelDB is a key/value store that is optimized for fast usage on hard +// disks. It prefers long read/writes to seeks and is based on a series of +// sorted key/value mapping files that are stacked on top of each other, with +// newer files overriding older files. A background thread compacts them +// together when too many files stack up. +// +// Learn more: http://code.google.com/p/leveldb/ +class CTxDB +{ +public: + CTxDB(const char* pszMode="r+"); + ~CTxDB() { + // Note that this is not the same as Close() because it deletes only + // data scoped to this TxDB object. + if (activeBatch) + delete activeBatch; + } + + // Destroys the underlying shared global state accessed by this TxDB. + void Close(); + +private: + leveldb::DB *pdb = nullptr; // Points to the global instance. + + // A batch stores up writes and deletes for atomic application. When this + // field is non-nullptr, writes/deletes go there instead of directly to disk. + leveldb::WriteBatch *activeBatch = nullptr; + leveldb::Options openOptions; + bool fReadOnly = false; + int nVersion = 0; + +protected: + // Returns true and sets (value,false) if activeBatch contains the given key + // or leaves value alone and sets deleted = true if activeBatch contains a + // delete for it. + bool ScanBatch(const CDataStream &key, std::string *value, bool *deleted) const; + + template + bool Read(const K& key, T& value) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + std::string strValue; + + bool readFromDb = true; + if (activeBatch) + { + // First we must search for it in the currently pending set of + // changes to the db. If not found in the batch, go on to read disk. + bool deleted = false; + readFromDb = ScanBatch(ssKey, &strValue, &deleted) == false; + if (deleted) + { + return false; + } + }; + + if (readFromDb) + { + leveldb::Status status = pdb->Get(GetReadOptions(), + ssKey.str(), &strValue); + if (!status.ok()) + { + if (status.IsNotFound()) + return false; + // Some unexpected error. + LogPrintf("LevelDB read failure: %s\n", status.ToString().c_str()); + return false; + } + } + // Unserialize value + try { + CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), + SER_DISK, CLIENT_VERSION); + ssValue >> value; + } catch (std::exception &e) + { + return false; + } + return true; + } + + template + bool Write(const K& key, const T& value) + { + if (fReadOnly) + assert(!"Write called on database in read-only mode"); + + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.reserve(10000); + ssValue << value; + + if (activeBatch) + { + activeBatch->Put(ssKey.str(), ssValue.str()); + return true; + }; + + leveldb::Status status = pdb->Put(GetWriteOptions(), ssKey.str(), ssValue.str()); + if (!status.ok()) + { + LogPrintf("LevelDB write failure: %s\n", status.ToString().c_str()); + return false; + }; + + return true; + } + + template + bool Erase(const K& key) + { + if (!pdb) + return false; + if (fReadOnly) + assert(!"Erase called on database in read-only mode"); + + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + if (activeBatch) + { + activeBatch->Delete(ssKey.str()); + return true; + }; + + leveldb::Status status = pdb->Delete(GetWriteOptions(), ssKey.str()); + return (status.ok() || status.IsNotFound()); + } + + template + bool Exists(const K& key) + { + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + std::string unused; + + if (activeBatch) + { + bool deleted; + if (ScanBatch(ssKey, &unused, &deleted) && !deleted) + { + return true; + } + } + + leveldb::Status status = pdb->Get(GetReadOptions(), ssKey.str(), &unused); + return status.IsNotFound() == false; + } + + +public: + bool TxnBegin(); + bool TxnCommit(); + bool TxnAbort() + { + delete activeBatch; + activeBatch = nullptr; + return true; + } + + leveldb::DB* GetInstance() + { + return pdb; + } + + bool ReadVersion(int& nVersion) + { + nVersion = 0; + return Read(std::string("version"), nVersion); + } + + bool WriteVersion(int nVersion) + { + return Write(std::string("version"), nVersion); + } + + static leveldb::ReadOptions GetReadOptions() + { + leveldb::ReadOptions readOptions; + return readOptions; + } + + static leveldb::WriteOptions GetWriteOptions() + { + leveldb::WriteOptions writeOptions; + writeOptions.sync = true; + return writeOptions; + } + + int CheckVersion(); + int RecreateDB(); + + bool WriteKeyImage(ec_point& keyImage, CKeyImageSpent& keyImageSpent); + bool ReadKeyImage(ec_point& keyImage, CKeyImageSpent& keyImageSpent); + bool EraseKeyImage(ec_point& keyImage); + + bool WriteAnonOutput(CPubKey& pkCoin, CAnonOutput& ao); + bool ReadAnonOutput(CPubKey& pkCoin, CAnonOutput& ao); + bool EraseAnonOutput(CPubKey& pkCoin); + + bool WriteCompromisedAnonHeights(std::map>& mapCompromisedHeights); + bool ReadCompromisedAnonHeights(std::map>& mapCompromisedHeights); + bool EraseCompromisedAnonHeights(); + + bool EraseRange(const std::string &sPrefix, uint32_t &nAffected, std::function funcProgress = nullptr); + + bool ReadTxIndex(uint256 hash, CTxIndex& txindex); + bool UpdateTxIndex(uint256 hash, const CTxIndex& txindex); + bool AddTxIndex(const CTransaction& tx, const CDiskTxPos& pos, int nHeight); + bool EraseTxIndex(const CTransaction& tx); + bool ContainsTx(uint256 hash); + bool ReadDiskTx(uint256 hash, CTransaction& tx, CTxIndex& txindex); + bool ReadDiskTx(uint256 hash, CTransaction& tx); + bool ReadDiskTx(COutPoint outpoint, CTransaction& tx, CTxIndex& txindex); + bool ReadDiskTx(COutPoint outpoint, CTransaction& tx); + bool WriteBlockIndex(const CDiskBlockIndex& blockindex); + bool EraseBlockIndex(const uint256& blockhash); + bool WriteBlockThinIndex(const CDiskBlockThinIndex& blockindex); + bool ReadBlockThinIndex(const uint256& hash, CDiskBlockThinIndex& blockindex); + bool ReadHashBestChain(uint256& hashBestChain); + bool WriteHashBestChain(uint256 hashBestChain); + bool ReadHashBestHeaderChain(uint256& hashBestChain); + bool WriteHashBestHeaderChain(uint256 hashBestChain); + bool ReadBestInvalidTrust(CBigNum& bnBestInvalidTrust); + bool WriteBestInvalidTrust(CBigNum bnBestInvalidTrust); + bool ReadSyncCheckpoint(uint256& hashCheckpoint); + bool WriteSyncCheckpoint(uint256 hashCheckpoint); + bool ReadCheckpointPubKey(std::string& strPubKey); + bool WriteCheckpointPubKey(const std::string& strPubKey); + bool LoadBlockIndex(std::function funcValidate = nullptr, std::function funcProgress = nullptr); + bool LoadBlockThinIndex(); +private: + bool LoadBlockIndexGuts(); }; -unsigned int chinese_traditional_txt_len = 8192; + + +#endif // BITCOIN_DB_H diff --git a/src/wordlists/english.h b/src/wordlists/english.h index 4b0c6361fa..eccae9cf3d 100644 --- a/src/wordlists/english.h +++ b/src/wordlists/english.h @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + #ifndef _WORDLIST_ENGLISH_H #define _WORDLIST_ENGLISH_H 1 diff --git a/src/wordlists/french.h b/src/wordlists/french.h index c4906769dd..dc664f4768 100644 --- a/src/wordlists/french.h +++ b/src/wordlists/french.h @@ -1,3 +1,9 @@ +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// +// SPDX-License-Identifier: MIT + unsigned char french_txt[] = { 0xef, 0xbb, 0xbf, 0x61, 0x62, 0x61, 0x69, 0x73, 0x73, 0x65, 0x72, 0x0a, 0x61, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x0a, 0x61, 0x62, 0x64, 0x69, diff --git a/src/wordlists/japanese.h b/src/wordlists/japanese.h index fbf4320c93..08b855daa0 100644 --- a/src/wordlists/japanese.h +++ b/src/wordlists/japanese.h @@ -1,2205 +1,868 @@ -unsigned char japanese_txt[] = { - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x83, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x82, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xb2, 0x0a, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x99, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0xbe, - 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x85, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0xbe, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x82, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0xbe, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x99, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x81, 0x82, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8b, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbe, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x86, 0xe3, 0x82, 0x80, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8f, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x82, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x86, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x82, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0x82, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0x0a, - 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0xae, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xb5, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8d, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x88, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x86, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x82, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xb5, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, 0xe3, - 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x9a, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x93, 0x0a, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xad, 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0xae, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0xbf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x82, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x82, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x82, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x84, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x88, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, - 0x82, 0x88, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x89, 0xe3, 0x81, - 0x99, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8a, 0xe3, - 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x84, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, - 0x82, 0x8c, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x8d, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x9a, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x86, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbe, 0xe3, 0x82, - 0x81, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x93, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x88, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x95, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaa, - 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8c, 0xe3, 0x82, - 0x8c, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0xbe, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x91, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x8d, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x99, 0xe3, 0x82, - 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x82, - 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x9b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xa1, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xa4, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb5, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x82, 0x89, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa1, 0x0a, - 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8a, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8b, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, - 0x8c, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x86, 0xe3, - 0x82, 0x8c, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x86, - 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, - 0x8d, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x95, - 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa6, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x88, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, - 0x8a, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8a, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, - 0x8d, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x88, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0xa4, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x88, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x88, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x88, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8a, 0xe3, 0x81, 0x82, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, - 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbe, 0x0a, - 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0xa4, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb5, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x86, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x9d, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x80, 0x0a, - 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8f, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x95, 0xe3, 0x82, - 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, - 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x9d, 0xe3, - 0x82, 0x8f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8b, 0x0a, - 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x91, - 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8d, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x82, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, - 0x82, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x82, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, - 0x84, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, - 0x8d, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8a, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x8a, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa1, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, - 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xb8, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9d, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa1, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x95, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0xbb, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0xbe, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x93, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0xa4, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8d, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x8a, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa1, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x89, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x95, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbe, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xab, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x85, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xad, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xac, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x81, 0xad, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xae, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xb5, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xbb, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xbb, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x82, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x97, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa1, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8a, 0xe3, - 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x89, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x8d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x8f, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8d, 0x0a, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0x0a, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x95, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xaa, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x8d, - 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8a, 0xe3, 0x82, - 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x9b, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0xa4, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa6, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xaa, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0xad, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xae, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x8f, - 0xe3, 0x81, 0x9b, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xbf, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x84, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x82, 0x89, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, - 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8f, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0xae, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, - 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0xaf, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, - 0xa1, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xb5, 0xe3, 0x82, - 0x9a, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x88, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8d, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xac, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xad, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x81, - 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x80, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x80, - 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0xae, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8d, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8a, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xab, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x89, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8a, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xbe, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xac, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xa1, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x8d, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x81, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa1, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xaa, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xad, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0xbe, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xbf, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x88, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xbe, - 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x80, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x82, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x84, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbe, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x8a, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x8c, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0xa6, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8c, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x93, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa6, 0x0a, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaa, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xab, 0x0a, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x91, 0x0a, 0xe3, - 0x81, 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, - 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x87, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x89, 0x0a, 0xe3, - 0x81, 0x95, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa4, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0x95, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xaf, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0xbe, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x82, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x82, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xb8, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbb, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbf, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x80, 0xe3, 0x81, 0x91, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x84, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x89, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x95, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xaf, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x8f, 0xe3, 0x82, - 0x84, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x8f, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x8b, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0x0a, - 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, - 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, - 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x82, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x9b, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x91, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x91, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa6, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x8a, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x82, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0xaa, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0xaa, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xad, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x8f, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xb5, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x87, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xb5, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xb8, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0xbf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x80, - 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, - 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x83, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x82, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x84, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x93, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x95, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x83, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x83, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x83, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x83, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, - 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x83, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x85, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x87, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x97, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0xe3, 0x82, - 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0xaa, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x82, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x8b, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x99, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x97, 0x0a, - 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x99, 0xe3, - 0x82, 0x80, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x99, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x99, 0xe3, - 0x81, 0xa6, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xad, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xae, 0xe3, 0x81, - 0x93, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xb5, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xac, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x99, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0x99, 0xe3, - 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0x99, - 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0x99, 0xe3, - 0x82, 0x82, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x84, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x89, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8b, 0xe3, - 0x82, 0x81, 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0xa1, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, - 0x81, 0x99, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, - 0x9a, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x88, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x89, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x99, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x91, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x8d, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x9b, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xa6, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x81, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, 0xe3, 0x82, - 0x8a, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xbb, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xad, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0xbe, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x8c, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0xb5, 0x0a, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x88, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, - 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x87, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x9a, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x80, 0x0a, 0xe3, - 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x82, - 0x89, 0x0a, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, - 0x82, 0x8a, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x9b, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x82, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xad, 0x0a, 0xe3, - 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xaa, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, - 0x86, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa6, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa8, - 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0xa4, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0xb5, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, - 0x81, 0x9d, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, - 0x80, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x80, 0xe3, - 0x82, 0x8a, 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x82, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x88, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9d, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x81, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9d, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x93, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xb5, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xbb, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xbe, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xbf, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8a, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8a, 0xe3, 0x82, - 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0xad, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x84, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x83, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x95, - 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbf, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x83, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xab, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xac, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x80, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x81, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x8a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x8b, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8c, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8c, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8d, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8f, - 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x82, 0xe3, 0x81, - 0xa4, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaa, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xbe, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x93, 0xe3, - 0x82, 0x81, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8f, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa1, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x89, - 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x91, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa1, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa1, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0x8a, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0xa1, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xac, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xac, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xa1, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x9f, 0x0a, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0xa1, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x8d, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x83, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xb8, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x86, 0xe3, - 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xa1, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, - 0xa1, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xbf, - 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8b, - 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x8f, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x93, - 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0x9f, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, - 0xa4, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xad, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0xad, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xa4, 0xe3, - 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xaa, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xad, 0x0a, 0xe3, 0x81, - 0xa4, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa4, - 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa4, 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, - 0x82, 0x82, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x88, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8b, 0xe3, 0x81, - 0xbb, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8b, 0xe3, - 0x81, 0xbf, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8f, - 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0xa4, 0xe3, 0x82, - 0x8f, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x82, 0xe3, - 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa6, - 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0xb8, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8c, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xbb, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x91, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8a, 0x0a, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0xa4, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x9a, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xbb, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0xa4, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xac, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0xac, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x89, 0x0a, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, - 0xbb, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x88, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x8b, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x84, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8c, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x91, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa6, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, - 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa6, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, - 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, - 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x8c, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x97, 0x0a, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8a, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8b, 0x0a, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x99, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xab, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x93, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x87, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, - 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xa3, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0xab, 0xe3, - 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0xa8, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x81, 0xa8, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbe, 0x0a, - 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, - 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xb5, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, - 0x81, 0xa8, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xa8, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x82, 0xe3, - 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x87, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x99, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x99, 0x0a, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x95, 0xe3, 0x81, - 0x91, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xa6, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8a, 0xe3, - 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, - 0xab, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0xab, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xbe, - 0xe3, 0x81, 0x88, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x81, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x84, 0xe3, 0x82, 0x80, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xaa, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0xaa, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0xaa, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xaa, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x82, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x81, 0xab, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x91, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8a, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0xbe, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x91, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, - 0x95, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x9d, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x82, - 0xe3, 0x81, 0xae, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xab, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0x95, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xab, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0xab, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xab, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xab, 0xe3, - 0x81, 0xbe, 0xe3, 0x82, 0x81, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x82, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x84, 0xe3, 0x82, - 0x8a, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x84, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x8a, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, - 0xab, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xab, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa1, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa6, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xab, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x9a, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xbe, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, - 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, 0x82, - 0x81, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x93, 0xe3, - 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0xac, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xac, 0xe3, - 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x82, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0x99, 0xe3, - 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x88, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x82, - 0x81, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x82, 0x89, 0xe3, - 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xac, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, - 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, - 0x82, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x84, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x8d, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x9b, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x8f, 0xe3, 0x82, - 0x89, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x80, - 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x91, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x93, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0xad, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0xad, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xad, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, 0x0a, - 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9d, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xbb, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xbb, - 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0xad, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x97, 0x0a, - 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, - 0xad, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xad, 0xe3, - 0x82, 0x80, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xad, - 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xad, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xad, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, - 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x83, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x9a, 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xad, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xad, - 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8c, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x8a, 0xe3, 0x81, 0xa4, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xae, 0xe3, - 0x81, 0x8d, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x99, 0x0a, 0xe3, - 0x81, 0xae, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xae, 0xe3, - 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xae, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xae, 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x99, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, - 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x89, 0x0a, 0xe3, - 0x81, 0xae, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x82, 0xe3, 0x81, - 0xae, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbe, 0x0a, - 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xac, - 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0xad, 0xe3, 0x81, - 0x93, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x82, 0xe3, - 0x81, 0xae, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x86, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x8c, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xae, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x95, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, 0xe3, - 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x8c, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8a, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0x9d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0xbf, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0xa4, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa1, - 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xbb, - 0xe3, 0x82, 0x9a, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0xaa, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xaa, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0xab, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x97, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0xa4, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x8d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x83, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x83, 0x0a, 0xe3, 0x81, 0xaf, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xa8, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x9a, - 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x89, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8d, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, - 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x8b, - 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, - 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x95, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x85, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x80, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x80, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, - 0xa3, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa4, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x99, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x9b, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x9a, 0xe3, - 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x9a, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x8a, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x88, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xaa, 0xe3, 0x81, - 0xbe, 0xe3, 0x81, 0xa4, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, - 0x81, 0xaa, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xad, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x87, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8f, 0xe3, - 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x91, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xaa, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x8b, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x8d, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x8d, - 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb2, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0x0a, 0xe3, - 0x81, 0xb2, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa1, - 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, - 0x9a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xb5, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, - 0x81, 0xb5, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x9a, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb5, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8a, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x81, 0xb5, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xb5, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, - 0xb5, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, - 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x97, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbf, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x9f, - 0xe3, 0x81, 0xab, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0x9f, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa1, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa4, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa4, 0xe3, 0x81, - 0x8b, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8d, - 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xb5, 0xe3, 0x81, 0xaf, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xb5, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xb5, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb5, - 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x81, - 0xbf, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x81, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x81, 0xb5, - 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, - 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x8f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xbb, 0xe3, - 0x82, 0x9a, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x8a, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x81, - 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, - 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, - 0x83, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9d, - 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa6, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xad, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x84, 0xe3, 0x82, - 0x8f, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x80, - 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xab, 0xe3, 0x81, - 0x84, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xab, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x89, - 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb8, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xb8, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, - 0xbb, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x87, - 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0xe3, 0x81, - 0x8f, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9d, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xbb, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, 0x82, - 0x82, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0xe3, - 0x82, 0x8a, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x88, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x8a, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8d, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8d, 0x0a, - 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, - 0xbb, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, - 0x81, 0x93, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x93, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0x0a, 0xe3, 0x81, - 0xbb, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x81, 0xbb, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xbb, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, - 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x9f, 0xe3, - 0x81, 0xa6, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x9a, 0xe3, 0x81, 0xa1, 0xe3, 0x81, - 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x8d, 0x0a, 0xe3, - 0x81, 0xbb, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x95, - 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x9f, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0xa8, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0xa8, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x81, - 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x91, 0x0a, 0xe3, 0x81, - 0xbb, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x81, 0xbb, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xab, 0xe3, 0x81, 0xa1, - 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xbe, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, - 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0xbe, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0xbe, - 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x81, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x9b, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, - 0xa4, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x81, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0xb5, - 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xac, 0xe3, 0x81, - 0x91, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0xbb, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, - 0xbe, 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xbe, - 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, - 0x8d, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x8f, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8f, - 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x8f, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, - 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, 0x82, 0x93, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbe, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xaa, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, - 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x89, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0xa1, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x88, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x9f, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, - 0xbf, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, - 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, - 0xbf, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x81, 0xbf, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, - 0xa4, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, - 0x81, 0xa4, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, - 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, - 0xa8, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, - 0x81, 0xaa, 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xaa, - 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xad, 0xe3, 0x82, 0x89, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xae, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x81, 0xbb, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa8, 0x0a, - 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x81, 0xbf, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x81, 0xbf, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x81, - 0xbf, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x81, 0xbf, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x82, - 0x80, 0xe3, 0x81, 0x88, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x82, 0x80, 0xe3, - 0x81, 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8b, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x88, 0x0a, - 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x82, - 0x80, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x83, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0xbb, 0xe3, 0x82, - 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x97, 0xe3, - 0x81, 0x82, 0xe3, 0x81, 0xa4, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x80, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, - 0x80, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x85, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x8d, 0x0a, - 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, - 0x80, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x93, 0x0a, 0xe3, 0x82, 0x80, 0xe3, - 0x81, 0x99, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x80, - 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x81, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, - 0x9b, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0x9b, 0xe3, - 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0xa1, 0xe3, 0x82, 0x85, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0xaa, 0xe3, 0x81, - 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x81, 0xae, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbf, - 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x82, 0x80, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x8d, 0x0a, - 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x82, 0x80, 0xe3, 0x82, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x82, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x88, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x81, 0xe3, - 0x81, 0x84, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, - 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x84, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, - 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x84, 0xe3, 0x82, 0x8f, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x81, - 0xbe, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x81, 0xe3, - 0x81, 0x95, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x82, 0x81, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x9f, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x99, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0x0a, 0xe3, - 0x82, 0x81, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0x0a, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x8d, - 0x0a, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xa8, 0xe3, 0x82, - 0x99, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x97, 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, - 0x82, 0x82, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x97, 0x0a, 0xe3, 0x82, 0x82, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa6, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x82, - 0x82, 0xe3, 0x81, 0x8f, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, 0x81, - 0xb2, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa1, 0xe3, - 0x82, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x81, 0xa8, - 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x82, - 0x89, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x93, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x82, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9f, - 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, - 0x8a, 0xe3, 0x82, 0x84, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x91, 0xe3, - 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x8d, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x99, 0xe3, 0x81, - 0xbf, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x8b, 0x0a, - 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, - 0x84, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x84, 0xe3, - 0x81, 0xa1, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xa3, - 0xe3, 0x81, 0xa8, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xa3, 0xe3, 0x81, - 0xaf, 0xe3, 0x82, 0x9a, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x82, 0x84, 0xe3, - 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x84, - 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x84, 0xe3, 0x82, - 0x84, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x82, 0x84, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x84, - 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x82, 0x86, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0x0a, - 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0xb8, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x81, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0xa4, 0x0a, - 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x82, 0x86, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x86, - 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x82, 0x86, 0xe3, 0x81, - 0xa1, 0xe3, 0x82, 0x83, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x86, 0xe3, - 0x81, 0xa6, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x86, - 0xe3, 0x81, 0xab, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, - 0x86, 0xe3, 0x81, 0xb2, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0x0a, 0xe3, - 0x82, 0x86, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x86, - 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x8b, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x8d, - 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x88, 0xe3, - 0x81, 0x86, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0xa1, 0xe3, 0x81, 0x88, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, - 0x88, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x99, 0x0a, 0xe3, - 0x82, 0x88, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x88, - 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, - 0x8f, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x88, 0xe3, - 0x81, 0x8f, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, - 0x88, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8c, 0xe3, 0x82, - 0x8b, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x95, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x82, 0x88, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x88, - 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, - 0xa6, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0xa8, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0xad, 0xe3, 0x81, 0xa4, - 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x82, 0x88, 0xe3, 0x82, 0x86, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x88, - 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x82, 0x88, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x97, 0xe3, 0x81, - 0x84, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, 0xe3, 0x81, - 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x95, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, - 0xe3, 0x81, 0x9f, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x99, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, 0x0a, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x9f, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x82, 0x89, 0xe3, 0x81, 0xa3, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x82, 0x89, - 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, - 0x88, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8b, 0xe3, - 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x95, - 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x9b, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8f, 0xe3, - 0x81, 0x8f, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8a, - 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, - 0x91, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x9b, 0xe3, 0x81, 0x84, - 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x86, 0x0a, 0xe3, - 0x82, 0x8a, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x8a, - 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, - 0xad, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x86, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x85, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, - 0x8a, 0xe3, 0x82, 0x88, 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, - 0x82, 0x87, 0xe3, 0x81, 0x86, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, 0x82, 0x8a, - 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, - 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0xa1, 0xe3, 0x82, - 0x83, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x87, 0xe3, 0x81, 0x93, 0xe3, - 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x8a, 0xe3, 0x81, 0x8f, - 0x0a, 0xe3, 0x82, 0x8a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x8d, 0x0a, 0xe3, - 0x82, 0x8a, 0xe3, 0x82, 0x8d, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8a, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, - 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, - 0x82, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, - 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, - 0x0a, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, 0xe3, 0x81, - 0x8d, 0x0a, 0xe3, 0x82, 0x8b, 0xe3, 0x81, 0x99, 0xe3, 0x81, 0xaf, 0xe3, - 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8b, 0xe3, 0x82, 0x8a, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x89, - 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8b, 0xe3, 0x82, - 0x93, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x8d, 0xe3, - 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x9b, - 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, - 0x9d, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x93, 0x0a, 0xe3, - 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xa8, 0xe3, 0x81, 0x86, 0x0a, - 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0xbb, 0xe3, 0x82, 0x99, - 0xe3, 0x81, 0x86, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x8d, 0xe3, 0x81, - 0x97, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0x8d, 0xe3, 0x81, 0x9f, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x93, - 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x91, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0x93, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8c, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x95, 0xe3, 0x81, 0x84, 0x0a, 0xe3, 0x82, - 0x8c, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, 0x81, - 0x86, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x93, 0xe3, 0x81, 0x9d, 0xe3, - 0x82, 0x99, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x93, - 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, - 0x86, 0xe3, 0x81, 0x8b, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, 0xe3, - 0x81, 0x93, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x86, - 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, - 0x8d, 0xe3, 0x81, 0x86, 0xe3, 0x81, 0x9d, 0xe3, 0x81, 0x8f, 0x0a, 0xe3, - 0x82, 0x8d, 0xe3, 0x81, 0x8f, 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x99, 0x0a, - 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x93, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, - 0x8d, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0x86, 0xe3, 0x82, - 0x89, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x97, 0xe3, 0x82, 0x85, 0xe3, - 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0x9b, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x81, 0xa6, 0xe3, 0x82, 0x93, 0x0a, 0xe3, - 0x82, 0x8d, 0xe3, 0x82, 0x81, 0xe3, 0x82, 0x93, 0x0a, 0xe3, 0x82, 0x8d, - 0xe3, 0x82, 0x8c, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x82, - 0x93, 0xe3, 0x81, 0x8d, 0xe3, 0x82, 0x99, 0x0a, 0xe3, 0x82, 0x8d, 0xe3, - 0x82, 0x93, 0xe3, 0x81, 0xaf, 0xe3, 0x82, 0x9a, 0x0a, 0xe3, 0x82, 0x8d, - 0xe3, 0x82, 0x93, 0xe3, 0x81, 0xb5, 0xe3, 0x82, 0x99, 0xe3, 0x82, 0x93, - 0x0a, 0xe3, 0x82, 0x8d, 0xe3, 0x82, 0x93, 0xe3, 0x82, 0x8a, 0x0a, 0xe3, - 0x82, 0x8f, 0xe3, 0x81, 0x8b, 0xe3, 0x81, 0x99, 0x0a, 0xe3, 0x82, 0x8f, - 0xe3, 0x81, 0x8b, 0xe3, 0x82, 0x81, 0x0a, 0xe3, 0x82, 0x8f, 0xe3, 0x81, - 0x8b, 0xe3, 0x82, 0x84, 0xe3, 0x81, 0xbe, 0x0a, 0xe3, 0x82, 0x8f, 0xe3, - 0x81, 0x8b, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a, 0xe3, 0x82, 0x8f, - 0xe3, 0x81, 0x97, 0xe3, 0x81, 0xa4, 0x0a, 0xe3, 0x82, 0x8f, 0xe3, 0x81, - 0x97, 0xe3, 0x82, 0x99, 0xe3, 0x81, 0xbe, 0xe3, 0x81, 0x97, 0x0a, 0xe3, - 0x82, 0x8f, 0xe3, 0x81, 0x99, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x82, 0xe3, - 0x81, 0xae, 0x0a, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x89, 0xe3, 0x81, 0x86, - 0x0a, 0xe3, 0x82, 0x8f, 0xe3, 0x82, 0x8c, 0xe3, 0x82, 0x8b, 0x0a +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2014 ShadowCoin Developers +// SPDX-FileCopyrightText: © 2014 BlackCoin Developers +// SPDX-FileCopyrightText: © 2013 NovaCoin Developers +// SPDX-FileCopyrightText: © 2011 PPCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// +// SPDX-License-Identifier: MIT + +#include "walletdb.h" +#include "wallet.h" +#include "util/fs.h" +#include + +using namespace std; + +static uint64_t nAccountingEntryNumber = 0; +extern bool fWalletUnlockStakingOnly; + +// +// CWalletDB +// + + + +bool CWalletDB::WriteName(const string& strAddress, const string& strName) +{ + nWalletDBUpdated++; + return Write(make_pair(string("name"), strAddress), strName); +} + +bool CWalletDB::EraseName(const string& strAddress) +{ + // This should only be used for sending addresses, never for receiving addresses, + // receiving addresses must always have an address book entry if they're not change return. + nWalletDBUpdated++; + return Erase(make_pair(string("name"), strAddress)); +} + +bool CWalletDB::EraseRange(const std::string& sPrefix, uint32_t &nAffected) +{ + + TxnBegin(); + + Dbc* pcursor = GetTxnCursor(); + + if (!pcursor) + throw runtime_error("EraseAllAnonData() : cannot create DB cursor"); + + size_t nLenPrefix = sPrefix.length(); + + if (nLenPrefix > 252) // fit in 256 and compressed int is 1 byte + { + LogPrintf("EraseRange(%s) - Key length too long.\n", sPrefix.c_str()); + return false; + }; + + // - key starts with strlen || str + uint8_t data[256]; + data[0] = (uint8_t)nLenPrefix; + memcpy(&data[1], sPrefix.data(), nLenPrefix); + + Dbt key, record; + memset(&key, 0, sizeof(key)); + key.set_data(data); + key.set_size(nLenPrefix+1); + unsigned int fFlags = DB_SET_RANGE; + int ret; + while ((ret = pcursor->get(&key, &record, fFlags)) == 0) + { + fFlags = DB_NEXT; + + if (key.get_size() < nLenPrefix+1 + || memcmp(key.get_data(), data, nLenPrefix+1) != 0) + break; + + if ((ret = pcursor->del(0)) != 0) + LogPrintf("EraseRange(%s) - Delete failed %d, %s\n", sPrefix.c_str(), ret, db_strerror(ret)); + + nAffected++; + }; + + pcursor->close(); + + TxnCommit(); + + return true; }; -unsigned int japanese_txt_len = 26423; + +bool CWalletDB::ReadAccount(const string& strAccount, CAccount& account) +{ + account.SetNull(); + return Read(make_pair(string("acc"), strAccount), account); +} + +bool CWalletDB::WriteAccount(const string& strAccount, const CAccount& account) +{ + return Write(make_pair(string("acc"), strAccount), account); +} + +bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) +{ + return Write(boost::make_tuple(string("acentry"), acentry.strAccount, nAccEntryNum), acentry); +} + +bool CWalletDB::WriteAccountingEntry(const CAccountingEntry& acentry) +{ + return WriteAccountingEntry(++nAccountingEntryNumber, acentry); +} + +bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) +{ + nWalletDBUpdated++; + + if (!Write(std::make_pair(std::string("keymeta"), vchPubKey), + keyMeta, true)) + return false; + + // hash pubkey/privkey to accelerate wallet load + std::vector vchKey; + vchKey.reserve(vchPubKey.size() + vchPrivKey.size()); + vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); + vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); + + return Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), true); +} + +bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, + const std::vector& vchCryptedSecret, + const CKeyMetadata &keyMeta) +{ + const bool fEraseUnencryptedKey = true; + nWalletDBUpdated++; + + if (!Write(std::make_pair(std::string("keymeta"), vchPubKey), + keyMeta)) + return false; + + if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, true)) + return false; + if (fEraseUnencryptedKey) + { + Erase(std::make_pair(std::string("key"), vchPubKey)); + Erase(std::make_pair(std::string("wkey"), vchPubKey)); + } + return true; +} + +bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) +{ + nWalletDBUpdated++; + return Write(std::string("defaultkey"), vchPubKey); +} + +int64_t CWalletDB::GetAccountCreditDebit(const string& strAccount) +{ + list entries; + ListAccountCreditDebit(strAccount, entries); + + int64_t nCreditDebit = 0; + for (const CAccountingEntry& entry : entries) + nCreditDebit += entry.nCreditDebit; + + return nCreditDebit; +} + +void CWalletDB::ListAccountCreditDebit(const string& strAccount, list& entries) +{ + bool fAllAccounts = (strAccount == "*"); + + Dbc* pcursor = GetCursor(); + if (!pcursor) + throw runtime_error("CWalletDB::ListAccountCreditDebit() : cannot create DB cursor"); + unsigned int fFlags = DB_SET_RANGE; + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + if (fFlags == DB_SET_RANGE) + ssKey << boost::make_tuple(string("acentry"), (fAllAccounts? string("") : strAccount), uint64_t(0)); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); + fFlags = DB_NEXT; + if (ret == DB_NOTFOUND) + break; + else + if (ret != 0) + { + pcursor->close(); + throw runtime_error("CWalletDB::ListAccountCreditDebit() : error scanning DB"); + } + + // Unserialize + string strType; + ssKey >> strType; + if (strType != "acentry") + break; + CAccountingEntry acentry; + ssKey >> acentry.strAccount; + if (!fAllAccounts && acentry.strAccount != strAccount) + break; + + ssValue >> acentry; + ssKey >> acentry.nEntryNo; + entries.push_back(acentry); + } + + pcursor->close(); +} + + +DBErrors +CWalletDB::ReorderTransactions(CWallet* pwallet) +{ + LOCK(pwallet->cs_wallet); + // Old wallets didn't have any defined order for transactions + // Probably a bad idea to change the output of this + + // First: get all CWalletTx and CAccountingEntry into a sorted-by-time multimap. + typedef pair TxPair; + typedef multimap TxItems; + TxItems txByTime; + + for (map::iterator it = pwallet->mapWallet.begin(); it != pwallet->mapWallet.end(); ++it) + { + CWalletTx* wtx = &((*it).second); + txByTime.insert(make_pair(wtx->nTimeReceived, TxPair(wtx, (CAccountingEntry*)0))); + } + list acentries; + ListAccountCreditDebit("", acentries); + for (CAccountingEntry& entry : acentries) { + txByTime.insert(make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); + } + + int64_t& nOrderPosNext = pwallet->nOrderPosNext; + nOrderPosNext = 0; + std::vector nOrderPosOffsets; + for (TxItems::iterator it = txByTime.begin(); it != txByTime.end(); ++it) + { + CWalletTx *const pwtx = (*it).second.first; + CAccountingEntry *const pacentry = (*it).second.second; + int64_t& nOrderPos = (pwtx != 0) ? pwtx->nOrderPos : pacentry->nOrderPos; + + if (nOrderPos == -1) + { + nOrderPos = nOrderPosNext++; + nOrderPosOffsets.push_back(nOrderPos); + + if (pacentry) + // Have to write accounting regardless, since we don't keep it in memory + if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + return DB_LOAD_FAIL; + } else + { + int64_t nOrderPosOff = 0; + for (const int64_t& nOffsetStart : nOrderPosOffsets) + { + if (nOrderPos >= nOffsetStart) + ++nOrderPosOff; + }; + + nOrderPos += nOrderPosOff; + nOrderPosNext = std::max(nOrderPosNext, nOrderPos + 1); + + if (!nOrderPosOff) + continue; + + // Since we're changing the order, write it back + if (pwtx) + { + if (!WriteTx(pwtx->GetHash(), *pwtx)) + return DB_LOAD_FAIL; + } else + { + if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry)) + return DB_LOAD_FAIL; + }; + }; + }; + + return DB_LOAD_OK; +} + +class CWalletScanState +{ +public: + unsigned int nKeys; + unsigned int nCKeys; + unsigned int nKeyMeta; + bool fIsEncrypted; + bool fAnyUnordered; + int nFileVersion; + vector vWalletUpgrade; + + CWalletScanState() + { + nKeys = nCKeys = nKeyMeta = 0; + fIsEncrypted = false; + fAnyUnordered = false; + nFileVersion = 0; + } +}; + +bool +ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, + CWalletScanState &wss, string& strType, string& strErr) +{ + try { + // Unserialize + // Taking advantage of the fact that pair serialization + // is just the two items serialized one after the other + ssKey >> strType; + if (strType == "name") + { + string strAddress; + ssKey >> strAddress; + ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()]; + } else + if (strType == "tx") + { + uint256 hash; + ssKey >> hash; + CWalletTx& wtx = pwallet->mapWallet[hash]; + ssValue >> wtx; + if (wtx.CheckTransaction() && (wtx.GetHash() == hash)) + { + wtx.BindWallet(pwallet); + } else + { + pwallet->mapWallet.erase(hash); + return false; + }; + + // Undo serialize changes in 31600 + if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) + { + if (!ssValue.empty()) + { + char fTmp; + char fUnused; + ssValue >> fTmp >> fUnused >> wtx.strFromAccount; + strErr = strprintf("LoadWallet() upgrading tx ver=%d %d '%s' %s", + wtx.fTimeReceivedIsTxTime, fTmp, wtx.strFromAccount.c_str(), hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = fTmp; + } else + { + strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString().c_str()); + wtx.fTimeReceivedIsTxTime = 0; + }; + wss.vWalletUpgrade.push_back(hash); + }; + + if (wtx.nOrderPos == -1) + wss.fAnyUnordered = true; + + //// debug print + //LogPrintf("LoadWallet %s\n", wtx.GetHash().ToString().c_str()); + //LogPrintf(" %12d %s %s %s\n", + // wtx.vout[0].nValue, + // DateTimeStrFormat("%x %H:%M:%S", wtx.GetBlockTime()).c_str(), + // wtx.hashBlock.ToString().substr(0,20).c_str(), + // wtx.mapValue["message"].c_str()); + } else + if (strType == "sxAddr") + { + if (fDebug) + LogPrintf("WalletDB ReadKeyValue sxAddr\n"); + + CStealthAddress sxAddr; + ssValue >> sxAddr; + + pwallet->stealthAddresses.insert(sxAddr); + } else + if (strType == "acentry") + { + string strAccount; + ssKey >> strAccount; + uint64_t nNumber; + ssKey >> nNumber; + if (nNumber > nAccountingEntryNumber) + nAccountingEntryNumber = nNumber; + + if (!wss.fAnyUnordered) + { + CAccountingEntry acentry; + ssValue >> acentry; + if (acentry.nOrderPos == -1) + wss.fAnyUnordered = true; + }; + } else + if (strType == "key" || strType == "wkey") + { + CPubKey vchPubKey; + ssKey >> vchPubKey; + if (!vchPubKey.IsValid()) + { + strErr = "Error reading wallet database: CPubKey corrupt"; + return false; + } + CKey key; + CPrivKey pkey; + uint256 hash = 0; + + if (strType == "key") + { + wss.nKeys++; + ssValue >> pkey; + } else { + CWalletKey wkey; + ssValue >> wkey; + pkey = wkey.vchPrivKey; + } + + // Old wallets store keys as "key" [pubkey] => [privkey] + // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key + // using EC operations as a checksum. + // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while + // remaining backwards-compatible. + try + { + ssValue >> hash; + } + catch(...){} + + bool fSkipCheck = false; + + if (hash != 0) + { + // hash pubkey/privkey to accelerate wallet load + std::vector vchKey; + vchKey.reserve(vchPubKey.size() + pkey.size()); + vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); + vchKey.insert(vchKey.end(), pkey.begin(), pkey.end()); + + if (Hash(vchKey.begin(), vchKey.end()) != hash) + { + strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt"; + return false; + } + + fSkipCheck = true; + } + + if (!key.Load(pkey, vchPubKey, fSkipCheck)) + { + strErr = "Error reading wallet database: CPrivKey corrupt"; + return false; + } + if (!pwallet->LoadKey(key, vchPubKey)) + { + strErr = "Error reading wallet database: LoadKey failed"; + return false; + } + } else + if (strType == "mkey") + { + unsigned int nID; + ssKey >> nID; + CMasterKey kMasterKey; + ssValue >> kMasterKey; + if(pwallet->mapMasterKeys.count(nID) != 0) + { + strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID); + return false; + }; + pwallet->mapMasterKeys[nID] = kMasterKey; + if (pwallet->nMasterKeyMaxID < nID) + pwallet->nMasterKeyMaxID = nID; + } else + if (strType == "ckey") + { + wss.nCKeys++; + vector vchPubKey; + ssKey >> vchPubKey; + vector vchPrivKey; + ssValue >> vchPrivKey; + if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey)) + { + strErr = "Error reading wallet database: LoadCryptedKey failed"; + return false; + }; + wss.fIsEncrypted = true; + } else + if (strType == "keymeta") + { + CPubKey vchPubKey; + ssKey >> vchPubKey; + CKeyMetadata keyMeta; + ssValue >> keyMeta; + wss.nKeyMeta++; + + // nTimeFirstKey set in LoadKeyMetadata + pwallet->LoadKeyMetadata(vchPubKey, keyMeta); + } else + if (strType == "sxKeyMeta") + { + if (fDebug) + LogPrintf("WalletDB ReadKeyValue sxKeyMeta\n"); + + CKeyID keyId; + ssKey >> keyId; + CStealthKeyMetadata sxKeyMeta; + ssValue >> sxKeyMeta; + + pwallet->mapStealthKeyMeta[keyId] = sxKeyMeta; + } else + if (strType == "defaultkey") + { + ssValue >> pwallet->vchDefaultKey; + } else + if (strType == "lastfilteredheight") + { + ssValue >> pwallet->nLastFilteredHeight; + } else + if (strType == "pool") + { + int64_t nIndex; + ssKey >> nIndex; + CKeyPool keypool; + ssValue >> keypool; + pwallet->setKeyPool.insert(nIndex); + + // If no metadata exists yet, create a default with the pool key's + // creation time. Note that this may be overwritten by actually + // stored metadata for that key later, which is fine. + CKeyID keyid = keypool.vchPubKey.GetID(); + if (pwallet->mapKeyMetadata.count(keyid) == 0) + pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime); + + } else + if (strType == "version") + { + ssValue >> wss.nFileVersion; + if (wss.nFileVersion == 10300) + wss.nFileVersion = 300; + } else + if (strType == "cscript") + { + uint160 hash; + ssKey >> hash; + CScript script; + ssValue >> script; + if (!pwallet->LoadCScript(script)) + { + strErr = "Error reading wallet database: LoadCScript failed"; + return false; + }; + } else + if (strType == "orderposnext") + { + ssValue >> pwallet->nOrderPosNext; + }; + } catch (...) + { + return false; + }; + return true; +} + +static bool IsKeyType(string strType) +{ + return (strType== "key" || strType == "wkey" || + strType == "mkey" || strType == "ckey"); +} + +DBErrors CWalletDB::LoadWallet(CWallet* pwallet, int& oldWalletVersion, std::function funcProgress) +{ + pwallet->vchDefaultKey = CPubKey(); + CWalletScanState wss; + bool fNoncriticalErrors = false; + DBErrors result = DB_LOAD_OK; + + try { + LOCK(pwallet->cs_wallet); + int nMinVersion = 0; + if (Read((string)"minversion", nMinVersion)) + { + if (nMinVersion > CLIENT_VERSION) + return DB_TOO_NEW; + pwallet->LoadMinVersion(nMinVersion); + }; + + // Get cursor + Dbc* pcursor = GetCursor(); + if (!pcursor) + { + LogPrintf("Error getting wallet database cursor\n"); + return DB_CORRUPT; + }; + + uint32_t count = 0; + while (true) + { + if (funcProgress && count != 0 && count % 10000 == 0) funcProgress(count); + count++; + + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue); + if (ret == DB_NOTFOUND) + { + break; + } else + if (ret != 0) + { + LogPrintf("Error reading next record from wallet database\n"); + return DB_CORRUPT; + }; + + // Try to be tolerant of single corrupt records: + string strType, strErr; + if (!ReadKeyValue(pwallet, ssKey, ssValue, wss, strType, strErr)) + { + // losing keys is considered a catastrophic error, anything else + // we assume the user can live with: + if (IsKeyType(strType)) + { + result = DB_CORRUPT; + } else + { + // Leave other errors alone, if we try to fix them we might make things worse. + fNoncriticalErrors = true; // ... but do warn the user there is something wrong. + if (strType == "tx") + // Rescan if there is a bad transaction record: + SoftSetBoolArg("-rescan", true); + }; + }; + if (!strErr.empty()) + LogPrintf("%s\n", strErr.c_str()); + }; + pcursor->close(); + if (funcProgress) funcProgress(count); + } catch (...) + { + result = DB_CORRUPT; + } + + if (fNoncriticalErrors && result == DB_LOAD_OK) + result = DB_NONCRITICAL_ERROR; + + // Any wallet corruption at all: skip any rewriting or + // upgrading, we don't want to make it worse. + if (result != DB_LOAD_OK) + return result; + + LogPrintf("nFileVersion = %d\n", wss.nFileVersion); + + LogPrintf("Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total\n", + wss.nKeys, wss.nCKeys, wss.nKeyMeta, wss.nKeys + wss.nCKeys); + + // nTimeFirstKey is only reliable if all keys have metadata + if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta) + pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value' + + for (const uint256& hash : wss.vWalletUpgrade) + WriteTx(hash, pwallet->mapWallet[hash]); + + // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: + if (wss.fIsEncrypted && (wss.nFileVersion == 40000 || wss.nFileVersion == 50000)) + return DB_NEED_REWRITE; + + if (wss.nFileVersion < CLIENT_VERSION) { // Update + oldWalletVersion = wss.nFileVersion; + WriteVersion(CLIENT_VERSION); + } + + // Add Development Contribution Address to address book + pwallet->mapAddressBook[CBitcoinAddress(Params().GetDevContributionAddress()).Get()] = "Alias Foundation"; + + if (wss.fAnyUnordered) + result = ReorderTransactions(pwallet); + + return result; +} + +void ThreadFlushWalletDB(const std::string& strFile) +{ + static bool fOneThread; + if (fOneThread) + return; + fOneThread = true; + if (!GetBoolArg("-flushwallet", true)) + return; + + unsigned int nLastSeen = nWalletDBUpdated; + unsigned int nLastFlushed = nWalletDBUpdated; + int64_t nLastWalletUpdate = GetTime(); + for (;;) + { + boost::this_thread::interruption_point(); + MilliSleep(500); + + if (nLastSeen != nWalletDBUpdated) + { + nLastSeen = nWalletDBUpdated; + nLastWalletUpdate = GetTime(); + }; + + if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) + { + TRY_LOCK(bitdb.cs_db,lockDb); + if (lockDb) + { + // Don't do this if any databases are in use + int nRefCount = 0; + map::iterator mi = bitdb.mapFileUseCount.begin(); + while (mi != bitdb.mapFileUseCount.end()) + { + nRefCount += (*mi).second; + mi++; + }; + + if (nRefCount == 0) + { + boost::this_thread::interruption_point(); + map::iterator mi = bitdb.mapFileUseCount.find(strFile); + if (mi != bitdb.mapFileUseCount.end()) + { + LogPrintf("Flushing wallet.dat\n"); + nLastFlushed = nWalletDBUpdated; + int64_t nStart = GetTimeMillis(); + + // Flush wallet.dat so it's self contained + bitdb.CloseDb(strFile); + bitdb.CheckpointLSN(strFile); + + bitdb.mapFileUseCount.erase(mi++); + LogPrintf("Flushed wallet.dat %dms\n", GetTimeMillis() - nStart); + }; + }; + }; + }; + }; +} + +bool BackupWallet(const CWallet& wallet, const string& strDest) +{ + if (!wallet.fFileBacked) + return false; + for (;;) + { + boost::this_thread::interruption_point(); + { + LOCK(bitdb.cs_db); + if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0) + { + // Flush log data to the dat file + bitdb.CloseDb(wallet.strWalletFile); + bitdb.CheckpointLSN(wallet.strWalletFile); + bitdb.mapFileUseCount.erase(wallet.strWalletFile); + + // Copy wallet.dat + fs::path pathSrc = GetDataDir() / wallet.strWalletFile; + fs::path pathDest(strDest); + if (fs::is_directory(pathDest)) + pathDest /= wallet.strWalletFile; + + try { +#if BOOST_VERSION >= 104000 + fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists); +#else + fs::copy_file(pathSrc, pathDest); +#endif + LogPrintf("copied wallet.dat to %s\n", pathDest.string().c_str()); + return true; + } catch(const fs::filesystem_error &e) + { + LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string().c_str(), e.what()); + return false; + }; + }; + } + MilliSleep(100); + }; + return false; +} + +// +// Try to (very carefully!) recover wallet.dat if there is a problem. +// +bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys) +{ + // Recovery procedure: + // move wallet.dat to wallet.timestamp.bak + // Call Salvage with fAggressive=true to + // get as much data as possible. + // Rewrite salvaged data to wallet.dat + // Set -rescan so any missing transactions will be + // found. + int64_t now = GetTime(); + std::string newFilename = strprintf("wallet.%d.bak", now); + + int result = dbenv.dbenv.dbrename(nullptr, filename.c_str(), nullptr, + newFilename.c_str(), DB_AUTO_COMMIT); + if (result == 0) + { + LogPrintf("Renamed %s to %s\n", filename.c_str(), newFilename.c_str()); + } else + { + LogPrintf("Failed to rename %s to %s\n", filename.c_str(), newFilename.c_str()); + return false; + }; + + std::vector salvagedData; + bool allOK = dbenv.Salvage(newFilename, true, salvagedData); + if (salvagedData.empty()) + { + LogPrintf("Salvage(aggressive) found no records in %s.\n", newFilename.c_str()); + return false; + }; + + LogPrintf("Salvage(aggressive) found %u records\n", salvagedData.size()); + + bool fSuccess = allOK; + Db* pdbCopy = new Db(&dbenv.dbenv, 0); + int ret = pdbCopy->open(nullptr, // Txn pointer + filename.c_str(), // Filename + "main", // Logical db name + DB_BTREE, // Database type + DB_CREATE, // Flags + 0); + if (ret > 0) + { + LogPrintf("Cannot create database file %s\n", filename.c_str()); + return false; + }; + CWallet dummyWallet; + CWalletScanState wss; + + DbTxn* ptxn = dbenv.TxnBegin(); + for (CDBEnv::KeyValPair& row : salvagedData) + { + if (fOnlyKeys) + { + CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION); + CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); + string strType, strErr; + bool fReadOK = ReadKeyValue(&dummyWallet, ssKey, ssValue, + wss, strType, strErr); + if (!IsKeyType(strType)) + continue; + + if (!fReadOK) + { + LogPrintf("WARNING: CWalletDB::Recover skipping %s: %s\n", strType.c_str(), strErr.c_str()); + continue; + }; + }; + Dbt datKey(&row.first[0], row.first.size()); + Dbt datValue(&row.second[0], row.second.size()); + int ret2 = pdbCopy->put(ptxn, &datKey, &datValue, DB_NOOVERWRITE); + if (ret2 > 0) + fSuccess = false; + }; + ptxn->commit(0); + pdbCopy->close(0); + delete pdbCopy; + + return fSuccess; +} + +bool CWalletDB::Recover(CDBEnv& dbenv, std::string filename) +{ + return CWalletDB::Recover(dbenv, filename, false); +} diff --git a/src/wordlists/spanish.h b/src/wordlists/spanish.h index e8e64af078..7fa202d491 100644 --- a/src/wordlists/spanish.h +++ b/src/wordlists/spanish.h @@ -1,1170 +1,337 @@ -unsigned char spanish_txt[] = { - 0x61, 0xcc, 0x81, 0x62, 0x61, 0x63, 0x6f, 0x0a, 0x61, 0x62, 0x64, 0x6f, - 0x6d, 0x65, 0x6e, 0x0a, 0x61, 0x62, 0x65, 0x6a, 0x61, 0x0a, 0x61, 0x62, - 0x69, 0x65, 0x72, 0x74, 0x6f, 0x0a, 0x61, 0x62, 0x6f, 0x67, 0x61, 0x64, - 0x6f, 0x0a, 0x61, 0x62, 0x6f, 0x6e, 0x6f, 0x0a, 0x61, 0x62, 0x6f, 0x72, - 0x74, 0x6f, 0x0a, 0x61, 0x62, 0x72, 0x61, 0x7a, 0x6f, 0x0a, 0x61, 0x62, - 0x72, 0x69, 0x72, 0x0a, 0x61, 0x62, 0x75, 0x65, 0x6c, 0x6f, 0x0a, 0x61, - 0x62, 0x75, 0x73, 0x6f, 0x0a, 0x61, 0x63, 0x61, 0x62, 0x61, 0x72, 0x0a, - 0x61, 0x63, 0x61, 0x64, 0x65, 0x6d, 0x69, 0x61, 0x0a, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x6f, 0x0a, 0x61, 0x63, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x61, 0x63, 0x65, 0x69, 0x74, 0x65, 0x0a, 0x61, 0x63, 0x65, 0x6c, - 0x67, 0x61, 0x0a, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x61, 0x63, - 0x65, 0x70, 0x74, 0x61, 0x72, 0x0a, 0x61, 0xcc, 0x81, 0x63, 0x69, 0x64, - 0x6f, 0x0a, 0x61, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x72, 0x0a, 0x61, 0x63, - 0x6e, 0x65, 0xcc, 0x81, 0x0a, 0x61, 0x63, 0x6f, 0x67, 0x65, 0x72, 0x0a, - 0x61, 0x63, 0x6f, 0x73, 0x6f, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x6f, - 0x0a, 0x61, 0x63, 0x74, 0x6f, 0x0a, 0x61, 0x63, 0x74, 0x72, 0x69, 0x7a, - 0x0a, 0x61, 0x63, 0x74, 0x75, 0x61, 0x72, 0x0a, 0x61, 0x63, 0x75, 0x64, - 0x69, 0x72, 0x0a, 0x61, 0x63, 0x75, 0x65, 0x72, 0x64, 0x6f, 0x0a, 0x61, - 0x63, 0x75, 0x73, 0x61, 0x72, 0x0a, 0x61, 0x64, 0x69, 0x63, 0x74, 0x6f, - 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x74, 0x69, 0x72, 0x0a, 0x61, 0x64, 0x6f, - 0x70, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x6f, 0x0a, - 0x61, 0x64, 0x75, 0x61, 0x6e, 0x61, 0x0a, 0x61, 0x64, 0x75, 0x6c, 0x74, - 0x6f, 0x0a, 0x61, 0x65, 0xcc, 0x81, 0x72, 0x65, 0x6f, 0x0a, 0x61, 0x66, - 0x65, 0x63, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x66, 0x69, 0x63, 0x69, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x61, 0x66, 0x69, 0x6e, 0x61, 0x72, 0x0a, 0x61, - 0x66, 0x69, 0x72, 0x6d, 0x61, 0x72, 0x0a, 0x61, 0xcc, 0x81, 0x67, 0x69, - 0x6c, 0x0a, 0x61, 0x67, 0x69, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x67, 0x6f, - 0x6e, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, - 0x0a, 0x61, 0x67, 0x6f, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x72, 0x0a, 0x61, 0x67, 0x72, 0x69, 0x6f, 0x0a, 0x61, 0x67, - 0x75, 0x61, 0x0a, 0x61, 0x67, 0x75, 0x64, 0x6f, 0x0a, 0x61, 0xcc, 0x81, - 0x67, 0x75, 0x69, 0x6c, 0x61, 0x0a, 0x61, 0x67, 0x75, 0x6a, 0x61, 0x0a, - 0x61, 0x68, 0x6f, 0x67, 0x6f, 0x0a, 0x61, 0x68, 0x6f, 0x72, 0x72, 0x6f, - 0x0a, 0x61, 0x69, 0x72, 0x65, 0x0a, 0x61, 0x69, 0x73, 0x6c, 0x61, 0x72, - 0x0a, 0x61, 0x6a, 0x65, 0x64, 0x72, 0x65, 0x7a, 0x0a, 0x61, 0x6a, 0x65, - 0x6e, 0x6f, 0x0a, 0x61, 0x6a, 0x75, 0x73, 0x74, 0x65, 0x0a, 0x61, 0x6c, - 0x61, 0x63, 0x72, 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x61, 0x6c, 0x61, 0x6d, - 0x62, 0x72, 0x65, 0x0a, 0x61, 0x6c, 0x61, 0x72, 0x6d, 0x61, 0x0a, 0x61, - 0x6c, 0x62, 0x61, 0x0a, 0x61, 0xcc, 0x81, 0x6c, 0x62, 0x75, 0x6d, 0x0a, - 0x61, 0x6c, 0x63, 0x61, 0x6c, 0x64, 0x65, 0x0a, 0x61, 0x6c, 0x64, 0x65, - 0x61, 0x0a, 0x61, 0x6c, 0x65, 0x67, 0x72, 0x65, 0x0a, 0x61, 0x6c, 0x65, - 0x6a, 0x61, 0x72, 0x0a, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x61, 0x0a, 0x61, - 0x6c, 0x65, 0x74, 0x61, 0x0a, 0x61, 0x6c, 0x66, 0x69, 0x6c, 0x65, 0x72, - 0x0a, 0x61, 0x6c, 0x67, 0x61, 0x0a, 0x61, 0x6c, 0x67, 0x6f, 0x64, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x61, 0x6c, 0x69, 0x61, 0x64, 0x6f, 0x0a, 0x61, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x61, 0x6c, 0x69, 0x76, 0x69, - 0x6f, 0x0a, 0x61, 0x6c, 0x6d, 0x61, 0x0a, 0x61, 0x6c, 0x6d, 0x65, 0x6a, - 0x61, 0x0a, 0x61, 0x6c, 0x6d, 0x69, 0xcc, 0x81, 0x62, 0x61, 0x72, 0x0a, - 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x6c, 0x74, 0x65, 0x7a, 0x61, - 0x0a, 0x61, 0x6c, 0x74, 0x69, 0x76, 0x6f, 0x0a, 0x61, 0x6c, 0x74, 0x6f, - 0x0a, 0x61, 0x6c, 0x74, 0x75, 0x72, 0x61, 0x0a, 0x61, 0x6c, 0x75, 0x6d, - 0x6e, 0x6f, 0x0a, 0x61, 0x6c, 0x7a, 0x61, 0x72, 0x0a, 0x61, 0x6d, 0x61, - 0x62, 0x6c, 0x65, 0x0a, 0x61, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x0a, 0x61, - 0x6d, 0x61, 0x70, 0x6f, 0x6c, 0x61, 0x0a, 0x61, 0x6d, 0x61, 0x72, 0x67, - 0x6f, 0x0a, 0x61, 0x6d, 0x61, 0x73, 0x61, 0x72, 0x0a, 0x61, 0xcc, 0x81, - 0x6d, 0x62, 0x61, 0x72, 0x0a, 0x61, 0xcc, 0x81, 0x6d, 0x62, 0x69, 0x74, - 0x6f, 0x0a, 0x61, 0x6d, 0x65, 0x6e, 0x6f, 0x0a, 0x61, 0x6d, 0x69, 0x67, - 0x6f, 0x0a, 0x61, 0x6d, 0x69, 0x73, 0x74, 0x61, 0x64, 0x0a, 0x61, 0x6d, - 0x6f, 0x72, 0x0a, 0x61, 0x6d, 0x70, 0x61, 0x72, 0x6f, 0x0a, 0x61, 0x6d, - 0x70, 0x6c, 0x69, 0x6f, 0x0a, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x0a, 0x61, - 0x6e, 0x63, 0x69, 0x61, 0x6e, 0x6f, 0x0a, 0x61, 0x6e, 0x63, 0x6c, 0x61, - 0x0a, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x0a, 0x61, 0x6e, 0x64, 0x65, 0xcc, - 0x81, 0x6e, 0x0a, 0x61, 0x6e, 0x65, 0x6d, 0x69, 0x61, 0x0a, 0x61, 0xcc, - 0x81, 0x6e, 0x67, 0x75, 0x6c, 0x6f, 0x0a, 0x61, 0x6e, 0x69, 0x6c, 0x6c, - 0x6f, 0x0a, 0x61, 0xcc, 0x81, 0x6e, 0x69, 0x6d, 0x6f, 0x0a, 0x61, 0x6e, - 0x69, 0xcc, 0x81, 0x73, 0x0a, 0x61, 0x6e, 0x6f, 0x74, 0x61, 0x72, 0x0a, - 0x61, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x0a, 0x61, 0x6e, 0x74, 0x69, 0x67, - 0x75, 0x6f, 0x0a, 0x61, 0x6e, 0x74, 0x6f, 0x6a, 0x6f, 0x0a, 0x61, 0x6e, - 0x75, 0x61, 0x6c, 0x0a, 0x61, 0x6e, 0x75, 0x6c, 0x61, 0x72, 0x0a, 0x61, - 0x6e, 0x75, 0x6e, 0x63, 0x69, 0x6f, 0x0a, 0x61, 0x6e, 0xcc, 0x83, 0x61, - 0x64, 0x69, 0x72, 0x0a, 0x61, 0x6e, 0xcc, 0x83, 0x65, 0x6a, 0x6f, 0x0a, - 0x61, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x61, 0x70, 0x61, 0x67, 0x61, 0x72, - 0x0a, 0x61, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x0a, 0x61, 0x70, 0x65, - 0x74, 0x69, 0x74, 0x6f, 0x0a, 0x61, 0x70, 0x69, 0x6f, 0x0a, 0x61, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x6f, 0x64, 0x6f, 0x0a, - 0x61, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x0a, 0x61, 0x70, 0x6f, 0x79, 0x6f, - 0x0a, 0x61, 0x70, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x0a, 0x61, 0x70, - 0x72, 0x6f, 0x62, 0x61, 0x72, 0x0a, 0x61, 0x70, 0x75, 0x65, 0x73, 0x74, - 0x61, 0x0a, 0x61, 0x70, 0x75, 0x72, 0x6f, 0x0a, 0x61, 0x72, 0x61, 0x64, - 0x6f, 0x0a, 0x61, 0x72, 0x61, 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x61, 0x72, - 0x61, 0x72, 0x0a, 0x61, 0xcc, 0x81, 0x72, 0x62, 0x69, 0x74, 0x72, 0x6f, - 0x0a, 0x61, 0xcc, 0x81, 0x72, 0x62, 0x6f, 0x6c, 0x0a, 0x61, 0x72, 0x62, - 0x75, 0x73, 0x74, 0x6f, 0x0a, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x6f, - 0x0a, 0x61, 0x72, 0x63, 0x6f, 0x0a, 0x61, 0x72, 0x64, 0x65, 0x72, 0x0a, - 0x61, 0x72, 0x64, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x61, 0x72, 0x64, 0x75, - 0x6f, 0x0a, 0x61, 0xcc, 0x81, 0x72, 0x65, 0x61, 0x0a, 0x61, 0xcc, 0x81, - 0x72, 0x69, 0x64, 0x6f, 0x0a, 0x61, 0x72, 0x69, 0x65, 0x73, 0x0a, 0x61, - 0x72, 0x6d, 0x6f, 0x6e, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x61, 0x72, 0x6e, - 0x65, 0xcc, 0x81, 0x73, 0x0a, 0x61, 0x72, 0x6f, 0x6d, 0x61, 0x0a, 0x61, - 0x72, 0x70, 0x61, 0x0a, 0x61, 0x72, 0x70, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x61, 0x72, 0x72, 0x65, 0x67, 0x6c, 0x6f, 0x0a, 0x61, 0x72, 0x72, 0x6f, - 0x7a, 0x0a, 0x61, 0x72, 0x72, 0x75, 0x67, 0x61, 0x0a, 0x61, 0x72, 0x74, - 0x65, 0x0a, 0x61, 0x72, 0x74, 0x69, 0x73, 0x74, 0x61, 0x0a, 0x61, 0x73, - 0x61, 0x0a, 0x61, 0x73, 0x61, 0x64, 0x6f, 0x0a, 0x61, 0x73, 0x61, 0x6c, - 0x74, 0x6f, 0x0a, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x73, 0x6f, 0x0a, 0x61, - 0x73, 0x65, 0x67, 0x75, 0x72, 0x61, 0x72, 0x0a, 0x61, 0x73, 0x65, 0x6f, - 0x0a, 0x61, 0x73, 0x65, 0x73, 0x6f, 0x72, 0x0a, 0x61, 0x73, 0x69, 0x65, - 0x6e, 0x74, 0x6f, 0x0a, 0x61, 0x73, 0x69, 0x6c, 0x6f, 0x0a, 0x61, 0x73, - 0x69, 0x73, 0x74, 0x69, 0x72, 0x0a, 0x61, 0x73, 0x6e, 0x6f, 0x0a, 0x61, - 0x73, 0x6f, 0x6d, 0x62, 0x72, 0x6f, 0x0a, 0x61, 0xcc, 0x81, 0x73, 0x70, - 0x65, 0x72, 0x6f, 0x0a, 0x61, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x61, 0x0a, - 0x61, 0x73, 0x74, 0x72, 0x6f, 0x0a, 0x61, 0x73, 0x74, 0x75, 0x74, 0x6f, - 0x0a, 0x61, 0x73, 0x75, 0x6d, 0x69, 0x72, 0x0a, 0x61, 0x73, 0x75, 0x6e, - 0x74, 0x6f, 0x0a, 0x61, 0x74, 0x61, 0x6a, 0x6f, 0x0a, 0x61, 0x74, 0x61, - 0x71, 0x75, 0x65, 0x0a, 0x61, 0x74, 0x61, 0x72, 0x0a, 0x61, 0x74, 0x65, - 0x6e, 0x74, 0x6f, 0x0a, 0x61, 0x74, 0x65, 0x6f, 0x0a, 0x61, 0xcc, 0x81, - 0x74, 0x69, 0x63, 0x6f, 0x0a, 0x61, 0x74, 0x6c, 0x65, 0x74, 0x61, 0x0a, - 0x61, 0xcc, 0x81, 0x74, 0x6f, 0x6d, 0x6f, 0x0a, 0x61, 0x74, 0x72, 0x61, - 0x65, 0x72, 0x0a, 0x61, 0x74, 0x72, 0x6f, 0x7a, 0x0a, 0x61, 0x74, 0x75, - 0xcc, 0x81, 0x6e, 0x0a, 0x61, 0x75, 0x64, 0x61, 0x7a, 0x0a, 0x61, 0x75, - 0x64, 0x69, 0x6f, 0x0a, 0x61, 0x75, 0x67, 0x65, 0x0a, 0x61, 0x75, 0x6c, - 0x61, 0x0a, 0x61, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x61, 0x75, - 0x73, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x61, 0x75, 0x74, 0x6f, 0x72, 0x0a, - 0x61, 0x76, 0x61, 0x6c, 0x0a, 0x61, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x0a, - 0x61, 0x76, 0x61, 0x72, 0x6f, 0x0a, 0x61, 0x76, 0x65, 0x0a, 0x61, 0x76, - 0x65, 0x6c, 0x6c, 0x61, 0x6e, 0x61, 0x0a, 0x61, 0x76, 0x65, 0x6e, 0x61, - 0x0a, 0x61, 0x76, 0x65, 0x73, 0x74, 0x72, 0x75, 0x7a, 0x0a, 0x61, 0x76, - 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x61, 0x76, 0x69, 0x73, 0x6f, 0x0a, - 0x61, 0x79, 0x65, 0x72, 0x0a, 0x61, 0x79, 0x75, 0x64, 0x61, 0x0a, 0x61, - 0x79, 0x75, 0x6e, 0x6f, 0x0a, 0x61, 0x7a, 0x61, 0x66, 0x72, 0x61, 0xcc, - 0x81, 0x6e, 0x0a, 0x61, 0x7a, 0x61, 0x72, 0x0a, 0x61, 0x7a, 0x6f, 0x74, - 0x65, 0x0a, 0x61, 0x7a, 0x75, 0xcc, 0x81, 0x63, 0x61, 0x72, 0x0a, 0x61, - 0x7a, 0x75, 0x66, 0x72, 0x65, 0x0a, 0x61, 0x7a, 0x75, 0x6c, 0x0a, 0x62, - 0x61, 0x62, 0x61, 0x0a, 0x62, 0x61, 0x62, 0x6f, 0x72, 0x0a, 0x62, 0x61, - 0x63, 0x68, 0x65, 0x0a, 0x62, 0x61, 0x68, 0x69, 0xcc, 0x81, 0x61, 0x0a, - 0x62, 0x61, 0x69, 0x6c, 0x65, 0x0a, 0x62, 0x61, 0x6a, 0x61, 0x72, 0x0a, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x7a, 0x61, 0x0a, 0x62, 0x61, 0x6c, 0x63, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x62, 0x61, 0x6c, 0x64, 0x65, 0x0a, 0x62, - 0x61, 0x6d, 0x62, 0x75, 0xcc, 0x81, 0x0a, 0x62, 0x61, 0x6e, 0x63, 0x6f, - 0x0a, 0x62, 0x61, 0x6e, 0x64, 0x61, 0x0a, 0x62, 0x61, 0x6e, 0xcc, 0x83, - 0x6f, 0x0a, 0x62, 0x61, 0x72, 0x62, 0x61, 0x0a, 0x62, 0x61, 0x72, 0x63, - 0x6f, 0x0a, 0x62, 0x61, 0x72, 0x6e, 0x69, 0x7a, 0x0a, 0x62, 0x61, 0x72, - 0x72, 0x6f, 0x0a, 0x62, 0x61, 0xcc, 0x81, 0x73, 0x63, 0x75, 0x6c, 0x61, - 0x0a, 0x62, 0x61, 0x73, 0x74, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x62, 0x61, - 0x73, 0x75, 0x72, 0x61, 0x0a, 0x62, 0x61, 0x74, 0x61, 0x6c, 0x6c, 0x61, - 0x0a, 0x62, 0x61, 0x74, 0x65, 0x72, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x62, - 0x61, 0x74, 0x69, 0x72, 0x0a, 0x62, 0x61, 0x74, 0x75, 0x74, 0x61, 0x0a, - 0x62, 0x61, 0x75, 0xcc, 0x81, 0x6c, 0x0a, 0x62, 0x61, 0x7a, 0x61, 0x72, - 0x0a, 0x62, 0x65, 0x62, 0x65, 0xcc, 0x81, 0x0a, 0x62, 0x65, 0x62, 0x69, - 0x64, 0x61, 0x0a, 0x62, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x62, 0x65, 0x73, - 0x61, 0x72, 0x0a, 0x62, 0x65, 0x73, 0x6f, 0x0a, 0x62, 0x65, 0x73, 0x74, - 0x69, 0x61, 0x0a, 0x62, 0x69, 0x63, 0x68, 0x6f, 0x0a, 0x62, 0x69, 0x65, - 0x6e, 0x0a, 0x62, 0x69, 0x6e, 0x67, 0x6f, 0x0a, 0x62, 0x6c, 0x61, 0x6e, - 0x63, 0x6f, 0x0a, 0x62, 0x6c, 0x6f, 0x71, 0x75, 0x65, 0x0a, 0x62, 0x6c, - 0x75, 0x73, 0x61, 0x0a, 0x62, 0x6f, 0x61, 0x0a, 0x62, 0x6f, 0x62, 0x69, - 0x6e, 0x61, 0x0a, 0x62, 0x6f, 0x62, 0x6f, 0x0a, 0x62, 0x6f, 0x63, 0x61, - 0x0a, 0x62, 0x6f, 0x63, 0x69, 0x6e, 0x61, 0x0a, 0x62, 0x6f, 0x64, 0x61, - 0x0a, 0x62, 0x6f, 0x64, 0x65, 0x67, 0x61, 0x0a, 0x62, 0x6f, 0x69, 0x6e, - 0x61, 0x0a, 0x62, 0x6f, 0x6c, 0x61, 0x0a, 0x62, 0x6f, 0x6c, 0x65, 0x72, - 0x6f, 0x0a, 0x62, 0x6f, 0x6c, 0x73, 0x61, 0x0a, 0x62, 0x6f, 0x6d, 0x62, - 0x61, 0x0a, 0x62, 0x6f, 0x6e, 0x64, 0x61, 0x64, 0x0a, 0x62, 0x6f, 0x6e, - 0x69, 0x74, 0x6f, 0x0a, 0x62, 0x6f, 0x6e, 0x6f, 0x0a, 0x62, 0x6f, 0x6e, - 0x73, 0x61, 0xcc, 0x81, 0x69, 0x0a, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x0a, - 0x62, 0x6f, 0x72, 0x72, 0x61, 0x72, 0x0a, 0x62, 0x6f, 0x73, 0x71, 0x75, - 0x65, 0x0a, 0x62, 0x6f, 0x74, 0x65, 0x0a, 0x62, 0x6f, 0x74, 0x69, 0xcc, - 0x81, 0x6e, 0x0a, 0x62, 0x6f, 0xcc, 0x81, 0x76, 0x65, 0x64, 0x61, 0x0a, - 0x62, 0x6f, 0x7a, 0x61, 0x6c, 0x0a, 0x62, 0x72, 0x61, 0x76, 0x6f, 0x0a, - 0x62, 0x72, 0x61, 0x7a, 0x6f, 0x0a, 0x62, 0x72, 0x65, 0x63, 0x68, 0x61, - 0x0a, 0x62, 0x72, 0x65, 0x76, 0x65, 0x0a, 0x62, 0x72, 0x69, 0x6c, 0x6c, - 0x6f, 0x0a, 0x62, 0x72, 0x69, 0x6e, 0x63, 0x6f, 0x0a, 0x62, 0x72, 0x69, - 0x73, 0x61, 0x0a, 0x62, 0x72, 0x6f, 0x63, 0x61, 0x0a, 0x62, 0x72, 0x6f, - 0x6d, 0x61, 0x0a, 0x62, 0x72, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x62, 0x72, - 0x6f, 0x74, 0x65, 0x0a, 0x62, 0x72, 0x75, 0x6a, 0x61, 0x0a, 0x62, 0x72, - 0x75, 0x73, 0x63, 0x6f, 0x0a, 0x62, 0x72, 0x75, 0x74, 0x6f, 0x0a, 0x62, - 0x75, 0x63, 0x65, 0x6f, 0x0a, 0x62, 0x75, 0x63, 0x6c, 0x65, 0x0a, 0x62, - 0x75, 0x65, 0x6e, 0x6f, 0x0a, 0x62, 0x75, 0x65, 0x79, 0x0a, 0x62, 0x75, - 0x66, 0x61, 0x6e, 0x64, 0x61, 0x0a, 0x62, 0x75, 0x66, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x62, 0x75, 0xcc, 0x81, 0x68, 0x6f, 0x0a, 0x62, 0x75, 0x69, - 0x74, 0x72, 0x65, 0x0a, 0x62, 0x75, 0x6c, 0x74, 0x6f, 0x0a, 0x62, 0x75, - 0x72, 0x62, 0x75, 0x6a, 0x61, 0x0a, 0x62, 0x75, 0x72, 0x6c, 0x61, 0x0a, - 0x62, 0x75, 0x72, 0x72, 0x6f, 0x0a, 0x62, 0x75, 0x73, 0x63, 0x61, 0x72, - 0x0a, 0x62, 0x75, 0x74, 0x61, 0x63, 0x61, 0x0a, 0x62, 0x75, 0x7a, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x61, 0x62, 0x61, 0x6c, 0x6c, 0x6f, 0x0a, - 0x63, 0x61, 0x62, 0x65, 0x7a, 0x61, 0x0a, 0x63, 0x61, 0x62, 0x69, 0x6e, - 0x61, 0x0a, 0x63, 0x61, 0x62, 0x72, 0x61, 0x0a, 0x63, 0x61, 0x63, 0x61, - 0x6f, 0x0a, 0x63, 0x61, 0x64, 0x61, 0xcc, 0x81, 0x76, 0x65, 0x72, 0x0a, - 0x63, 0x61, 0x64, 0x65, 0x6e, 0x61, 0x0a, 0x63, 0x61, 0x65, 0x72, 0x0a, - 0x63, 0x61, 0x66, 0x65, 0xcc, 0x81, 0x0a, 0x63, 0x61, 0x69, 0xcc, 0x81, - 0x64, 0x61, 0x0a, 0x63, 0x61, 0x69, 0x6d, 0x61, 0xcc, 0x81, 0x6e, 0x0a, - 0x63, 0x61, 0x6a, 0x61, 0x0a, 0x63, 0x61, 0x6a, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x63, 0x61, 0x6c, 0x0a, 0x63, 0x61, 0x6c, 0x61, 0x6d, 0x61, 0x72, - 0x0a, 0x63, 0x61, 0x6c, 0x63, 0x69, 0x6f, 0x0a, 0x63, 0x61, 0x6c, 0x64, - 0x6f, 0x0a, 0x63, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x64, 0x0a, 0x63, 0x61, - 0x6c, 0x6c, 0x65, 0x0a, 0x63, 0x61, 0x6c, 0x6d, 0x61, 0x0a, 0x63, 0x61, - 0x6c, 0x6f, 0x72, 0x0a, 0x63, 0x61, 0x6c, 0x76, 0x6f, 0x0a, 0x63, 0x61, - 0x6d, 0x61, 0x0a, 0x63, 0x61, 0x6d, 0x62, 0x69, 0x6f, 0x0a, 0x63, 0x61, - 0x6d, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x63, 0x61, 0x6d, 0x69, 0x6e, 0x6f, - 0x0a, 0x63, 0x61, 0x6d, 0x70, 0x6f, 0x0a, 0x63, 0x61, 0xcc, 0x81, 0x6e, - 0x63, 0x65, 0x72, 0x0a, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x6c, 0x0a, 0x63, - 0x61, 0x6e, 0x65, 0x6c, 0x61, 0x0a, 0x63, 0x61, 0x6e, 0x67, 0x75, 0x72, - 0x6f, 0x0a, 0x63, 0x61, 0x6e, 0x69, 0x63, 0x61, 0x0a, 0x63, 0x61, 0x6e, - 0x74, 0x6f, 0x0a, 0x63, 0x61, 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x63, 0x61, - 0x6e, 0xcc, 0x83, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x61, 0x6f, 0x62, - 0x61, 0x0a, 0x63, 0x61, 0x6f, 0x73, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x7a, - 0x0a, 0x63, 0x61, 0x70, 0x69, 0x74, 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x63, - 0x61, 0x70, 0x6f, 0x74, 0x65, 0x0a, 0x63, 0x61, 0x70, 0x74, 0x61, 0x72, - 0x0a, 0x63, 0x61, 0x70, 0x75, 0x63, 0x68, 0x61, 0x0a, 0x63, 0x61, 0x72, - 0x61, 0x0a, 0x63, 0x61, 0x72, 0x62, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x63, - 0x61, 0xcc, 0x81, 0x72, 0x63, 0x65, 0x6c, 0x0a, 0x63, 0x61, 0x72, 0x65, - 0x74, 0x61, 0x0a, 0x63, 0x61, 0x72, 0x67, 0x61, 0x0a, 0x63, 0x61, 0x72, - 0x69, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x63, 0x61, 0x72, 0x6e, 0x65, 0x0a, - 0x63, 0x61, 0x72, 0x70, 0x65, 0x74, 0x61, 0x0a, 0x63, 0x61, 0x72, 0x72, - 0x6f, 0x0a, 0x63, 0x61, 0x72, 0x74, 0x61, 0x0a, 0x63, 0x61, 0x73, 0x61, - 0x0a, 0x63, 0x61, 0x73, 0x63, 0x6f, 0x0a, 0x63, 0x61, 0x73, 0x65, 0x72, - 0x6f, 0x0a, 0x63, 0x61, 0x73, 0x70, 0x61, 0x0a, 0x63, 0x61, 0x73, 0x74, - 0x6f, 0x72, 0x0a, 0x63, 0x61, 0x74, 0x6f, 0x72, 0x63, 0x65, 0x0a, 0x63, - 0x61, 0x74, 0x72, 0x65, 0x0a, 0x63, 0x61, 0x75, 0x64, 0x61, 0x6c, 0x0a, - 0x63, 0x61, 0x75, 0x73, 0x61, 0x0a, 0x63, 0x61, 0x7a, 0x6f, 0x0a, 0x63, - 0x65, 0x62, 0x6f, 0x6c, 0x6c, 0x61, 0x0a, 0x63, 0x65, 0x64, 0x65, 0x72, - 0x0a, 0x63, 0x65, 0x64, 0x72, 0x6f, 0x0a, 0x63, 0x65, 0x6c, 0x64, 0x61, - 0x0a, 0x63, 0x65, 0xcc, 0x81, 0x6c, 0x65, 0x62, 0x72, 0x65, 0x0a, 0x63, - 0x65, 0x6c, 0x6f, 0x73, 0x6f, 0x0a, 0x63, 0x65, 0xcc, 0x81, 0x6c, 0x75, - 0x6c, 0x61, 0x0a, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x63, - 0x65, 0x6e, 0x69, 0x7a, 0x61, 0x0a, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x6f, - 0x0a, 0x63, 0x65, 0x72, 0x63, 0x61, 0x0a, 0x63, 0x65, 0x72, 0x64, 0x6f, - 0x0a, 0x63, 0x65, 0x72, 0x65, 0x7a, 0x61, 0x0a, 0x63, 0x65, 0x72, 0x6f, - 0x0a, 0x63, 0x65, 0x72, 0x72, 0x61, 0x72, 0x0a, 0x63, 0x65, 0x72, 0x74, - 0x65, 0x7a, 0x61, 0x0a, 0x63, 0x65, 0xcc, 0x81, 0x73, 0x70, 0x65, 0x64, - 0x0a, 0x63, 0x65, 0x74, 0x72, 0x6f, 0x0a, 0x63, 0x68, 0x61, 0x63, 0x61, - 0x6c, 0x0a, 0x63, 0x68, 0x61, 0x6c, 0x65, 0x63, 0x6f, 0x0a, 0x63, 0x68, - 0x61, 0x6d, 0x70, 0x75, 0xcc, 0x81, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x63, - 0x6c, 0x61, 0x0a, 0x63, 0x68, 0x61, 0x70, 0x61, 0x0a, 0x63, 0x68, 0x61, - 0x72, 0x6c, 0x61, 0x0a, 0x63, 0x68, 0x69, 0x63, 0x6f, 0x0a, 0x63, 0x68, - 0x69, 0x73, 0x74, 0x65, 0x0a, 0x63, 0x68, 0x69, 0x76, 0x6f, 0x0a, 0x63, - 0x68, 0x6f, 0x71, 0x75, 0x65, 0x0a, 0x63, 0x68, 0x6f, 0x7a, 0x61, 0x0a, - 0x63, 0x68, 0x75, 0x6c, 0x65, 0x74, 0x61, 0x0a, 0x63, 0x68, 0x75, 0x70, - 0x61, 0x72, 0x0a, 0x63, 0x69, 0x63, 0x6c, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x63, 0x69, 0x65, 0x67, 0x6f, 0x0a, 0x63, 0x69, 0x65, 0x6c, 0x6f, 0x0a, - 0x63, 0x69, 0x65, 0x6e, 0x0a, 0x63, 0x69, 0x65, 0x72, 0x74, 0x6f, 0x0a, - 0x63, 0x69, 0x66, 0x72, 0x61, 0x0a, 0x63, 0x69, 0x67, 0x61, 0x72, 0x72, - 0x6f, 0x0a, 0x63, 0x69, 0x6d, 0x61, 0x0a, 0x63, 0x69, 0x6e, 0x63, 0x6f, - 0x0a, 0x63, 0x69, 0x6e, 0x65, 0x0a, 0x63, 0x69, 0x6e, 0x74, 0x61, 0x0a, - 0x63, 0x69, 0x70, 0x72, 0x65, 0xcc, 0x81, 0x73, 0x0a, 0x63, 0x69, 0x72, - 0x63, 0x6f, 0x0a, 0x63, 0x69, 0x72, 0x75, 0x65, 0x6c, 0x61, 0x0a, 0x63, - 0x69, 0x73, 0x6e, 0x65, 0x0a, 0x63, 0x69, 0x74, 0x61, 0x0a, 0x63, 0x69, - 0x75, 0x64, 0x61, 0x64, 0x0a, 0x63, 0x6c, 0x61, 0x6d, 0x6f, 0x72, 0x0a, - 0x63, 0x6c, 0x61, 0x6e, 0x0a, 0x63, 0x6c, 0x61, 0x72, 0x6f, 0x0a, 0x63, - 0x6c, 0x61, 0x73, 0x65, 0x0a, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x0a, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x63, 0x6c, 0x69, 0x6d, 0x61, - 0x0a, 0x63, 0x6c, 0x69, 0xcc, 0x81, 0x6e, 0x69, 0x63, 0x61, 0x0a, 0x63, - 0x6f, 0x62, 0x72, 0x65, 0x0a, 0x63, 0x6f, 0x63, 0x63, 0x69, 0x6f, 0xcc, - 0x81, 0x6e, 0x0a, 0x63, 0x6f, 0x63, 0x68, 0x69, 0x6e, 0x6f, 0x0a, 0x63, - 0x6f, 0x63, 0x69, 0x6e, 0x61, 0x0a, 0x63, 0x6f, 0x63, 0x6f, 0x0a, 0x63, - 0x6f, 0xcc, 0x81, 0x64, 0x69, 0x67, 0x6f, 0x0a, 0x63, 0x6f, 0x64, 0x6f, - 0x0a, 0x63, 0x6f, 0x66, 0x72, 0x65, 0x0a, 0x63, 0x6f, 0x67, 0x65, 0x72, - 0x0a, 0x63, 0x6f, 0x68, 0x65, 0x74, 0x65, 0x0a, 0x63, 0x6f, 0x6a, 0x69, - 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x6f, 0x6a, 0x6f, 0x0a, 0x63, 0x6f, 0x6c, - 0x61, 0x0a, 0x63, 0x6f, 0x6c, 0x63, 0x68, 0x61, 0x0a, 0x63, 0x6f, 0x6c, - 0x65, 0x67, 0x69, 0x6f, 0x0a, 0x63, 0x6f, 0x6c, 0x67, 0x61, 0x72, 0x0a, - 0x63, 0x6f, 0x6c, 0x69, 0x6e, 0x61, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x61, - 0x72, 0x0a, 0x63, 0x6f, 0x6c, 0x6d, 0x6f, 0x0a, 0x63, 0x6f, 0x6c, 0x75, - 0x6d, 0x6e, 0x61, 0x0a, 0x63, 0x6f, 0x6d, 0x62, 0x61, 0x74, 0x65, 0x0a, - 0x63, 0x6f, 0x6d, 0x65, 0x72, 0x0a, 0x63, 0x6f, 0x6d, 0x69, 0x64, 0x61, - 0x0a, 0x63, 0x6f, 0xcc, 0x81, 0x6d, 0x6f, 0x64, 0x6f, 0x0a, 0x63, 0x6f, - 0x6d, 0x70, 0x72, 0x61, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x65, 0x0a, 0x63, - 0x6f, 0x6e, 0x65, 0x6a, 0x6f, 0x0a, 0x63, 0x6f, 0x6e, 0x67, 0x61, 0x0a, - 0x63, 0x6f, 0x6e, 0x6f, 0x63, 0x65, 0x72, 0x0a, 0x63, 0x6f, 0x6e, 0x73, - 0x65, 0x6a, 0x6f, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x72, 0x0a, 0x63, - 0x6f, 0x70, 0x61, 0x0a, 0x63, 0x6f, 0x70, 0x69, 0x61, 0x0a, 0x63, 0x6f, - 0x72, 0x61, 0x7a, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x6f, 0x72, 0x62, - 0x61, 0x74, 0x61, 0x0a, 0x63, 0x6f, 0x72, 0x63, 0x68, 0x6f, 0x0a, 0x63, - 0x6f, 0x72, 0x64, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x6f, 0x72, 0x6f, - 0x6e, 0x61, 0x0a, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x72, 0x0a, 0x63, 0x6f, - 0x73, 0x65, 0x72, 0x0a, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x0a, 0x63, - 0x6f, 0x73, 0x74, 0x61, 0x0a, 0x63, 0x72, 0x61, 0xcc, 0x81, 0x6e, 0x65, - 0x6f, 0x0a, 0x63, 0x72, 0x61, 0xcc, 0x81, 0x74, 0x65, 0x72, 0x0a, 0x63, - 0x72, 0x65, 0x61, 0x72, 0x0a, 0x63, 0x72, 0x65, 0x63, 0x65, 0x72, 0x0a, - 0x63, 0x72, 0x65, 0x69, 0xcc, 0x81, 0x64, 0x6f, 0x0a, 0x63, 0x72, 0x65, - 0x6d, 0x61, 0x0a, 0x63, 0x72, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x63, 0x72, - 0x69, 0x6d, 0x65, 0x6e, 0x0a, 0x63, 0x72, 0x69, 0x70, 0x74, 0x61, 0x0a, - 0x63, 0x72, 0x69, 0x73, 0x69, 0x73, 0x0a, 0x63, 0x72, 0x6f, 0x6d, 0x6f, - 0x0a, 0x63, 0x72, 0x6f, 0xcc, 0x81, 0x6e, 0x69, 0x63, 0x61, 0x0a, 0x63, - 0x72, 0x6f, 0x71, 0x75, 0x65, 0x74, 0x61, 0x0a, 0x63, 0x72, 0x75, 0x64, - 0x6f, 0x0a, 0x63, 0x72, 0x75, 0x7a, 0x0a, 0x63, 0x75, 0x61, 0x64, 0x72, - 0x6f, 0x0a, 0x63, 0x75, 0x61, 0x72, 0x74, 0x6f, 0x0a, 0x63, 0x75, 0x61, - 0x74, 0x72, 0x6f, 0x0a, 0x63, 0x75, 0x62, 0x6f, 0x0a, 0x63, 0x75, 0x62, - 0x72, 0x69, 0x72, 0x0a, 0x63, 0x75, 0x63, 0x68, 0x61, 0x72, 0x61, 0x0a, - 0x63, 0x75, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x63, 0x75, 0x65, 0x6e, 0x74, - 0x6f, 0x0a, 0x63, 0x75, 0x65, 0x72, 0x64, 0x61, 0x0a, 0x63, 0x75, 0x65, - 0x73, 0x74, 0x61, 0x0a, 0x63, 0x75, 0x65, 0x76, 0x61, 0x0a, 0x63, 0x75, - 0x69, 0x64, 0x61, 0x72, 0x0a, 0x63, 0x75, 0x6c, 0x65, 0x62, 0x72, 0x61, - 0x0a, 0x63, 0x75, 0x6c, 0x70, 0x61, 0x0a, 0x63, 0x75, 0x6c, 0x74, 0x6f, - 0x0a, 0x63, 0x75, 0x6d, 0x62, 0x72, 0x65, 0x0a, 0x63, 0x75, 0x6d, 0x70, - 0x6c, 0x69, 0x72, 0x0a, 0x63, 0x75, 0x6e, 0x61, 0x0a, 0x63, 0x75, 0x6e, - 0x65, 0x74, 0x61, 0x0a, 0x63, 0x75, 0x6f, 0x74, 0x61, 0x0a, 0x63, 0x75, - 0x70, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x63, 0x75, 0xcc, 0x81, 0x70, 0x75, - 0x6c, 0x61, 0x0a, 0x63, 0x75, 0x72, 0x61, 0x72, 0x0a, 0x63, 0x75, 0x72, - 0x69, 0x6f, 0x73, 0x6f, 0x0a, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x0a, 0x63, - 0x75, 0x72, 0x76, 0x61, 0x0a, 0x63, 0x75, 0x74, 0x69, 0x73, 0x0a, 0x64, - 0x61, 0x6d, 0x61, 0x0a, 0x64, 0x61, 0x6e, 0x7a, 0x61, 0x0a, 0x64, 0x61, - 0x72, 0x0a, 0x64, 0x61, 0x72, 0x64, 0x6f, 0x0a, 0x64, 0x61, 0xcc, 0x81, - 0x74, 0x69, 0x6c, 0x0a, 0x64, 0x65, 0x62, 0x65, 0x72, 0x0a, 0x64, 0x65, - 0xcc, 0x81, 0x62, 0x69, 0x6c, 0x0a, 0x64, 0x65, 0xcc, 0x81, 0x63, 0x61, - 0x64, 0x61, 0x0a, 0x64, 0x65, 0x63, 0x69, 0x72, 0x0a, 0x64, 0x65, 0x64, - 0x6f, 0x0a, 0x64, 0x65, 0x66, 0x65, 0x6e, 0x73, 0x61, 0x0a, 0x64, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x72, 0x0a, 0x64, 0x65, 0x6a, 0x61, 0x72, 0x0a, - 0x64, 0x65, 0x6c, 0x66, 0x69, 0xcc, 0x81, 0x6e, 0x0a, 0x64, 0x65, 0x6c, - 0x67, 0x61, 0x64, 0x6f, 0x0a, 0x64, 0x65, 0x6c, 0x69, 0x74, 0x6f, 0x0a, - 0x64, 0x65, 0x6d, 0x6f, 0x72, 0x61, 0x0a, 0x64, 0x65, 0x6e, 0x73, 0x6f, - 0x0a, 0x64, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0a, 0x64, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x0a, 0x64, 0x65, 0x72, 0x65, 0x63, 0x68, 0x6f, 0x0a, - 0x64, 0x65, 0x72, 0x72, 0x6f, 0x74, 0x61, 0x0a, 0x64, 0x65, 0x73, 0x61, - 0x79, 0x75, 0x6e, 0x6f, 0x0a, 0x64, 0x65, 0x73, 0x65, 0x6f, 0x0a, 0x64, - 0x65, 0x73, 0x66, 0x69, 0x6c, 0x65, 0x0a, 0x64, 0x65, 0x73, 0x6e, 0x75, - 0x64, 0x6f, 0x0a, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x6f, 0x0a, 0x64, - 0x65, 0x73, 0x76, 0x69, 0xcc, 0x81, 0x6f, 0x0a, 0x64, 0x65, 0x74, 0x61, - 0x6c, 0x6c, 0x65, 0x0a, 0x64, 0x65, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x0a, - 0x64, 0x65, 0x75, 0x64, 0x61, 0x0a, 0x64, 0x69, 0xcc, 0x81, 0x61, 0x0a, - 0x64, 0x69, 0x61, 0x62, 0x6c, 0x6f, 0x0a, 0x64, 0x69, 0x61, 0x64, 0x65, - 0x6d, 0x61, 0x0a, 0x64, 0x69, 0x61, 0x6d, 0x61, 0x6e, 0x74, 0x65, 0x0a, - 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0a, 0x64, 0x69, 0x61, 0x72, 0x69, 0x6f, - 0x0a, 0x64, 0x69, 0x62, 0x75, 0x6a, 0x6f, 0x0a, 0x64, 0x69, 0x63, 0x74, - 0x61, 0x72, 0x0a, 0x64, 0x69, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x64, 0x69, - 0x65, 0x74, 0x61, 0x0a, 0x64, 0x69, 0x65, 0x7a, 0x0a, 0x64, 0x69, 0x66, - 0x69, 0xcc, 0x81, 0x63, 0x69, 0x6c, 0x0a, 0x64, 0x69, 0x67, 0x6e, 0x6f, - 0x0a, 0x64, 0x69, 0x6c, 0x65, 0x6d, 0x61, 0x0a, 0x64, 0x69, 0x6c, 0x75, - 0x69, 0x72, 0x0a, 0x64, 0x69, 0x6e, 0x65, 0x72, 0x6f, 0x0a, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x6f, 0x0a, 0x64, 0x69, 0x72, 0x69, 0x67, 0x69, - 0x72, 0x0a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x0a, 0x64, 0x69, 0x73, 0x65, - 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x64, 0x69, 0x73, 0x66, 0x72, 0x61, 0x7a, - 0x0a, 0x64, 0x69, 0x76, 0x61, 0x0a, 0x64, 0x69, 0x76, 0x69, 0x6e, 0x6f, - 0x0a, 0x64, 0x6f, 0x62, 0x6c, 0x65, 0x0a, 0x64, 0x6f, 0x63, 0x65, 0x0a, - 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x0a, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, - 0x6f, 0x0a, 0x64, 0x6f, 0x6e, 0x0a, 0x64, 0x6f, 0x6e, 0x61, 0x72, 0x0a, - 0x64, 0x6f, 0x72, 0x61, 0x64, 0x6f, 0x0a, 0x64, 0x6f, 0x72, 0x6d, 0x69, - 0x72, 0x0a, 0x64, 0x6f, 0x72, 0x73, 0x6f, 0x0a, 0x64, 0x6f, 0x73, 0x0a, - 0x64, 0x6f, 0x73, 0x69, 0x73, 0x0a, 0x64, 0x72, 0x61, 0x67, 0x6f, 0xcc, - 0x81, 0x6e, 0x0a, 0x64, 0x72, 0x6f, 0x67, 0x61, 0x0a, 0x64, 0x75, 0x63, - 0x68, 0x61, 0x0a, 0x64, 0x75, 0x64, 0x61, 0x0a, 0x64, 0x75, 0x65, 0x6c, - 0x6f, 0x0a, 0x64, 0x75, 0x65, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x64, 0x75, - 0x6c, 0x63, 0x65, 0x0a, 0x64, 0x75, 0xcc, 0x81, 0x6f, 0x0a, 0x64, 0x75, - 0x71, 0x75, 0x65, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x72, 0x0a, 0x64, 0x75, - 0x72, 0x65, 0x7a, 0x61, 0x0a, 0x64, 0x75, 0x72, 0x6f, 0x0a, 0x65, 0xcc, - 0x81, 0x62, 0x61, 0x6e, 0x6f, 0x0a, 0x65, 0x62, 0x72, 0x69, 0x6f, 0x0a, - 0x65, 0x63, 0x68, 0x61, 0x72, 0x0a, 0x65, 0x63, 0x6f, 0x0a, 0x65, 0x63, - 0x75, 0x61, 0x64, 0x6f, 0x72, 0x0a, 0x65, 0x64, 0x61, 0x64, 0x0a, 0x65, - 0x64, 0x69, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x65, 0x64, 0x69, - 0x66, 0x69, 0x63, 0x69, 0x6f, 0x0a, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, - 0x0a, 0x65, 0x64, 0x75, 0x63, 0x61, 0x72, 0x0a, 0x65, 0x66, 0x65, 0x63, - 0x74, 0x6f, 0x0a, 0x65, 0x66, 0x69, 0x63, 0x61, 0x7a, 0x0a, 0x65, 0x6a, - 0x65, 0x0a, 0x65, 0x6a, 0x65, 0x6d, 0x70, 0x6c, 0x6f, 0x0a, 0x65, 0x6c, - 0x65, 0x66, 0x61, 0x6e, 0x74, 0x65, 0x0a, 0x65, 0x6c, 0x65, 0x67, 0x69, - 0x72, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x65, - 0x6c, 0x65, 0x76, 0x61, 0x72, 0x0a, 0x65, 0x6c, 0x69, 0x70, 0x73, 0x65, - 0x0a, 0x65, 0xcc, 0x81, 0x6c, 0x69, 0x74, 0x65, 0x0a, 0x65, 0x6c, 0x69, - 0x78, 0x69, 0x72, 0x0a, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x6f, 0x0a, 0x65, - 0x6c, 0x75, 0x64, 0x69, 0x72, 0x0a, 0x65, 0x6d, 0x62, 0x75, 0x64, 0x6f, - 0x0a, 0x65, 0x6d, 0x69, 0x74, 0x69, 0x72, 0x0a, 0x65, 0x6d, 0x6f, 0x63, - 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x65, 0x6d, 0x70, 0x61, 0x74, 0x65, - 0x0a, 0x65, 0x6d, 0x70, 0x65, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x65, 0x6d, - 0x70, 0x6c, 0x65, 0x6f, 0x0a, 0x65, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x61, - 0x0a, 0x65, 0x6e, 0x61, 0x6e, 0x6f, 0x0a, 0x65, 0x6e, 0x63, 0x61, 0x72, - 0x67, 0x6f, 0x0a, 0x65, 0x6e, 0x63, 0x68, 0x75, 0x66, 0x65, 0x0a, 0x65, - 0x6e, 0x63, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x65, 0x6e, 0x65, 0x6d, 0x69, - 0x67, 0x6f, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x0a, 0x65, 0x6e, 0x66, - 0x61, 0x64, 0x6f, 0x0a, 0x65, 0x6e, 0x66, 0x65, 0x72, 0x6d, 0x6f, 0x0a, - 0x65, 0x6e, 0x67, 0x61, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x65, 0x6e, 0x69, - 0x67, 0x6d, 0x61, 0x0a, 0x65, 0x6e, 0x6c, 0x61, 0x63, 0x65, 0x0a, 0x65, - 0x6e, 0x6f, 0x72, 0x6d, 0x65, 0x0a, 0x65, 0x6e, 0x72, 0x65, 0x64, 0x6f, - 0x0a, 0x65, 0x6e, 0x73, 0x61, 0x79, 0x6f, 0x0a, 0x65, 0x6e, 0x73, 0x65, - 0x6e, 0xcc, 0x83, 0x61, 0x72, 0x0a, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x6f, - 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x72, 0x0a, 0x65, 0x6e, 0x76, 0x61, - 0x73, 0x65, 0x0a, 0x65, 0x6e, 0x76, 0x69, 0xcc, 0x81, 0x6f, 0x0a, 0x65, - 0xcc, 0x81, 0x70, 0x6f, 0x63, 0x61, 0x0a, 0x65, 0x71, 0x75, 0x69, 0x70, - 0x6f, 0x0a, 0x65, 0x72, 0x69, 0x7a, 0x6f, 0x0a, 0x65, 0x73, 0x63, 0x61, - 0x6c, 0x61, 0x0a, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x61, 0x0a, 0x65, 0x73, - 0x63, 0x6f, 0x6c, 0x61, 0x72, 0x0a, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x69, 0x72, 0x0a, 0x65, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x0a, 0x65, 0x73, - 0x65, 0x6e, 0x63, 0x69, 0x61, 0x0a, 0x65, 0x73, 0x66, 0x65, 0x72, 0x61, - 0x0a, 0x65, 0x73, 0x66, 0x75, 0x65, 0x72, 0x7a, 0x6f, 0x0a, 0x65, 0x73, - 0x70, 0x61, 0x64, 0x61, 0x0a, 0x65, 0x73, 0x70, 0x65, 0x6a, 0x6f, 0x0a, - 0x65, 0x73, 0x70, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x65, 0x73, 0x70, 0x6f, - 0x73, 0x61, 0x0a, 0x65, 0x73, 0x70, 0x75, 0x6d, 0x61, 0x0a, 0x65, 0x73, - 0x71, 0x75, 0x69, 0xcc, 0x81, 0x0a, 0x65, 0x73, 0x74, 0x61, 0x72, 0x0a, - 0x65, 0x73, 0x74, 0x65, 0x0a, 0x65, 0x73, 0x74, 0x69, 0x6c, 0x6f, 0x0a, - 0x65, 0x73, 0x74, 0x75, 0x66, 0x61, 0x0a, 0x65, 0x74, 0x61, 0x70, 0x61, - 0x0a, 0x65, 0x74, 0x65, 0x72, 0x6e, 0x6f, 0x0a, 0x65, 0xcc, 0x81, 0x74, - 0x69, 0x63, 0x61, 0x0a, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x0a, 0x65, 0x76, - 0x61, 0x64, 0x69, 0x72, 0x0a, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x72, - 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x65, 0x76, 0x69, 0x74, - 0x61, 0x72, 0x0a, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6f, 0x0a, 0x65, 0x78, - 0x61, 0x6d, 0x65, 0x6e, 0x0a, 0x65, 0x78, 0x63, 0x65, 0x73, 0x6f, 0x0a, - 0x65, 0x78, 0x63, 0x75, 0x73, 0x61, 0x0a, 0x65, 0x78, 0x65, 0x6e, 0x74, - 0x6f, 0x0a, 0x65, 0x78, 0x69, 0x67, 0x69, 0x72, 0x0a, 0x65, 0x78, 0x69, - 0x6c, 0x69, 0x6f, 0x0a, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x72, 0x0a, - 0x65, 0xcc, 0x81, 0x78, 0x69, 0x74, 0x6f, 0x0a, 0x65, 0x78, 0x70, 0x65, - 0x72, 0x74, 0x6f, 0x0a, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x72, - 0x0a, 0x65, 0x78, 0x70, 0x6f, 0x6e, 0x65, 0x72, 0x0a, 0x65, 0x78, 0x74, - 0x72, 0x65, 0x6d, 0x6f, 0x0a, 0x66, 0x61, 0xcc, 0x81, 0x62, 0x72, 0x69, - 0x63, 0x61, 0x0a, 0x66, 0x61, 0xcc, 0x81, 0x62, 0x75, 0x6c, 0x61, 0x0a, - 0x66, 0x61, 0x63, 0x68, 0x61, 0x64, 0x61, 0x0a, 0x66, 0x61, 0xcc, 0x81, - 0x63, 0x69, 0x6c, 0x0a, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x0a, 0x66, - 0x61, 0x65, 0x6e, 0x61, 0x0a, 0x66, 0x61, 0x6a, 0x61, 0x0a, 0x66, 0x61, - 0x6c, 0x64, 0x61, 0x0a, 0x66, 0x61, 0x6c, 0x6c, 0x6f, 0x0a, 0x66, 0x61, - 0x6c, 0x73, 0x6f, 0x0a, 0x66, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0a, 0x66, - 0x61, 0x6d, 0x61, 0x0a, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x61, 0x0a, - 0x66, 0x61, 0x6d, 0x6f, 0x73, 0x6f, 0x0a, 0x66, 0x61, 0x72, 0x61, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x66, 0x61, 0x72, 0x6d, 0x61, 0x63, 0x69, 0x61, - 0x0a, 0x66, 0x61, 0x72, 0x6f, 0x6c, 0x0a, 0x66, 0x61, 0x72, 0x73, 0x61, - 0x0a, 0x66, 0x61, 0x73, 0x65, 0x0a, 0x66, 0x61, 0x74, 0x69, 0x67, 0x61, - 0x0a, 0x66, 0x61, 0x75, 0x6e, 0x61, 0x0a, 0x66, 0x61, 0x76, 0x6f, 0x72, - 0x0a, 0x66, 0x61, 0x78, 0x0a, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, - 0x0a, 0x66, 0x65, 0x63, 0x68, 0x61, 0x0a, 0x66, 0x65, 0x6c, 0x69, 0x7a, - 0x0a, 0x66, 0x65, 0x6f, 0x0a, 0x66, 0x65, 0x72, 0x69, 0x61, 0x0a, 0x66, - 0x65, 0x72, 0x6f, 0x7a, 0x0a, 0x66, 0x65, 0xcc, 0x81, 0x72, 0x74, 0x69, - 0x6c, 0x0a, 0x66, 0x65, 0x72, 0x76, 0x6f, 0x72, 0x0a, 0x66, 0x65, 0x73, - 0x74, 0x69, 0xcc, 0x81, 0x6e, 0x0a, 0x66, 0x69, 0x61, 0x62, 0x6c, 0x65, - 0x0a, 0x66, 0x69, 0x61, 0x6e, 0x7a, 0x61, 0x0a, 0x66, 0x69, 0x61, 0x72, - 0x0a, 0x66, 0x69, 0x62, 0x72, 0x61, 0x0a, 0x66, 0x69, 0x63, 0x63, 0x69, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x66, 0x69, 0x63, 0x68, 0x61, 0x0a, 0x66, - 0x69, 0x64, 0x65, 0x6f, 0x0a, 0x66, 0x69, 0x65, 0x62, 0x72, 0x65, 0x0a, - 0x66, 0x69, 0x65, 0x6c, 0x0a, 0x66, 0x69, 0x65, 0x72, 0x61, 0x0a, 0x66, - 0x69, 0x65, 0x73, 0x74, 0x61, 0x0a, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x0a, 0x66, 0x69, 0x6a, 0x61, 0x72, 0x0a, 0x66, 0x69, 0x6a, 0x6f, 0x0a, - 0x66, 0x69, 0x6c, 0x61, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x74, 0x65, 0x0a, - 0x66, 0x69, 0x6c, 0x69, 0x61, 0x6c, 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x72, - 0x6f, 0x0a, 0x66, 0x69, 0x6e, 0x0a, 0x66, 0x69, 0x6e, 0x63, 0x61, 0x0a, - 0x66, 0x69, 0x6e, 0x67, 0x69, 0x72, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x74, - 0x6f, 0x0a, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x0a, 0x66, 0x6c, 0x61, 0x63, - 0x6f, 0x0a, 0x66, 0x6c, 0x61, 0x75, 0x74, 0x61, 0x0a, 0x66, 0x6c, 0x65, - 0x63, 0x68, 0x61, 0x0a, 0x66, 0x6c, 0x6f, 0x72, 0x0a, 0x66, 0x6c, 0x6f, - 0x74, 0x61, 0x0a, 0x66, 0x6c, 0x75, 0x69, 0x72, 0x0a, 0x66, 0x6c, 0x75, - 0x6a, 0x6f, 0x0a, 0x66, 0x6c, 0x75, 0xcc, 0x81, 0x6f, 0x72, 0x0a, 0x66, - 0x6f, 0x62, 0x69, 0x61, 0x0a, 0x66, 0x6f, 0x63, 0x61, 0x0a, 0x66, 0x6f, - 0x67, 0x61, 0x74, 0x61, 0x0a, 0x66, 0x6f, 0x67, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x0a, 0x66, 0x6f, 0x6c, 0x6c, 0x65, - 0x74, 0x6f, 0x0a, 0x66, 0x6f, 0x6e, 0x64, 0x6f, 0x0a, 0x66, 0x6f, 0x72, - 0x6d, 0x61, 0x0a, 0x66, 0x6f, 0x72, 0x72, 0x6f, 0x0a, 0x66, 0x6f, 0x72, - 0x74, 0x75, 0x6e, 0x61, 0x0a, 0x66, 0x6f, 0x72, 0x7a, 0x61, 0x72, 0x0a, - 0x66, 0x6f, 0x73, 0x61, 0x0a, 0x66, 0x6f, 0x74, 0x6f, 0x0a, 0x66, 0x72, - 0x61, 0x63, 0x61, 0x73, 0x6f, 0x0a, 0x66, 0x72, 0x61, 0xcc, 0x81, 0x67, - 0x69, 0x6c, 0x0a, 0x66, 0x72, 0x61, 0x6e, 0x6a, 0x61, 0x0a, 0x66, 0x72, - 0x61, 0x73, 0x65, 0x0a, 0x66, 0x72, 0x61, 0x75, 0x64, 0x65, 0x0a, 0x66, - 0x72, 0x65, 0x69, 0xcc, 0x81, 0x72, 0x0a, 0x66, 0x72, 0x65, 0x6e, 0x6f, - 0x0a, 0x66, 0x72, 0x65, 0x73, 0x61, 0x0a, 0x66, 0x72, 0x69, 0xcc, 0x81, - 0x6f, 0x0a, 0x66, 0x72, 0x69, 0x74, 0x6f, 0x0a, 0x66, 0x72, 0x75, 0x74, - 0x61, 0x0a, 0x66, 0x75, 0x65, 0x67, 0x6f, 0x0a, 0x66, 0x75, 0x65, 0x6e, - 0x74, 0x65, 0x0a, 0x66, 0x75, 0x65, 0x72, 0x7a, 0x61, 0x0a, 0x66, 0x75, - 0x67, 0x61, 0x0a, 0x66, 0x75, 0x6d, 0x61, 0x72, 0x0a, 0x66, 0x75, 0x6e, - 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x66, 0x75, 0x6e, 0x64, 0x61, - 0x0a, 0x66, 0x75, 0x72, 0x67, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x66, 0x75, - 0x72, 0x69, 0x61, 0x0a, 0x66, 0x75, 0x73, 0x69, 0x6c, 0x0a, 0x66, 0x75, - 0xcc, 0x81, 0x74, 0x62, 0x6f, 0x6c, 0x0a, 0x66, 0x75, 0x74, 0x75, 0x72, - 0x6f, 0x0a, 0x67, 0x61, 0x63, 0x65, 0x6c, 0x61, 0x0a, 0x67, 0x61, 0x66, - 0x61, 0x73, 0x0a, 0x67, 0x61, 0x69, 0x74, 0x61, 0x0a, 0x67, 0x61, 0x6a, - 0x6f, 0x0a, 0x67, 0x61, 0x6c, 0x61, 0x0a, 0x67, 0x61, 0x6c, 0x65, 0x72, - 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x67, 0x61, 0x6c, 0x6c, 0x6f, 0x0a, 0x67, - 0x61, 0x6d, 0x62, 0x61, 0x0a, 0x67, 0x61, 0x6e, 0x61, 0x72, 0x0a, 0x67, - 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x0a, 0x67, 0x61, 0x6e, 0x67, 0x61, 0x0a, - 0x67, 0x61, 0x6e, 0x73, 0x6f, 0x0a, 0x67, 0x61, 0x72, 0x61, 0x6a, 0x65, - 0x0a, 0x67, 0x61, 0x72, 0x7a, 0x61, 0x0a, 0x67, 0x61, 0x73, 0x6f, 0x6c, - 0x69, 0x6e, 0x61, 0x0a, 0x67, 0x61, 0x73, 0x74, 0x61, 0x72, 0x0a, 0x67, - 0x61, 0x74, 0x6f, 0x0a, 0x67, 0x61, 0x76, 0x69, 0x6c, 0x61, 0xcc, 0x81, - 0x6e, 0x0a, 0x67, 0x65, 0x6d, 0x65, 0x6c, 0x6f, 0x0a, 0x67, 0x65, 0x6d, - 0x69, 0x72, 0x0a, 0x67, 0x65, 0x6e, 0x0a, 0x67, 0x65, 0xcc, 0x81, 0x6e, - 0x65, 0x72, 0x6f, 0x0a, 0x67, 0x65, 0x6e, 0x69, 0x6f, 0x0a, 0x67, 0x65, - 0x6e, 0x74, 0x65, 0x0a, 0x67, 0x65, 0x72, 0x61, 0x6e, 0x69, 0x6f, 0x0a, - 0x67, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x67, 0x65, 0x72, 0x6d, - 0x65, 0x6e, 0x0a, 0x67, 0x65, 0x73, 0x74, 0x6f, 0x0a, 0x67, 0x69, 0x67, - 0x61, 0x6e, 0x74, 0x65, 0x0a, 0x67, 0x69, 0x6d, 0x6e, 0x61, 0x73, 0x69, - 0x6f, 0x0a, 0x67, 0x69, 0x72, 0x61, 0x72, 0x0a, 0x67, 0x69, 0x72, 0x6f, - 0x0a, 0x67, 0x6c, 0x61, 0x63, 0x69, 0x61, 0x72, 0x0a, 0x67, 0x6c, 0x6f, - 0x62, 0x6f, 0x0a, 0x67, 0x6c, 0x6f, 0x72, 0x69, 0x61, 0x0a, 0x67, 0x6f, - 0x6c, 0x0a, 0x67, 0x6f, 0x6c, 0x66, 0x6f, 0x0a, 0x67, 0x6f, 0x6c, 0x6f, - 0x73, 0x6f, 0x0a, 0x67, 0x6f, 0x6c, 0x70, 0x65, 0x0a, 0x67, 0x6f, 0x6d, - 0x61, 0x0a, 0x67, 0x6f, 0x72, 0x64, 0x6f, 0x0a, 0x67, 0x6f, 0x72, 0x69, - 0x6c, 0x61, 0x0a, 0x67, 0x6f, 0x72, 0x72, 0x61, 0x0a, 0x67, 0x6f, 0x74, - 0x61, 0x0a, 0x67, 0x6f, 0x74, 0x65, 0x6f, 0x0a, 0x67, 0x6f, 0x7a, 0x61, - 0x72, 0x0a, 0x67, 0x72, 0x61, 0x64, 0x61, 0x0a, 0x67, 0x72, 0x61, 0xcc, - 0x81, 0x66, 0x69, 0x63, 0x6f, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x6f, 0x0a, - 0x67, 0x72, 0x61, 0x73, 0x61, 0x0a, 0x67, 0x72, 0x61, 0x74, 0x69, 0x73, - 0x0a, 0x67, 0x72, 0x61, 0x76, 0x65, 0x0a, 0x67, 0x72, 0x69, 0x65, 0x74, - 0x61, 0x0a, 0x67, 0x72, 0x69, 0x6c, 0x6c, 0x6f, 0x0a, 0x67, 0x72, 0x69, - 0x70, 0x65, 0x0a, 0x67, 0x72, 0x69, 0x73, 0x0a, 0x67, 0x72, 0x69, 0x74, - 0x6f, 0x0a, 0x67, 0x72, 0x6f, 0x73, 0x6f, 0x72, 0x0a, 0x67, 0x72, 0x75, - 0xcc, 0x81, 0x61, 0x0a, 0x67, 0x72, 0x75, 0x65, 0x73, 0x6f, 0x0a, 0x67, - 0x72, 0x75, 0x6d, 0x6f, 0x0a, 0x67, 0x72, 0x75, 0x70, 0x6f, 0x0a, 0x67, - 0x75, 0x61, 0x6e, 0x74, 0x65, 0x0a, 0x67, 0x75, 0x61, 0x70, 0x6f, 0x0a, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x0a, 0x67, 0x75, 0x65, 0x72, - 0x72, 0x61, 0x0a, 0x67, 0x75, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x67, 0x75, - 0x69, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x67, 0x75, 0x69, 0x6f, 0x6e, 0x0a, - 0x67, 0x75, 0x69, 0x73, 0x6f, 0x0a, 0x67, 0x75, 0x69, 0x74, 0x61, 0x72, - 0x72, 0x61, 0x0a, 0x67, 0x75, 0x73, 0x61, 0x6e, 0x6f, 0x0a, 0x67, 0x75, - 0x73, 0x74, 0x61, 0x72, 0x0a, 0x68, 0x61, 0x62, 0x65, 0x72, 0x0a, 0x68, - 0x61, 0xcc, 0x81, 0x62, 0x69, 0x6c, 0x0a, 0x68, 0x61, 0x62, 0x6c, 0x61, - 0x72, 0x0a, 0x68, 0x61, 0x63, 0x65, 0x72, 0x0a, 0x68, 0x61, 0x63, 0x68, - 0x61, 0x0a, 0x68, 0x61, 0x64, 0x61, 0x0a, 0x68, 0x61, 0x6c, 0x6c, 0x61, - 0x72, 0x0a, 0x68, 0x61, 0x6d, 0x61, 0x63, 0x61, 0x0a, 0x68, 0x61, 0x72, - 0x69, 0x6e, 0x61, 0x0a, 0x68, 0x61, 0x7a, 0x0a, 0x68, 0x61, 0x7a, 0x61, - 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x68, 0x65, 0x62, 0x69, 0x6c, 0x6c, 0x61, - 0x0a, 0x68, 0x65, 0x62, 0x72, 0x61, 0x0a, 0x68, 0x65, 0x63, 0x68, 0x6f, - 0x0a, 0x68, 0x65, 0x6c, 0x61, 0x64, 0x6f, 0x0a, 0x68, 0x65, 0x6c, 0x69, - 0x6f, 0x0a, 0x68, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x0a, 0x68, 0x65, 0x72, - 0x69, 0x72, 0x0a, 0x68, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x6f, 0x0a, 0x68, - 0x65, 0xcc, 0x81, 0x72, 0x6f, 0x65, 0x0a, 0x68, 0x65, 0x72, 0x76, 0x69, - 0x72, 0x0a, 0x68, 0x69, 0x65, 0x6c, 0x6f, 0x0a, 0x68, 0x69, 0x65, 0x72, - 0x72, 0x6f, 0x0a, 0x68, 0x69, 0xcc, 0x81, 0x67, 0x61, 0x64, 0x6f, 0x0a, - 0x68, 0x69, 0x67, 0x69, 0x65, 0x6e, 0x65, 0x0a, 0x68, 0x69, 0x6a, 0x6f, - 0x0a, 0x68, 0x69, 0x6d, 0x6e, 0x6f, 0x0a, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x69, 0x61, 0x0a, 0x68, 0x6f, 0x63, 0x69, 0x63, 0x6f, 0x0a, 0x68, - 0x6f, 0x67, 0x61, 0x72, 0x0a, 0x68, 0x6f, 0x67, 0x75, 0x65, 0x72, 0x61, - 0x0a, 0x68, 0x6f, 0x6a, 0x61, 0x0a, 0x68, 0x6f, 0x6d, 0x62, 0x72, 0x65, - 0x0a, 0x68, 0x6f, 0x6e, 0x67, 0x6f, 0x0a, 0x68, 0x6f, 0x6e, 0x6f, 0x72, - 0x0a, 0x68, 0x6f, 0x6e, 0x72, 0x61, 0x0a, 0x68, 0x6f, 0x72, 0x61, 0x0a, - 0x68, 0x6f, 0x72, 0x6d, 0x69, 0x67, 0x61, 0x0a, 0x68, 0x6f, 0x72, 0x6e, - 0x6f, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x69, 0x6c, 0x0a, 0x68, 0x6f, 0x79, - 0x6f, 0x0a, 0x68, 0x75, 0x65, 0x63, 0x6f, 0x0a, 0x68, 0x75, 0x65, 0x6c, - 0x67, 0x61, 0x0a, 0x68, 0x75, 0x65, 0x72, 0x74, 0x61, 0x0a, 0x68, 0x75, - 0x65, 0x73, 0x6f, 0x0a, 0x68, 0x75, 0x65, 0x76, 0x6f, 0x0a, 0x68, 0x75, - 0x69, 0x64, 0x61, 0x0a, 0x68, 0x75, 0x69, 0x72, 0x0a, 0x68, 0x75, 0x6d, - 0x61, 0x6e, 0x6f, 0x0a, 0x68, 0x75, 0xcc, 0x81, 0x6d, 0x65, 0x64, 0x6f, - 0x0a, 0x68, 0x75, 0x6d, 0x69, 0x6c, 0x64, 0x65, 0x0a, 0x68, 0x75, 0x6d, - 0x6f, 0x0a, 0x68, 0x75, 0x6e, 0x64, 0x69, 0x72, 0x0a, 0x68, 0x75, 0x72, - 0x61, 0x63, 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x68, 0x75, 0x72, 0x74, 0x6f, - 0x0a, 0x69, 0x63, 0x6f, 0x6e, 0x6f, 0x0a, 0x69, 0x64, 0x65, 0x61, 0x6c, - 0x0a, 0x69, 0x64, 0x69, 0x6f, 0x6d, 0x61, 0x0a, 0x69, 0xcc, 0x81, 0x64, - 0x6f, 0x6c, 0x6f, 0x0a, 0x69, 0x67, 0x6c, 0x65, 0x73, 0x69, 0x61, 0x0a, - 0x69, 0x67, 0x6c, 0x75, 0xcc, 0x81, 0x0a, 0x69, 0x67, 0x75, 0x61, 0x6c, - 0x0a, 0x69, 0x6c, 0x65, 0x67, 0x61, 0x6c, 0x0a, 0x69, 0x6c, 0x75, 0x73, - 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x6e, - 0x0a, 0x69, 0x6d, 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x69, 0x6d, 0x69, 0x74, - 0x61, 0x72, 0x0a, 0x69, 0x6d, 0x70, 0x61, 0x72, 0x0a, 0x69, 0x6d, 0x70, - 0x65, 0x72, 0x69, 0x6f, 0x0a, 0x69, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x72, - 0x0a, 0x69, 0x6d, 0x70, 0x75, 0x6c, 0x73, 0x6f, 0x0a, 0x69, 0x6e, 0x63, - 0x61, 0x70, 0x61, 0x7a, 0x0a, 0x69, 0xcc, 0x81, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x0a, 0x69, 0x6e, 0x65, 0x72, 0x74, 0x65, 0x0a, 0x69, 0x6e, 0x66, - 0x69, 0x65, 0x6c, 0x0a, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x0a, - 0x69, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x6f, 0x0a, 0x69, 0x6e, 0x69, 0x63, - 0x69, 0x6f, 0x0a, 0x69, 0x6e, 0x6d, 0x65, 0x6e, 0x73, 0x6f, 0x0a, 0x69, - 0x6e, 0x6d, 0x75, 0x6e, 0x65, 0x0a, 0x69, 0x6e, 0x6e, 0x61, 0x74, 0x6f, - 0x0a, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x6f, 0x0a, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x74, 0x65, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x65, - 0xcc, 0x81, 0x73, 0x0a, 0x69, 0xcc, 0x81, 0x6e, 0x74, 0x69, 0x6d, 0x6f, - 0x0a, 0x69, 0x6e, 0x74, 0x75, 0x69, 0x72, 0x0a, 0x69, 0x6e, 0x75, 0xcc, - 0x81, 0x74, 0x69, 0x6c, 0x0a, 0x69, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x6e, - 0x6f, 0x0a, 0x69, 0x72, 0x61, 0x0a, 0x69, 0x72, 0x69, 0x73, 0x0a, 0x69, - 0x72, 0x6f, 0x6e, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x69, 0x73, 0x6c, 0x61, - 0x0a, 0x69, 0x73, 0x6c, 0x6f, 0x74, 0x65, 0x0a, 0x6a, 0x61, 0x62, 0x61, - 0x6c, 0x69, 0xcc, 0x81, 0x0a, 0x6a, 0x61, 0x62, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x6a, 0x61, 0x6d, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6a, 0x61, 0x72, - 0x61, 0x62, 0x65, 0x0a, 0x6a, 0x61, 0x72, 0x64, 0x69, 0xcc, 0x81, 0x6e, - 0x0a, 0x6a, 0x61, 0x72, 0x72, 0x61, 0x0a, 0x6a, 0x61, 0x75, 0x6c, 0x61, - 0x0a, 0x6a, 0x61, 0x7a, 0x6d, 0x69, 0xcc, 0x81, 0x6e, 0x0a, 0x6a, 0x65, - 0x66, 0x65, 0x0a, 0x6a, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x61, 0x0a, 0x6a, - 0x69, 0x6e, 0x65, 0x74, 0x65, 0x0a, 0x6a, 0x6f, 0x72, 0x6e, 0x61, 0x64, - 0x61, 0x0a, 0x6a, 0x6f, 0x72, 0x6f, 0x62, 0x61, 0x0a, 0x6a, 0x6f, 0x76, - 0x65, 0x6e, 0x0a, 0x6a, 0x6f, 0x79, 0x61, 0x0a, 0x6a, 0x75, 0x65, 0x72, - 0x67, 0x61, 0x0a, 0x6a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x0a, 0x6a, 0x75, - 0x65, 0x7a, 0x0a, 0x6a, 0x75, 0x67, 0x61, 0x64, 0x6f, 0x72, 0x0a, 0x6a, - 0x75, 0x67, 0x6f, 0x0a, 0x6a, 0x75, 0x67, 0x75, 0x65, 0x74, 0x65, 0x0a, - 0x6a, 0x75, 0x69, 0x63, 0x69, 0x6f, 0x0a, 0x6a, 0x75, 0x6e, 0x63, 0x6f, - 0x0a, 0x6a, 0x75, 0x6e, 0x67, 0x6c, 0x61, 0x0a, 0x6a, 0x75, 0x6e, 0x69, - 0x6f, 0x0a, 0x6a, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x0a, 0x6a, 0x75, 0xcc, - 0x81, 0x70, 0x69, 0x74, 0x65, 0x72, 0x0a, 0x6a, 0x75, 0x72, 0x61, 0x72, - 0x0a, 0x6a, 0x75, 0x73, 0x74, 0x6f, 0x0a, 0x6a, 0x75, 0x76, 0x65, 0x6e, - 0x69, 0x6c, 0x0a, 0x6a, 0x75, 0x7a, 0x67, 0x61, 0x72, 0x0a, 0x6b, 0x69, - 0x6c, 0x6f, 0x0a, 0x6b, 0x6f, 0x61, 0x6c, 0x61, 0x0a, 0x6c, 0x61, 0x62, - 0x69, 0x6f, 0x0a, 0x6c, 0x61, 0x63, 0x69, 0x6f, 0x0a, 0x6c, 0x61, 0x63, - 0x72, 0x61, 0x0a, 0x6c, 0x61, 0x64, 0x6f, 0x0a, 0x6c, 0x61, 0x64, 0x72, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6c, 0x61, 0x67, 0x61, 0x72, 0x74, 0x6f, - 0x0a, 0x6c, 0x61, 0xcc, 0x81, 0x67, 0x72, 0x69, 0x6d, 0x61, 0x0a, 0x6c, - 0x61, 0x67, 0x75, 0x6e, 0x61, 0x0a, 0x6c, 0x61, 0x69, 0x63, 0x6f, 0x0a, - 0x6c, 0x61, 0x6d, 0x65, 0x72, 0x0a, 0x6c, 0x61, 0xcc, 0x81, 0x6d, 0x69, - 0x6e, 0x61, 0x0a, 0x6c, 0x61, 0xcc, 0x81, 0x6d, 0x70, 0x61, 0x72, 0x61, - 0x0a, 0x6c, 0x61, 0x6e, 0x61, 0x0a, 0x6c, 0x61, 0x6e, 0x63, 0x68, 0x61, - 0x0a, 0x6c, 0x61, 0x6e, 0x67, 0x6f, 0x73, 0x74, 0x61, 0x0a, 0x6c, 0x61, - 0x6e, 0x7a, 0x61, 0x0a, 0x6c, 0x61, 0xcc, 0x81, 0x70, 0x69, 0x7a, 0x0a, - 0x6c, 0x61, 0x72, 0x67, 0x6f, 0x0a, 0x6c, 0x61, 0x72, 0x76, 0x61, 0x0a, - 0x6c, 0x61, 0xcc, 0x81, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x0a, 0x6c, 0x61, - 0x74, 0x61, 0x0a, 0x6c, 0x61, 0xcc, 0x81, 0x74, 0x65, 0x78, 0x0a, 0x6c, - 0x61, 0x74, 0x69, 0x72, 0x0a, 0x6c, 0x61, 0x75, 0x72, 0x65, 0x6c, 0x0a, - 0x6c, 0x61, 0x76, 0x61, 0x72, 0x0a, 0x6c, 0x61, 0x7a, 0x6f, 0x0a, 0x6c, - 0x65, 0x61, 0x6c, 0x0a, 0x6c, 0x65, 0x63, 0x63, 0x69, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x6c, 0x65, 0x63, 0x68, 0x65, 0x0a, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x0a, 0x6c, 0x65, 0x65, 0x72, 0x0a, 0x6c, 0x65, 0x67, 0x69, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6c, 0x65, 0x67, 0x75, 0x6d, 0x62, 0x72, - 0x65, 0x0a, 0x6c, 0x65, 0x6a, 0x61, 0x6e, 0x6f, 0x0a, 0x6c, 0x65, 0x6e, - 0x67, 0x75, 0x61, 0x0a, 0x6c, 0x65, 0x6e, 0x74, 0x6f, 0x0a, 0x6c, 0x65, - 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x6c, 0x65, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x6c, 0x65, 0x6f, 0x70, 0x61, 0x72, 0x64, 0x6f, 0x0a, 0x6c, 0x65, 0x73, - 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6c, 0x65, 0x74, 0x61, 0x6c, 0x0a, - 0x6c, 0x65, 0x74, 0x72, 0x61, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x0a, 0x6c, - 0x65, 0x79, 0x65, 0x6e, 0x64, 0x61, 0x0a, 0x6c, 0x69, 0x62, 0x65, 0x72, - 0x74, 0x61, 0x64, 0x0a, 0x6c, 0x69, 0x62, 0x72, 0x6f, 0x0a, 0x6c, 0x69, - 0x63, 0x6f, 0x72, 0x0a, 0x6c, 0x69, 0xcc, 0x81, 0x64, 0x65, 0x72, 0x0a, - 0x6c, 0x69, 0x64, 0x69, 0x61, 0x72, 0x0a, 0x6c, 0x69, 0x65, 0x6e, 0x7a, - 0x6f, 0x0a, 0x6c, 0x69, 0x67, 0x61, 0x0a, 0x6c, 0x69, 0x67, 0x65, 0x72, - 0x6f, 0x0a, 0x6c, 0x69, 0x6d, 0x61, 0x0a, 0x6c, 0x69, 0xcc, 0x81, 0x6d, - 0x69, 0x74, 0x65, 0x0a, 0x6c, 0x69, 0x6d, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x6c, 0x69, 0x6d, 0x70, 0x69, 0x6f, 0x0a, 0x6c, 0x69, 0x6e, 0x63, 0x65, - 0x0a, 0x6c, 0x69, 0x6e, 0x64, 0x6f, 0x0a, 0x6c, 0x69, 0xcc, 0x81, 0x6e, - 0x65, 0x61, 0x0a, 0x6c, 0x69, 0x6e, 0x67, 0x6f, 0x74, 0x65, 0x0a, 0x6c, - 0x69, 0x6e, 0x6f, 0x0a, 0x6c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x0a, 0x6c, 0x69, 0xcc, 0x81, 0x71, 0x75, 0x69, 0x64, 0x6f, 0x0a, 0x6c, - 0x69, 0x73, 0x6f, 0x0a, 0x6c, 0x69, 0x73, 0x74, 0x61, 0x0a, 0x6c, 0x69, - 0x74, 0x65, 0x72, 0x61, 0x0a, 0x6c, 0x69, 0x74, 0x69, 0x6f, 0x0a, 0x6c, - 0x69, 0x74, 0x72, 0x6f, 0x0a, 0x6c, 0x6c, 0x61, 0x67, 0x61, 0x0a, 0x6c, - 0x6c, 0x61, 0x6d, 0x61, 0x0a, 0x6c, 0x6c, 0x61, 0x6e, 0x74, 0x6f, 0x0a, - 0x6c, 0x6c, 0x61, 0x76, 0x65, 0x0a, 0x6c, 0x6c, 0x65, 0x67, 0x61, 0x72, - 0x0a, 0x6c, 0x6c, 0x65, 0x6e, 0x61, 0x72, 0x0a, 0x6c, 0x6c, 0x65, 0x76, - 0x61, 0x72, 0x0a, 0x6c, 0x6c, 0x6f, 0x72, 0x61, 0x72, 0x0a, 0x6c, 0x6c, - 0x6f, 0x76, 0x65, 0x72, 0x0a, 0x6c, 0x6c, 0x75, 0x76, 0x69, 0x61, 0x0a, - 0x6c, 0x6f, 0x62, 0x6f, 0x0a, 0x6c, 0x6f, 0x63, 0x69, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x6c, 0x6f, 0x63, 0x6f, 0x0a, 0x6c, 0x6f, 0x63, 0x75, 0x72, - 0x61, 0x0a, 0x6c, 0x6f, 0xcc, 0x81, 0x67, 0x69, 0x63, 0x61, 0x0a, 0x6c, - 0x6f, 0x67, 0x72, 0x6f, 0x0a, 0x6c, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x7a, - 0x0a, 0x6c, 0x6f, 0x6d, 0x6f, 0x0a, 0x6c, 0x6f, 0x6e, 0x6a, 0x61, 0x0a, - 0x6c, 0x6f, 0x74, 0x65, 0x0a, 0x6c, 0x75, 0x63, 0x68, 0x61, 0x0a, 0x6c, - 0x75, 0x63, 0x69, 0x72, 0x0a, 0x6c, 0x75, 0x67, 0x61, 0x72, 0x0a, 0x6c, - 0x75, 0x6a, 0x6f, 0x0a, 0x6c, 0x75, 0x6e, 0x61, 0x0a, 0x6c, 0x75, 0x6e, - 0x65, 0x73, 0x0a, 0x6c, 0x75, 0x70, 0x61, 0x0a, 0x6c, 0x75, 0x73, 0x74, - 0x72, 0x6f, 0x0a, 0x6c, 0x75, 0x74, 0x6f, 0x0a, 0x6c, 0x75, 0x7a, 0x0a, - 0x6d, 0x61, 0x63, 0x65, 0x74, 0x61, 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x6f, - 0x0a, 0x6d, 0x61, 0x64, 0x65, 0x72, 0x61, 0x0a, 0x6d, 0x61, 0x64, 0x72, - 0x65, 0x0a, 0x6d, 0x61, 0x64, 0x75, 0x72, 0x6f, 0x0a, 0x6d, 0x61, 0x65, - 0x73, 0x74, 0x72, 0x6f, 0x0a, 0x6d, 0x61, 0x66, 0x69, 0x61, 0x0a, 0x6d, - 0x61, 0x67, 0x69, 0x61, 0x0a, 0x6d, 0x61, 0x67, 0x6f, 0x0a, 0x6d, 0x61, - 0x69, 0xcc, 0x81, 0x7a, 0x0a, 0x6d, 0x61, 0x6c, 0x64, 0x61, 0x64, 0x0a, - 0x6d, 0x61, 0x6c, 0x65, 0x74, 0x61, 0x0a, 0x6d, 0x61, 0x6c, 0x6c, 0x61, - 0x0a, 0x6d, 0x61, 0x6c, 0x6f, 0x0a, 0x6d, 0x61, 0x6d, 0x61, 0xcc, 0x81, - 0x0a, 0x6d, 0x61, 0x6d, 0x62, 0x6f, 0x0a, 0x6d, 0x61, 0x6d, 0x75, 0x74, - 0x0a, 0x6d, 0x61, 0x6e, 0x63, 0x6f, 0x0a, 0x6d, 0x61, 0x6e, 0x64, 0x6f, - 0x0a, 0x6d, 0x61, 0x6e, 0x65, 0x6a, 0x61, 0x72, 0x0a, 0x6d, 0x61, 0x6e, - 0x67, 0x61, 0x0a, 0x6d, 0x61, 0x6e, 0x69, 0x71, 0x75, 0x69, 0xcc, 0x81, - 0x0a, 0x6d, 0x61, 0x6e, 0x6a, 0x61, 0x72, 0x0a, 0x6d, 0x61, 0x6e, 0x6f, - 0x0a, 0x6d, 0x61, 0x6e, 0x73, 0x6f, 0x0a, 0x6d, 0x61, 0x6e, 0x74, 0x61, - 0x0a, 0x6d, 0x61, 0x6e, 0xcc, 0x83, 0x61, 0x6e, 0x61, 0x0a, 0x6d, 0x61, - 0x70, 0x61, 0x0a, 0x6d, 0x61, 0xcc, 0x81, 0x71, 0x75, 0x69, 0x6e, 0x61, - 0x0a, 0x6d, 0x61, 0x72, 0x0a, 0x6d, 0x61, 0x72, 0x63, 0x6f, 0x0a, 0x6d, - 0x61, 0x72, 0x65, 0x61, 0x0a, 0x6d, 0x61, 0x72, 0x66, 0x69, 0x6c, 0x0a, - 0x6d, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x0a, 0x6d, 0x61, 0x72, 0x69, 0x64, - 0x6f, 0x0a, 0x6d, 0x61, 0xcc, 0x81, 0x72, 0x6d, 0x6f, 0x6c, 0x0a, 0x6d, - 0x61, 0x72, 0x72, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6d, 0x61, 0x72, 0x74, - 0x65, 0x73, 0x0a, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x0a, 0x6d, 0x61, 0x73, - 0x61, 0x0a, 0x6d, 0x61, 0xcc, 0x81, 0x73, 0x63, 0x61, 0x72, 0x61, 0x0a, - 0x6d, 0x61, 0x73, 0x69, 0x76, 0x6f, 0x0a, 0x6d, 0x61, 0x74, 0x61, 0x72, - 0x0a, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x0a, 0x6d, 0x61, 0x74, - 0x69, 0x7a, 0x0a, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x7a, 0x0a, 0x6d, 0x61, - 0xcc, 0x81, 0x78, 0x69, 0x6d, 0x6f, 0x0a, 0x6d, 0x61, 0x79, 0x6f, 0x72, - 0x0a, 0x6d, 0x61, 0x7a, 0x6f, 0x72, 0x63, 0x61, 0x0a, 0x6d, 0x65, 0x63, - 0x68, 0x61, 0x0a, 0x6d, 0x65, 0x64, 0x61, 0x6c, 0x6c, 0x61, 0x0a, 0x6d, - 0x65, 0x64, 0x69, 0x6f, 0x0a, 0x6d, 0x65, 0xcc, 0x81, 0x64, 0x75, 0x6c, - 0x61, 0x0a, 0x6d, 0x65, 0x6a, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x6d, 0x65, - 0x6a, 0x6f, 0x72, 0x0a, 0x6d, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0a, 0x6d, - 0x65, 0x6c, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, - 0x69, 0x61, 0x0a, 0x6d, 0x65, 0x6e, 0x6f, 0x72, 0x0a, 0x6d, 0x65, 0x6e, - 0x73, 0x61, 0x6a, 0x65, 0x0a, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x6d, - 0x65, 0x6e, 0x75, 0xcc, 0x81, 0x0a, 0x6d, 0x65, 0x72, 0x63, 0x61, 0x64, - 0x6f, 0x0a, 0x6d, 0x65, 0x72, 0x65, 0x6e, 0x67, 0x75, 0x65, 0x0a, 0x6d, - 0x65, 0xcc, 0x81, 0x72, 0x69, 0x74, 0x6f, 0x0a, 0x6d, 0x65, 0x73, 0x0a, - 0x6d, 0x65, 0x73, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6d, 0x65, 0x74, 0x61, - 0x0a, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x0a, 0x6d, 0x65, 0xcc, 0x81, 0x74, - 0x6f, 0x64, 0x6f, 0x0a, 0x6d, 0x65, 0x74, 0x72, 0x6f, 0x0a, 0x6d, 0x65, - 0x7a, 0x63, 0x6c, 0x61, 0x0a, 0x6d, 0x69, 0x65, 0x64, 0x6f, 0x0a, 0x6d, - 0x69, 0x65, 0x6c, 0x0a, 0x6d, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x0a, - 0x6d, 0x69, 0x67, 0x61, 0x0a, 0x6d, 0x69, 0x6c, 0x0a, 0x6d, 0x69, 0x6c, - 0x61, 0x67, 0x72, 0x6f, 0x0a, 0x6d, 0x69, 0x6c, 0x69, 0x74, 0x61, 0x72, - 0x0a, 0x6d, 0x69, 0x6c, 0x6c, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6d, 0x69, - 0x6d, 0x6f, 0x0a, 0x6d, 0x69, 0x6e, 0x61, 0x0a, 0x6d, 0x69, 0x6e, 0x65, - 0x72, 0x6f, 0x0a, 0x6d, 0x69, 0xcc, 0x81, 0x6e, 0x69, 0x6d, 0x6f, 0x0a, - 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x6f, 0x0a, 0x6d, 0x69, 0x6f, 0x70, 0x65, - 0x0a, 0x6d, 0x69, 0x72, 0x61, 0x72, 0x0a, 0x6d, 0x69, 0x73, 0x61, 0x0a, - 0x6d, 0x69, 0x73, 0x65, 0x72, 0x69, 0x61, 0x0a, 0x6d, 0x69, 0x73, 0x69, - 0x6c, 0x0a, 0x6d, 0x69, 0x73, 0x6d, 0x6f, 0x0a, 0x6d, 0x69, 0x74, 0x61, - 0x64, 0x0a, 0x6d, 0x69, 0x74, 0x6f, 0x0a, 0x6d, 0x6f, 0x63, 0x68, 0x69, - 0x6c, 0x61, 0x0a, 0x6d, 0x6f, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x6d, 0x6f, 0x64, 0x61, 0x0a, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x6f, 0x0a, - 0x6d, 0x6f, 0x68, 0x6f, 0x0a, 0x6d, 0x6f, 0x6a, 0x61, 0x72, 0x0a, 0x6d, - 0x6f, 0x6c, 0x64, 0x65, 0x0a, 0x6d, 0x6f, 0x6c, 0x65, 0x72, 0x0a, 0x6d, - 0x6f, 0x6c, 0x69, 0x6e, 0x6f, 0x0a, 0x6d, 0x6f, 0x6d, 0x65, 0x6e, 0x74, - 0x6f, 0x0a, 0x6d, 0x6f, 0x6d, 0x69, 0x61, 0x0a, 0x6d, 0x6f, 0x6e, 0x61, - 0x72, 0x63, 0x61, 0x0a, 0x6d, 0x6f, 0x6e, 0x65, 0x64, 0x61, 0x0a, 0x6d, - 0x6f, 0x6e, 0x6a, 0x61, 0x0a, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x0a, 0x6d, - 0x6f, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x6d, 0x6f, 0x72, 0x61, 0x64, 0x61, - 0x0a, 0x6d, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x0a, 0x6d, 0x6f, 0x72, 0x65, - 0x6e, 0x6f, 0x0a, 0x6d, 0x6f, 0x72, 0x69, 0x72, 0x0a, 0x6d, 0x6f, 0x72, - 0x72, 0x6f, 0x0a, 0x6d, 0x6f, 0x72, 0x73, 0x61, 0x0a, 0x6d, 0x6f, 0x72, - 0x74, 0x61, 0x6c, 0x0a, 0x6d, 0x6f, 0x73, 0x63, 0x61, 0x0a, 0x6d, 0x6f, - 0x73, 0x74, 0x72, 0x61, 0x72, 0x0a, 0x6d, 0x6f, 0x74, 0x69, 0x76, 0x6f, - 0x0a, 0x6d, 0x6f, 0x76, 0x65, 0x72, 0x0a, 0x6d, 0x6f, 0xcc, 0x81, 0x76, - 0x69, 0x6c, 0x0a, 0x6d, 0x6f, 0x7a, 0x6f, 0x0a, 0x6d, 0x75, 0x63, 0x68, - 0x6f, 0x0a, 0x6d, 0x75, 0x64, 0x61, 0x72, 0x0a, 0x6d, 0x75, 0x65, 0x62, - 0x6c, 0x65, 0x0a, 0x6d, 0x75, 0x65, 0x6c, 0x61, 0x0a, 0x6d, 0x75, 0x65, - 0x72, 0x74, 0x65, 0x0a, 0x6d, 0x75, 0x65, 0x73, 0x74, 0x72, 0x61, 0x0a, - 0x6d, 0x75, 0x67, 0x72, 0x65, 0x0a, 0x6d, 0x75, 0x6a, 0x65, 0x72, 0x0a, - 0x6d, 0x75, 0x6c, 0x61, 0x0a, 0x6d, 0x75, 0x6c, 0x65, 0x74, 0x61, 0x0a, - 0x6d, 0x75, 0x6c, 0x74, 0x61, 0x0a, 0x6d, 0x75, 0x6e, 0x64, 0x6f, 0x0a, - 0x6d, 0x75, 0x6e, 0xcc, 0x83, 0x65, 0x63, 0x61, 0x0a, 0x6d, 0x75, 0x72, - 0x61, 0x6c, 0x0a, 0x6d, 0x75, 0x72, 0x6f, 0x0a, 0x6d, 0x75, 0xcc, 0x81, - 0x73, 0x63, 0x75, 0x6c, 0x6f, 0x0a, 0x6d, 0x75, 0x73, 0x65, 0x6f, 0x0a, - 0x6d, 0x75, 0x73, 0x67, 0x6f, 0x0a, 0x6d, 0x75, 0xcc, 0x81, 0x73, 0x69, - 0x63, 0x61, 0x0a, 0x6d, 0x75, 0x73, 0x6c, 0x6f, 0x0a, 0x6e, 0x61, 0xcc, - 0x81, 0x63, 0x61, 0x72, 0x0a, 0x6e, 0x61, 0x63, 0x69, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x6e, 0x61, 0x64, 0x61, 0x72, 0x0a, 0x6e, 0x61, 0x69, 0x70, - 0x65, 0x0a, 0x6e, 0x61, 0x72, 0x61, 0x6e, 0x6a, 0x61, 0x0a, 0x6e, 0x61, - 0x72, 0x69, 0x7a, 0x0a, 0x6e, 0x61, 0x72, 0x72, 0x61, 0x72, 0x0a, 0x6e, - 0x61, 0x73, 0x61, 0x6c, 0x0a, 0x6e, 0x61, 0x74, 0x61, 0x6c, 0x0a, 0x6e, - 0x61, 0x74, 0x69, 0x76, 0x6f, 0x0a, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, - 0x6c, 0x0a, 0x6e, 0x61, 0xcc, 0x81, 0x75, 0x73, 0x65, 0x61, 0x0a, 0x6e, - 0x61, 0x76, 0x61, 0x6c, 0x0a, 0x6e, 0x61, 0x76, 0x65, 0x0a, 0x6e, 0x61, - 0x76, 0x69, 0x64, 0x61, 0x64, 0x0a, 0x6e, 0x65, 0x63, 0x69, 0x6f, 0x0a, - 0x6e, 0x65, 0xcc, 0x81, 0x63, 0x74, 0x61, 0x72, 0x0a, 0x6e, 0x65, 0x67, - 0x61, 0x72, 0x0a, 0x6e, 0x65, 0x67, 0x6f, 0x63, 0x69, 0x6f, 0x0a, 0x6e, - 0x65, 0x67, 0x72, 0x6f, 0x0a, 0x6e, 0x65, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, - 0x6e, 0x65, 0x72, 0x76, 0x69, 0x6f, 0x0a, 0x6e, 0x65, 0x74, 0x6f, 0x0a, - 0x6e, 0x65, 0x75, 0x74, 0x72, 0x6f, 0x0a, 0x6e, 0x65, 0x76, 0x61, 0x72, - 0x0a, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x61, 0x0a, 0x6e, 0x69, 0x63, 0x68, - 0x6f, 0x0a, 0x6e, 0x69, 0x64, 0x6f, 0x0a, 0x6e, 0x69, 0x65, 0x62, 0x6c, - 0x61, 0x0a, 0x6e, 0x69, 0x65, 0x74, 0x6f, 0x0a, 0x6e, 0x69, 0x6e, 0xcc, - 0x83, 0x65, 0x7a, 0x0a, 0x6e, 0x69, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x6e, - 0x69, 0xcc, 0x81, 0x74, 0x69, 0x64, 0x6f, 0x0a, 0x6e, 0x69, 0x76, 0x65, - 0x6c, 0x0a, 0x6e, 0x6f, 0x62, 0x6c, 0x65, 0x7a, 0x61, 0x0a, 0x6e, 0x6f, - 0x63, 0x68, 0x65, 0x0a, 0x6e, 0x6f, 0xcc, 0x81, 0x6d, 0x69, 0x6e, 0x61, - 0x0a, 0x6e, 0x6f, 0x72, 0x69, 0x61, 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, - 0x0a, 0x6e, 0x6f, 0x72, 0x74, 0x65, 0x0a, 0x6e, 0x6f, 0x74, 0x61, 0x0a, - 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x69, 0x61, 0x0a, 0x6e, 0x6f, 0x76, 0x61, - 0x74, 0x6f, 0x0a, 0x6e, 0x6f, 0x76, 0x65, 0x6c, 0x61, 0x0a, 0x6e, 0x6f, - 0x76, 0x69, 0x6f, 0x0a, 0x6e, 0x75, 0x62, 0x65, 0x0a, 0x6e, 0x75, 0x63, - 0x61, 0x0a, 0x6e, 0x75, 0xcc, 0x81, 0x63, 0x6c, 0x65, 0x6f, 0x0a, 0x6e, - 0x75, 0x64, 0x69, 0x6c, 0x6c, 0x6f, 0x0a, 0x6e, 0x75, 0x64, 0x6f, 0x0a, - 0x6e, 0x75, 0x65, 0x72, 0x61, 0x0a, 0x6e, 0x75, 0x65, 0x76, 0x65, 0x0a, - 0x6e, 0x75, 0x65, 0x7a, 0x0a, 0x6e, 0x75, 0x6c, 0x6f, 0x0a, 0x6e, 0x75, - 0xcc, 0x81, 0x6d, 0x65, 0x72, 0x6f, 0x0a, 0x6e, 0x75, 0x74, 0x72, 0x69, - 0x61, 0x0a, 0x6f, 0x61, 0x73, 0x69, 0x73, 0x0a, 0x6f, 0x62, 0x65, 0x73, - 0x6f, 0x0a, 0x6f, 0x62, 0x69, 0x73, 0x70, 0x6f, 0x0a, 0x6f, 0x62, 0x6a, - 0x65, 0x74, 0x6f, 0x0a, 0x6f, 0x62, 0x72, 0x61, 0x0a, 0x6f, 0x62, 0x72, - 0x65, 0x72, 0x6f, 0x0a, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x72, - 0x0a, 0x6f, 0x62, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x0a, 0x6f, 0x62, 0x76, - 0x69, 0x6f, 0x0a, 0x6f, 0x63, 0x61, 0x0a, 0x6f, 0x63, 0x61, 0x73, 0x6f, - 0x0a, 0x6f, 0x63, 0x65, 0xcc, 0x81, 0x61, 0x6e, 0x6f, 0x0a, 0x6f, 0x63, - 0x68, 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x6f, 0x63, 0x68, 0x6f, 0x0a, 0x6f, - 0x63, 0x69, 0x6f, 0x0a, 0x6f, 0x63, 0x72, 0x65, 0x0a, 0x6f, 0x63, 0x74, - 0x61, 0x76, 0x6f, 0x0a, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x0a, - 0x6f, 0x63, 0x75, 0x6c, 0x74, 0x6f, 0x0a, 0x6f, 0x63, 0x75, 0x70, 0x61, - 0x72, 0x0a, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x69, 0x72, 0x0a, 0x6f, 0x64, - 0x69, 0x61, 0x72, 0x0a, 0x6f, 0x64, 0x69, 0x6f, 0x0a, 0x6f, 0x64, 0x69, - 0x73, 0x65, 0x61, 0x0a, 0x6f, 0x65, 0x73, 0x74, 0x65, 0x0a, 0x6f, 0x66, - 0x65, 0x6e, 0x73, 0x61, 0x0a, 0x6f, 0x66, 0x65, 0x72, 0x74, 0x61, 0x0a, - 0x6f, 0x66, 0x69, 0x63, 0x69, 0x6f, 0x0a, 0x6f, 0x66, 0x72, 0x65, 0x63, - 0x65, 0x72, 0x0a, 0x6f, 0x67, 0x72, 0x6f, 0x0a, 0x6f, 0x69, 0xcc, 0x81, - 0x64, 0x6f, 0x0a, 0x6f, 0x69, 0xcc, 0x81, 0x72, 0x0a, 0x6f, 0x6a, 0x6f, - 0x0a, 0x6f, 0x6c, 0x61, 0x0a, 0x6f, 0x6c, 0x65, 0x61, 0x64, 0x61, 0x0a, - 0x6f, 0x6c, 0x66, 0x61, 0x74, 0x6f, 0x0a, 0x6f, 0x6c, 0x69, 0x76, 0x6f, - 0x0a, 0x6f, 0x6c, 0x6c, 0x61, 0x0a, 0x6f, 0x6c, 0x6d, 0x6f, 0x0a, 0x6f, - 0x6c, 0x6f, 0x72, 0x0a, 0x6f, 0x6c, 0x76, 0x69, 0x64, 0x6f, 0x0a, 0x6f, - 0x6d, 0x62, 0x6c, 0x69, 0x67, 0x6f, 0x0a, 0x6f, 0x6e, 0x64, 0x61, 0x0a, - 0x6f, 0x6e, 0x7a, 0x61, 0x0a, 0x6f, 0x70, 0x61, 0x63, 0x6f, 0x0a, 0x6f, - 0x70, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x6f, 0xcc, 0x81, 0x70, - 0x65, 0x72, 0x61, 0x0a, 0x6f, 0x70, 0x69, 0x6e, 0x61, 0x72, 0x0a, 0x6f, - 0x70, 0x6f, 0x6e, 0x65, 0x72, 0x0a, 0x6f, 0x70, 0x74, 0x61, 0x72, 0x0a, - 0x6f, 0xcc, 0x81, 0x70, 0x74, 0x69, 0x63, 0x61, 0x0a, 0x6f, 0x70, 0x75, - 0x65, 0x73, 0x74, 0x6f, 0x0a, 0x6f, 0x72, 0x61, 0x63, 0x69, 0x6f, 0xcc, - 0x81, 0x6e, 0x0a, 0x6f, 0x72, 0x61, 0x64, 0x6f, 0x72, 0x0a, 0x6f, 0x72, - 0x61, 0x6c, 0x0a, 0x6f, 0xcc, 0x81, 0x72, 0x62, 0x69, 0x74, 0x61, 0x0a, - 0x6f, 0x72, 0x63, 0x61, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x6e, 0x0a, 0x6f, - 0x72, 0x65, 0x6a, 0x61, 0x0a, 0x6f, 0xcc, 0x81, 0x72, 0x67, 0x61, 0x6e, - 0x6f, 0x0a, 0x6f, 0x72, 0x67, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x6f, 0x72, - 0x67, 0x75, 0x6c, 0x6c, 0x6f, 0x0a, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, - 0x65, 0x0a, 0x6f, 0x72, 0x69, 0x67, 0x65, 0x6e, 0x0a, 0x6f, 0x72, 0x69, - 0x6c, 0x6c, 0x61, 0x0a, 0x6f, 0x72, 0x6f, 0x0a, 0x6f, 0x72, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x61, 0x0a, 0x6f, 0x72, 0x75, 0x67, 0x61, 0x0a, 0x6f, - 0x73, 0x61, 0x64, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x6f, 0x73, 0x63, 0x75, - 0x72, 0x6f, 0x0a, 0x6f, 0x73, 0x65, 0x7a, 0x6e, 0x6f, 0x0a, 0x6f, 0x73, - 0x6f, 0x0a, 0x6f, 0x73, 0x74, 0x72, 0x61, 0x0a, 0x6f, 0x74, 0x6f, 0x6e, - 0xcc, 0x83, 0x6f, 0x0a, 0x6f, 0x74, 0x72, 0x6f, 0x0a, 0x6f, 0x76, 0x65, - 0x6a, 0x61, 0x0a, 0x6f, 0xcc, 0x81, 0x76, 0x75, 0x6c, 0x6f, 0x0a, 0x6f, - 0xcc, 0x81, 0x78, 0x69, 0x64, 0x6f, 0x0a, 0x6f, 0x78, 0x69, 0xcc, 0x81, - 0x67, 0x65, 0x6e, 0x6f, 0x0a, 0x6f, 0x79, 0x65, 0x6e, 0x74, 0x65, 0x0a, - 0x6f, 0x7a, 0x6f, 0x6e, 0x6f, 0x0a, 0x70, 0x61, 0x63, 0x74, 0x6f, 0x0a, - 0x70, 0x61, 0x64, 0x72, 0x65, 0x0a, 0x70, 0x61, 0x65, 0x6c, 0x6c, 0x61, - 0x0a, 0x70, 0x61, 0xcc, 0x81, 0x67, 0x69, 0x6e, 0x61, 0x0a, 0x70, 0x61, - 0x67, 0x6f, 0x0a, 0x70, 0x61, 0x69, 0xcc, 0x81, 0x73, 0x0a, 0x70, 0x61, - 0xcc, 0x81, 0x6a, 0x61, 0x72, 0x6f, 0x0a, 0x70, 0x61, 0x6c, 0x61, 0x62, - 0x72, 0x61, 0x0a, 0x70, 0x61, 0x6c, 0x63, 0x6f, 0x0a, 0x70, 0x61, 0x6c, - 0x65, 0x74, 0x61, 0x0a, 0x70, 0x61, 0xcc, 0x81, 0x6c, 0x69, 0x64, 0x6f, - 0x0a, 0x70, 0x61, 0x6c, 0x6d, 0x61, 0x0a, 0x70, 0x61, 0x6c, 0x6f, 0x6d, - 0x61, 0x0a, 0x70, 0x61, 0x6c, 0x70, 0x61, 0x72, 0x0a, 0x70, 0x61, 0x6e, - 0x0a, 0x70, 0x61, 0x6e, 0x61, 0x6c, 0x0a, 0x70, 0x61, 0xcc, 0x81, 0x6e, - 0x69, 0x63, 0x6f, 0x0a, 0x70, 0x61, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x0a, - 0x70, 0x61, 0x6e, 0xcc, 0x83, 0x75, 0x65, 0x6c, 0x6f, 0x0a, 0x70, 0x61, - 0x70, 0x61, 0xcc, 0x81, 0x0a, 0x70, 0x61, 0x70, 0x65, 0x6c, 0x0a, 0x70, - 0x61, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x70, 0x61, 0x71, 0x75, 0x65, - 0x74, 0x65, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x72, 0x0a, 0x70, 0x61, 0x72, - 0x63, 0x65, 0x6c, 0x61, 0x0a, 0x70, 0x61, 0x72, 0x65, 0x64, 0x0a, 0x70, - 0x61, 0x72, 0x69, 0x72, 0x0a, 0x70, 0x61, 0x72, 0x6f, 0x0a, 0x70, 0x61, - 0xcc, 0x81, 0x72, 0x70, 0x61, 0x64, 0x6f, 0x0a, 0x70, 0x61, 0x72, 0x71, - 0x75, 0x65, 0x0a, 0x70, 0x61, 0xcc, 0x81, 0x72, 0x72, 0x61, 0x66, 0x6f, - 0x0a, 0x70, 0x61, 0x72, 0x74, 0x65, 0x0a, 0x70, 0x61, 0x73, 0x61, 0x72, - 0x0a, 0x70, 0x61, 0x73, 0x65, 0x6f, 0x0a, 0x70, 0x61, 0x73, 0x69, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x61, 0x73, 0x6f, 0x0a, 0x70, 0x61, 0x73, - 0x74, 0x61, 0x0a, 0x70, 0x61, 0x74, 0x61, 0x0a, 0x70, 0x61, 0x74, 0x69, - 0x6f, 0x0a, 0x70, 0x61, 0x74, 0x72, 0x69, 0x61, 0x0a, 0x70, 0x61, 0x75, - 0x73, 0x61, 0x0a, 0x70, 0x61, 0x75, 0x74, 0x61, 0x0a, 0x70, 0x61, 0x76, - 0x6f, 0x0a, 0x70, 0x61, 0x79, 0x61, 0x73, 0x6f, 0x0a, 0x70, 0x65, 0x61, - 0x74, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x65, 0x63, 0x61, 0x64, 0x6f, - 0x0a, 0x70, 0x65, 0x63, 0x65, 0x72, 0x61, 0x0a, 0x70, 0x65, 0x63, 0x68, - 0x6f, 0x0a, 0x70, 0x65, 0x64, 0x61, 0x6c, 0x0a, 0x70, 0x65, 0x64, 0x69, - 0x72, 0x0a, 0x70, 0x65, 0x67, 0x61, 0x72, 0x0a, 0x70, 0x65, 0x69, 0x6e, - 0x65, 0x0a, 0x70, 0x65, 0x6c, 0x61, 0x72, 0x0a, 0x70, 0x65, 0x6c, 0x64, - 0x61, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x70, 0x65, 0x6c, 0x65, 0x61, 0x0a, - 0x70, 0x65, 0x6c, 0x69, 0x67, 0x72, 0x6f, 0x0a, 0x70, 0x65, 0x6c, 0x6c, - 0x65, 0x6a, 0x6f, 0x0a, 0x70, 0x65, 0x6c, 0x6f, 0x0a, 0x70, 0x65, 0x6c, - 0x75, 0x63, 0x61, 0x0a, 0x70, 0x65, 0x6e, 0x61, 0x0a, 0x70, 0x65, 0x6e, - 0x73, 0x61, 0x72, 0x0a, 0x70, 0x65, 0x6e, 0xcc, 0x83, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x70, 0x65, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x65, 0x6f, - 0x72, 0x0a, 0x70, 0x65, 0x70, 0x69, 0x6e, 0x6f, 0x0a, 0x70, 0x65, 0x71, - 0x75, 0x65, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x70, 0x65, 0x72, 0x61, 0x0a, - 0x70, 0x65, 0x72, 0x63, 0x68, 0x61, 0x0a, 0x70, 0x65, 0x72, 0x64, 0x65, - 0x72, 0x0a, 0x70, 0x65, 0x72, 0x65, 0x7a, 0x61, 0x0a, 0x70, 0x65, 0x72, - 0x66, 0x69, 0x6c, 0x0a, 0x70, 0x65, 0x72, 0x69, 0x63, 0x6f, 0x0a, 0x70, - 0x65, 0x72, 0x6c, 0x61, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x6f, - 0x0a, 0x70, 0x65, 0x72, 0x72, 0x6f, 0x0a, 0x70, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x61, 0x0a, 0x70, 0x65, 0x73, 0x61, 0x0a, 0x70, 0x65, 0x73, 0x63, - 0x61, 0x0a, 0x70, 0x65, 0xcc, 0x81, 0x73, 0x69, 0x6d, 0x6f, 0x0a, 0x70, - 0x65, 0x73, 0x74, 0x61, 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x70, 0x65, 0xcc, - 0x81, 0x74, 0x61, 0x6c, 0x6f, 0x0a, 0x70, 0x65, 0x74, 0x72, 0x6f, 0xcc, - 0x81, 0x6c, 0x65, 0x6f, 0x0a, 0x70, 0x65, 0x7a, 0x0a, 0x70, 0x65, 0x7a, - 0x75, 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x70, 0x69, 0x63, 0x61, 0x72, 0x0a, - 0x70, 0x69, 0x63, 0x68, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x69, 0x65, - 0x0a, 0x70, 0x69, 0x65, 0x64, 0x72, 0x61, 0x0a, 0x70, 0x69, 0x65, 0x72, - 0x6e, 0x61, 0x0a, 0x70, 0x69, 0x65, 0x7a, 0x61, 0x0a, 0x70, 0x69, 0x6a, - 0x61, 0x6d, 0x61, 0x0a, 0x70, 0x69, 0x6c, 0x61, 0x72, 0x0a, 0x70, 0x69, - 0x6c, 0x6f, 0x74, 0x6f, 0x0a, 0x70, 0x69, 0x6d, 0x69, 0x65, 0x6e, 0x74, - 0x61, 0x0a, 0x70, 0x69, 0x6e, 0x6f, 0x0a, 0x70, 0x69, 0x6e, 0x74, 0x6f, - 0x72, 0x0a, 0x70, 0x69, 0x6e, 0x7a, 0x61, 0x0a, 0x70, 0x69, 0x6e, 0xcc, - 0x83, 0x61, 0x0a, 0x70, 0x69, 0x6f, 0x6a, 0x6f, 0x0a, 0x70, 0x69, 0x70, - 0x61, 0x0a, 0x70, 0x69, 0x72, 0x61, 0x74, 0x61, 0x0a, 0x70, 0x69, 0x73, - 0x61, 0x72, 0x0a, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6e, 0x61, 0x0a, 0x70, - 0x69, 0x73, 0x6f, 0x0a, 0x70, 0x69, 0x73, 0x74, 0x61, 0x0a, 0x70, 0x69, - 0x74, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x69, 0x7a, 0x63, 0x61, 0x0a, - 0x70, 0x6c, 0x61, 0x63, 0x61, 0x0a, 0x70, 0x6c, 0x61, 0x6e, 0x0a, 0x70, - 0x6c, 0x61, 0x74, 0x61, 0x0a, 0x70, 0x6c, 0x61, 0x79, 0x61, 0x0a, 0x70, - 0x6c, 0x61, 0x7a, 0x61, 0x0a, 0x70, 0x6c, 0x65, 0x69, 0x74, 0x6f, 0x0a, - 0x70, 0x6c, 0x65, 0x6e, 0x6f, 0x0a, 0x70, 0x6c, 0x6f, 0x6d, 0x6f, 0x0a, - 0x70, 0x6c, 0x75, 0x6d, 0x61, 0x0a, 0x70, 0x6c, 0x75, 0x72, 0x61, 0x6c, - 0x0a, 0x70, 0x6f, 0x62, 0x72, 0x65, 0x0a, 0x70, 0x6f, 0x63, 0x6f, 0x0a, - 0x70, 0x6f, 0x64, 0x65, 0x72, 0x0a, 0x70, 0x6f, 0x64, 0x69, 0x6f, 0x0a, - 0x70, 0x6f, 0x65, 0x6d, 0x61, 0x0a, 0x70, 0x6f, 0x65, 0x73, 0x69, 0xcc, - 0x81, 0x61, 0x0a, 0x70, 0x6f, 0x65, 0x74, 0x61, 0x0a, 0x70, 0x6f, 0x6c, - 0x65, 0x6e, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0xcc, 0x81, 0x61, - 0x0a, 0x70, 0x6f, 0x6c, 0x6c, 0x6f, 0x0a, 0x70, 0x6f, 0x6c, 0x76, 0x6f, - 0x0a, 0x70, 0x6f, 0x6d, 0x61, 0x64, 0x61, 0x0a, 0x70, 0x6f, 0x6d, 0x65, - 0x6c, 0x6f, 0x0a, 0x70, 0x6f, 0x6d, 0x6f, 0x0a, 0x70, 0x6f, 0x6d, 0x70, - 0x61, 0x0a, 0x70, 0x6f, 0x6e, 0x65, 0x72, 0x0a, 0x70, 0x6f, 0x72, 0x63, - 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, - 0x0a, 0x70, 0x6f, 0x73, 0x61, 0x64, 0x61, 0x0a, 0x70, 0x6f, 0x73, 0x65, - 0x65, 0x72, 0x0a, 0x70, 0x6f, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x0a, 0x70, - 0x6f, 0x73, 0x74, 0x65, 0x0a, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x69, - 0x61, 0x0a, 0x70, 0x6f, 0x74, 0x72, 0x6f, 0x0a, 0x70, 0x6f, 0x7a, 0x6f, - 0x0a, 0x70, 0x72, 0x61, 0x64, 0x6f, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x6f, - 0x7a, 0x0a, 0x70, 0x72, 0x65, 0x67, 0x75, 0x6e, 0x74, 0x61, 0x0a, 0x70, - 0x72, 0x65, 0x6d, 0x69, 0x6f, 0x0a, 0x70, 0x72, 0x65, 0x6e, 0x73, 0x61, - 0x0a, 0x70, 0x72, 0x65, 0x73, 0x6f, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, - 0x6f, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x6f, 0x0a, 0x70, 0x72, 0x69, 0xcc, - 0x81, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x0a, 0x70, 0x72, 0x69, 0x73, 0x69, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x72, 0x0a, - 0x70, 0x72, 0x6f, 0x61, 0x0a, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x72, 0x0a, - 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x6f, 0x0a, 0x70, 0x72, 0x6f, 0x64, - 0x75, 0x63, 0x74, 0x6f, 0x0a, 0x70, 0x72, 0x6f, 0x65, 0x7a, 0x61, 0x0a, - 0x70, 0x72, 0x6f, 0x66, 0x65, 0x73, 0x6f, 0x72, 0x0a, 0x70, 0x72, 0x6f, - 0x67, 0x72, 0x61, 0x6d, 0x61, 0x0a, 0x70, 0x72, 0x6f, 0x6c, 0x65, 0x0a, - 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x73, 0x61, 0x0a, 0x70, 0x72, 0x6f, 0x6e, - 0x74, 0x6f, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x69, 0x6f, 0x0a, 0x70, 0x72, - 0x6f, 0xcc, 0x81, 0x78, 0x69, 0x6d, 0x6f, 0x0a, 0x70, 0x72, 0x75, 0x65, - 0x62, 0x61, 0x0a, 0x70, 0x75, 0xcc, 0x81, 0x62, 0x6c, 0x69, 0x63, 0x6f, - 0x0a, 0x70, 0x75, 0x63, 0x68, 0x65, 0x72, 0x6f, 0x0a, 0x70, 0x75, 0x64, - 0x6f, 0x72, 0x0a, 0x70, 0x75, 0x65, 0x62, 0x6c, 0x6f, 0x0a, 0x70, 0x75, - 0x65, 0x72, 0x74, 0x61, 0x0a, 0x70, 0x75, 0x65, 0x73, 0x74, 0x6f, 0x0a, - 0x70, 0x75, 0x6c, 0x67, 0x61, 0x0a, 0x70, 0x75, 0x6c, 0x69, 0x72, 0x0a, - 0x70, 0x75, 0x6c, 0x6d, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x70, 0x75, 0x6c, - 0x70, 0x6f, 0x0a, 0x70, 0x75, 0x6c, 0x73, 0x6f, 0x0a, 0x70, 0x75, 0x6d, - 0x61, 0x0a, 0x70, 0x75, 0x6e, 0x74, 0x6f, 0x0a, 0x70, 0x75, 0x6e, 0xcc, - 0x83, 0x61, 0x6c, 0x0a, 0x70, 0x75, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x70, - 0x75, 0x70, 0x61, 0x0a, 0x70, 0x75, 0x70, 0x69, 0x6c, 0x61, 0x0a, 0x70, - 0x75, 0x72, 0x65, 0xcc, 0x81, 0x0a, 0x71, 0x75, 0x65, 0x64, 0x61, 0x72, - 0x0a, 0x71, 0x75, 0x65, 0x6a, 0x61, 0x0a, 0x71, 0x75, 0x65, 0x6d, 0x61, - 0x72, 0x0a, 0x71, 0x75, 0x65, 0x72, 0x65, 0x72, 0x0a, 0x71, 0x75, 0x65, - 0x73, 0x6f, 0x0a, 0x71, 0x75, 0x69, 0x65, 0x74, 0x6f, 0x0a, 0x71, 0x75, - 0x69, 0xcc, 0x81, 0x6d, 0x69, 0x63, 0x61, 0x0a, 0x71, 0x75, 0x69, 0x6e, - 0x63, 0x65, 0x0a, 0x71, 0x75, 0x69, 0x74, 0x61, 0x72, 0x0a, 0x72, 0x61, - 0xcc, 0x81, 0x62, 0x61, 0x6e, 0x6f, 0x0a, 0x72, 0x61, 0x62, 0x69, 0x61, - 0x0a, 0x72, 0x61, 0x62, 0x6f, 0x0a, 0x72, 0x61, 0x63, 0x69, 0x6f, 0xcc, - 0x81, 0x6e, 0x0a, 0x72, 0x61, 0x64, 0x69, 0x63, 0x61, 0x6c, 0x0a, 0x72, - 0x61, 0x69, 0xcc, 0x81, 0x7a, 0x0a, 0x72, 0x61, 0x6d, 0x61, 0x0a, 0x72, - 0x61, 0x6d, 0x70, 0x61, 0x0a, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x0a, - 0x72, 0x61, 0x6e, 0x67, 0x6f, 0x0a, 0x72, 0x61, 0x70, 0x61, 0x7a, 0x0a, - 0x72, 0x61, 0xcc, 0x81, 0x70, 0x69, 0x64, 0x6f, 0x0a, 0x72, 0x61, 0x70, - 0x74, 0x6f, 0x0a, 0x72, 0x61, 0x73, 0x67, 0x6f, 0x0a, 0x72, 0x61, 0x73, - 0x70, 0x61, 0x0a, 0x72, 0x61, 0x74, 0x6f, 0x0a, 0x72, 0x61, 0x79, 0x6f, - 0x0a, 0x72, 0x61, 0x7a, 0x61, 0x0a, 0x72, 0x61, 0x7a, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x72, 0x65, 0x61, 0x63, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x72, 0x65, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x64, 0x0a, 0x72, 0x65, - 0x62, 0x61, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x72, 0x65, 0x62, 0x6f, 0x74, - 0x65, 0x0a, 0x72, 0x65, 0x63, 0x61, 0x65, 0x72, 0x0a, 0x72, 0x65, 0x63, - 0x65, 0x74, 0x61, 0x0a, 0x72, 0x65, 0x63, 0x68, 0x61, 0x7a, 0x6f, 0x0a, - 0x72, 0x65, 0x63, 0x6f, 0x67, 0x65, 0x72, 0x0a, 0x72, 0x65, 0x63, 0x72, - 0x65, 0x6f, 0x0a, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x0a, 0x72, 0x65, 0x63, - 0x75, 0x72, 0x73, 0x6f, 0x0a, 0x72, 0x65, 0x64, 0x0a, 0x72, 0x65, 0x64, - 0x6f, 0x6e, 0x64, 0x6f, 0x0a, 0x72, 0x65, 0x64, 0x75, 0x63, 0x69, 0x72, - 0x0a, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x6a, 0x6f, 0x0a, 0x72, 0x65, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x0a, 0x72, 0x65, 0x66, 0x72, 0x61, 0xcc, 0x81, - 0x6e, 0x0a, 0x72, 0x65, 0x66, 0x75, 0x67, 0x69, 0x6f, 0x0a, 0x72, 0x65, - 0x67, 0x61, 0x6c, 0x6f, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x72, 0x0a, 0x72, - 0x65, 0x67, 0x6c, 0x61, 0x0a, 0x72, 0x65, 0x67, 0x72, 0x65, 0x73, 0x6f, - 0x0a, 0x72, 0x65, 0x68, 0x65, 0xcc, 0x81, 0x6e, 0x0a, 0x72, 0x65, 0x69, - 0x6e, 0x6f, 0x0a, 0x72, 0x65, 0x69, 0xcc, 0x81, 0x72, 0x0a, 0x72, 0x65, - 0x6a, 0x61, 0x0a, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x6f, 0x0a, 0x72, 0x65, - 0x6c, 0x65, 0x76, 0x6f, 0x0a, 0x72, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, - 0x0a, 0x72, 0x65, 0x6c, 0x6c, 0x65, 0x6e, 0x6f, 0x0a, 0x72, 0x65, 0x6c, - 0x6f, 0x6a, 0x0a, 0x72, 0x65, 0x6d, 0x61, 0x72, 0x0a, 0x72, 0x65, 0x6d, - 0x65, 0x64, 0x69, 0x6f, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x0a, 0x72, 0x65, - 0x6e, 0x63, 0x6f, 0x72, 0x0a, 0x72, 0x65, 0x6e, 0x64, 0x69, 0x72, 0x0a, - 0x72, 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x72, 0x65, 0x70, 0x61, 0x72, 0x74, - 0x6f, 0x0a, 0x72, 0x65, 0x70, 0x65, 0x74, 0x69, 0x72, 0x0a, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x6f, 0x0a, 0x72, 0x65, 0x70, 0x74, 0x69, 0x6c, 0x0a, - 0x72, 0x65, 0x73, 0x0a, 0x72, 0x65, 0x73, 0x63, 0x61, 0x74, 0x65, 0x0a, - 0x72, 0x65, 0x73, 0x69, 0x6e, 0x61, 0x0a, 0x72, 0x65, 0x73, 0x70, 0x65, - 0x74, 0x6f, 0x0a, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x0a, 0x72, 0x65, 0x73, - 0x75, 0x6d, 0x65, 0x6e, 0x0a, 0x72, 0x65, 0x74, 0x69, 0x72, 0x6f, 0x0a, - 0x72, 0x65, 0x74, 0x6f, 0x72, 0x6e, 0x6f, 0x0a, 0x72, 0x65, 0x74, 0x72, - 0x61, 0x74, 0x6f, 0x0a, 0x72, 0x65, 0x75, 0x6e, 0x69, 0x72, 0x0a, 0x72, - 0x65, 0x76, 0x65, 0xcc, 0x81, 0x73, 0x0a, 0x72, 0x65, 0x76, 0x69, 0x73, - 0x74, 0x61, 0x0a, 0x72, 0x65, 0x79, 0x0a, 0x72, 0x65, 0x7a, 0x61, 0x72, - 0x0a, 0x72, 0x69, 0x63, 0x6f, 0x0a, 0x72, 0x69, 0x65, 0x67, 0x6f, 0x0a, - 0x72, 0x69, 0x65, 0x6e, 0x64, 0x61, 0x0a, 0x72, 0x69, 0x65, 0x73, 0x67, - 0x6f, 0x0a, 0x72, 0x69, 0x66, 0x61, 0x0a, 0x72, 0x69, 0xcc, 0x81, 0x67, - 0x69, 0x64, 0x6f, 0x0a, 0x72, 0x69, 0x67, 0x6f, 0x72, 0x0a, 0x72, 0x69, - 0x6e, 0x63, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x72, 0x69, 0x6e, 0xcc, 0x83, - 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x72, 0x69, 0xcc, 0x81, 0x6f, 0x0a, 0x72, - 0x69, 0x71, 0x75, 0x65, 0x7a, 0x61, 0x0a, 0x72, 0x69, 0x73, 0x61, 0x0a, - 0x72, 0x69, 0x74, 0x6d, 0x6f, 0x0a, 0x72, 0x69, 0x74, 0x6f, 0x0a, 0x72, - 0x69, 0x7a, 0x6f, 0x0a, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x0a, 0x72, 0x6f, - 0x63, 0x65, 0x0a, 0x72, 0x6f, 0x63, 0x69, 0x61, 0x72, 0x0a, 0x72, 0x6f, - 0x64, 0x61, 0x72, 0x0a, 0x72, 0x6f, 0x64, 0x65, 0x6f, 0x0a, 0x72, 0x6f, - 0x64, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x72, 0x6f, 0x65, 0x72, 0x0a, 0x72, - 0x6f, 0x6a, 0x69, 0x7a, 0x6f, 0x0a, 0x72, 0x6f, 0x6a, 0x6f, 0x0a, 0x72, - 0x6f, 0x6d, 0x65, 0x72, 0x6f, 0x0a, 0x72, 0x6f, 0x6d, 0x70, 0x65, 0x72, - 0x0a, 0x72, 0x6f, 0x6e, 0x0a, 0x72, 0x6f, 0x6e, 0x63, 0x6f, 0x0a, 0x72, - 0x6f, 0x6e, 0x64, 0x61, 0x0a, 0x72, 0x6f, 0x70, 0x61, 0x0a, 0x72, 0x6f, - 0x70, 0x65, 0x72, 0x6f, 0x0a, 0x72, 0x6f, 0x73, 0x61, 0x0a, 0x72, 0x6f, - 0x73, 0x63, 0x61, 0x0a, 0x72, 0x6f, 0x73, 0x74, 0x72, 0x6f, 0x0a, 0x72, - 0x6f, 0x74, 0x61, 0x72, 0x0a, 0x72, 0x75, 0x62, 0x69, 0xcc, 0x81, 0x0a, - 0x72, 0x75, 0x62, 0x6f, 0x72, 0x0a, 0x72, 0x75, 0x64, 0x6f, 0x0a, 0x72, - 0x75, 0x65, 0x64, 0x61, 0x0a, 0x72, 0x75, 0x67, 0x69, 0x72, 0x0a, 0x72, - 0x75, 0x69, 0x64, 0x6f, 0x0a, 0x72, 0x75, 0x69, 0x6e, 0x61, 0x0a, 0x72, - 0x75, 0x6c, 0x65, 0x74, 0x61, 0x0a, 0x72, 0x75, 0x6c, 0x6f, 0x0a, 0x72, - 0x75, 0x6d, 0x62, 0x6f, 0x0a, 0x72, 0x75, 0x6d, 0x6f, 0x72, 0x0a, 0x72, - 0x75, 0x70, 0x74, 0x75, 0x72, 0x61, 0x0a, 0x72, 0x75, 0x74, 0x61, 0x0a, - 0x72, 0x75, 0x74, 0x69, 0x6e, 0x61, 0x0a, 0x73, 0x61, 0xcc, 0x81, 0x62, - 0x61, 0x64, 0x6f, 0x0a, 0x73, 0x61, 0x62, 0x65, 0x72, 0x0a, 0x73, 0x61, - 0x62, 0x69, 0x6f, 0x0a, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x73, 0x61, - 0x63, 0x61, 0x72, 0x0a, 0x73, 0x61, 0x67, 0x61, 0x7a, 0x0a, 0x73, 0x61, - 0x67, 0x72, 0x61, 0x64, 0x6f, 0x0a, 0x73, 0x61, 0x6c, 0x61, 0x0a, 0x73, - 0x61, 0x6c, 0x64, 0x6f, 0x0a, 0x73, 0x61, 0x6c, 0x65, 0x72, 0x6f, 0x0a, - 0x73, 0x61, 0x6c, 0x69, 0x72, 0x0a, 0x73, 0x61, 0x6c, 0x6d, 0x6f, 0xcc, - 0x81, 0x6e, 0x0a, 0x73, 0x61, 0x6c, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x73, - 0x61, 0x6c, 0x73, 0x61, 0x0a, 0x73, 0x61, 0x6c, 0x74, 0x6f, 0x0a, 0x73, - 0x61, 0x6c, 0x75, 0x64, 0x0a, 0x73, 0x61, 0x6c, 0x76, 0x61, 0x72, 0x0a, - 0x73, 0x61, 0x6d, 0x62, 0x61, 0x0a, 0x73, 0x61, 0x6e, 0x63, 0x69, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x61, 0x6e, 0x64, 0x69, 0xcc, 0x81, 0x61, - 0x0a, 0x73, 0x61, 0x6e, 0x65, 0x61, 0x72, 0x0a, 0x73, 0x61, 0x6e, 0x67, - 0x72, 0x65, 0x0a, 0x73, 0x61, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x0a, 0x73, - 0x61, 0x6e, 0x6f, 0x0a, 0x73, 0x61, 0x6e, 0x74, 0x6f, 0x0a, 0x73, 0x61, - 0x70, 0x6f, 0x0a, 0x73, 0x61, 0x71, 0x75, 0x65, 0x0a, 0x73, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x61, 0x0a, 0x73, 0x61, 0x72, 0x74, 0x65, 0xcc, 0x81, - 0x6e, 0x0a, 0x73, 0x61, 0x73, 0x74, 0x72, 0x65, 0x0a, 0x73, 0x61, 0x74, - 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x61, 0x75, 0x6e, 0x61, 0x0a, 0x73, - 0x61, 0x78, 0x6f, 0x66, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x65, 0x63, - 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x65, 0x63, 0x6f, 0x0a, - 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x6f, 0x0a, 0x73, 0x65, 0x63, 0x74, - 0x61, 0x0a, 0x73, 0x65, 0x64, 0x0a, 0x73, 0x65, 0x67, 0x75, 0x69, 0x72, - 0x0a, 0x73, 0x65, 0x69, 0x73, 0x0a, 0x73, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, - 0x73, 0x65, 0x6c, 0x76, 0x61, 0x0a, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x61, - 0x0a, 0x73, 0x65, 0x6d, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x73, 0x65, 0x6e, - 0x64, 0x61, 0x0a, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x0a, 0x73, 0x65, - 0x6e, 0xcc, 0x83, 0x61, 0x6c, 0x0a, 0x73, 0x65, 0x6e, 0xcc, 0x83, 0x6f, - 0x72, 0x0a, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x72, 0x0a, 0x73, 0x65, - 0x70, 0x69, 0x61, 0x0a, 0x73, 0x65, 0x71, 0x75, 0x69, 0xcc, 0x81, 0x61, - 0x0a, 0x73, 0x65, 0x72, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x65, 0x0a, 0x73, - 0x65, 0x72, 0x6d, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x72, 0x0a, 0x73, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x73, - 0x65, 0x73, 0x69, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x65, 0x74, 0x61, - 0x0a, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x73, 0x65, 0x76, - 0x65, 0x72, 0x6f, 0x0a, 0x73, 0x65, 0x78, 0x6f, 0x0a, 0x73, 0x65, 0x78, - 0x74, 0x6f, 0x0a, 0x73, 0x69, 0x64, 0x72, 0x61, 0x0a, 0x73, 0x69, 0x65, - 0x73, 0x74, 0x61, 0x0a, 0x73, 0x69, 0x65, 0x74, 0x65, 0x0a, 0x73, 0x69, - 0x67, 0x6c, 0x6f, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x6f, 0x0a, 0x73, 0x69, - 0xcc, 0x81, 0x6c, 0x61, 0x62, 0x61, 0x0a, 0x73, 0x69, 0x6c, 0x62, 0x61, - 0x72, 0x0a, 0x73, 0x69, 0x6c, 0x65, 0x6e, 0x63, 0x69, 0x6f, 0x0a, 0x73, - 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x73, 0x69, 0xcc, 0x81, 0x6d, 0x62, 0x6f, - 0x6c, 0x6f, 0x0a, 0x73, 0x69, 0x6d, 0x69, 0x6f, 0x0a, 0x73, 0x69, 0x72, - 0x65, 0x6e, 0x61, 0x0a, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6d, 0x61, 0x0a, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x0a, 0x73, 0x69, 0x74, 0x75, 0x61, 0x72, - 0x0a, 0x73, 0x6f, 0x62, 0x72, 0x65, 0x0a, 0x73, 0x6f, 0x63, 0x69, 0x6f, - 0x0a, 0x73, 0x6f, 0x64, 0x69, 0x6f, 0x0a, 0x73, 0x6f, 0x6c, 0x0a, 0x73, - 0x6f, 0x6c, 0x61, 0x70, 0x61, 0x0a, 0x73, 0x6f, 0x6c, 0x64, 0x61, 0x64, - 0x6f, 0x0a, 0x73, 0x6f, 0x6c, 0x65, 0x64, 0x61, 0x64, 0x0a, 0x73, 0x6f, - 0xcc, 0x81, 0x6c, 0x69, 0x64, 0x6f, 0x0a, 0x73, 0x6f, 0x6c, 0x74, 0x61, - 0x72, 0x0a, 0x73, 0x6f, 0x6c, 0x75, 0x63, 0x69, 0x6f, 0xcc, 0x81, 0x6e, - 0x0a, 0x73, 0x6f, 0x6d, 0x62, 0x72, 0x61, 0x0a, 0x73, 0x6f, 0x6e, 0x64, - 0x65, 0x6f, 0x0a, 0x73, 0x6f, 0x6e, 0x69, 0x64, 0x6f, 0x0a, 0x73, 0x6f, - 0x6e, 0x6f, 0x72, 0x6f, 0x0a, 0x73, 0x6f, 0x6e, 0x72, 0x69, 0x73, 0x61, - 0x0a, 0x73, 0x6f, 0x70, 0x61, 0x0a, 0x73, 0x6f, 0x70, 0x6c, 0x61, 0x72, - 0x0a, 0x73, 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x0a, 0x73, 0x6f, 0x72, - 0x64, 0x6f, 0x0a, 0x73, 0x6f, 0x72, 0x70, 0x72, 0x65, 0x73, 0x61, 0x0a, - 0x73, 0x6f, 0x72, 0x74, 0x65, 0x6f, 0x0a, 0x73, 0x6f, 0x73, 0x74, 0x65, - 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x6f, 0xcc, 0x81, 0x74, 0x61, 0x6e, 0x6f, - 0x0a, 0x73, 0x75, 0x61, 0x76, 0x65, 0x0a, 0x73, 0x75, 0x62, 0x69, 0x72, - 0x0a, 0x73, 0x75, 0x63, 0x65, 0x73, 0x6f, 0x0a, 0x73, 0x75, 0x64, 0x6f, - 0x72, 0x0a, 0x73, 0x75, 0x65, 0x67, 0x72, 0x61, 0x0a, 0x73, 0x75, 0x65, - 0x6c, 0x6f, 0x0a, 0x73, 0x75, 0x65, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x73, - 0x75, 0x65, 0x72, 0x74, 0x65, 0x0a, 0x73, 0x75, 0x66, 0x72, 0x69, 0x72, - 0x0a, 0x73, 0x75, 0x6a, 0x65, 0x74, 0x6f, 0x0a, 0x73, 0x75, 0x6c, 0x74, - 0x61, 0xcc, 0x81, 0x6e, 0x0a, 0x73, 0x75, 0x6d, 0x61, 0x72, 0x0a, 0x73, - 0x75, 0x70, 0x65, 0x72, 0x61, 0x72, 0x0a, 0x73, 0x75, 0x70, 0x6c, 0x69, - 0x72, 0x0a, 0x73, 0x75, 0x70, 0x6f, 0x6e, 0x65, 0x72, 0x0a, 0x73, 0x75, - 0x70, 0x72, 0x65, 0x6d, 0x6f, 0x0a, 0x73, 0x75, 0x72, 0x0a, 0x73, 0x75, - 0x72, 0x63, 0x6f, 0x0a, 0x73, 0x75, 0x72, 0x65, 0x6e, 0xcc, 0x83, 0x6f, - 0x0a, 0x73, 0x75, 0x72, 0x67, 0x69, 0x72, 0x0a, 0x73, 0x75, 0x73, 0x74, - 0x6f, 0x0a, 0x73, 0x75, 0x74, 0x69, 0x6c, 0x0a, 0x74, 0x61, 0x62, 0x61, - 0x63, 0x6f, 0x0a, 0x74, 0x61, 0x62, 0x69, 0x71, 0x75, 0x65, 0x0a, 0x74, - 0x61, 0x62, 0x6c, 0x61, 0x0a, 0x74, 0x61, 0x62, 0x75, 0xcc, 0x81, 0x0a, - 0x74, 0x61, 0x63, 0x6f, 0x0a, 0x74, 0x61, 0x63, 0x74, 0x6f, 0x0a, 0x74, - 0x61, 0x6a, 0x6f, 0x0a, 0x74, 0x61, 0x6c, 0x61, 0x72, 0x0a, 0x74, 0x61, - 0x6c, 0x63, 0x6f, 0x0a, 0x74, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x6f, 0x0a, - 0x74, 0x61, 0x6c, 0x6c, 0x61, 0x0a, 0x74, 0x61, 0x6c, 0x6f, 0xcc, 0x81, - 0x6e, 0x0a, 0x74, 0x61, 0x6d, 0x61, 0x6e, 0xcc, 0x83, 0x6f, 0x0a, 0x74, - 0x61, 0x6d, 0x62, 0x6f, 0x72, 0x0a, 0x74, 0x61, 0x6e, 0x67, 0x6f, 0x0a, - 0x74, 0x61, 0x6e, 0x71, 0x75, 0x65, 0x0a, 0x74, 0x61, 0x70, 0x61, 0x0a, - 0x74, 0x61, 0x70, 0x65, 0x74, 0x65, 0x0a, 0x74, 0x61, 0x70, 0x69, 0x61, - 0x0a, 0x74, 0x61, 0x70, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x74, 0x61, 0x71, - 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x74, 0x61, 0x72, 0x64, 0x65, 0x0a, - 0x74, 0x61, 0x72, 0x65, 0x61, 0x0a, 0x74, 0x61, 0x72, 0x69, 0x66, 0x61, - 0x0a, 0x74, 0x61, 0x72, 0x6a, 0x65, 0x74, 0x61, 0x0a, 0x74, 0x61, 0x72, - 0x6f, 0x74, 0x0a, 0x74, 0x61, 0x72, 0x72, 0x6f, 0x0a, 0x74, 0x61, 0x72, - 0x74, 0x61, 0x0a, 0x74, 0x61, 0x74, 0x75, 0x61, 0x6a, 0x65, 0x0a, 0x74, - 0x61, 0x75, 0x72, 0x6f, 0x0a, 0x74, 0x61, 0x7a, 0x61, 0x0a, 0x74, 0x61, - 0x7a, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x74, 0x65, 0x61, 0x74, 0x72, 0x6f, - 0x0a, 0x74, 0x65, 0x63, 0x68, 0x6f, 0x0a, 0x74, 0x65, 0x63, 0x6c, 0x61, - 0x0a, 0x74, 0x65, 0xcc, 0x81, 0x63, 0x6e, 0x69, 0x63, 0x61, 0x0a, 0x74, - 0x65, 0x6a, 0x61, 0x64, 0x6f, 0x0a, 0x74, 0x65, 0x6a, 0x65, 0x72, 0x0a, - 0x74, 0x65, 0x6a, 0x69, 0x64, 0x6f, 0x0a, 0x74, 0x65, 0x6c, 0x61, 0x0a, - 0x74, 0x65, 0x6c, 0x65, 0xcc, 0x81, 0x66, 0x6f, 0x6e, 0x6f, 0x0a, 0x74, - 0x65, 0x6d, 0x61, 0x0a, 0x74, 0x65, 0x6d, 0x6f, 0x72, 0x0a, 0x74, 0x65, - 0x6d, 0x70, 0x6c, 0x6f, 0x0a, 0x74, 0x65, 0x6e, 0x61, 0x7a, 0x0a, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x0a, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x0a, - 0x74, 0x65, 0x6e, 0x69, 0x73, 0x0a, 0x74, 0x65, 0x6e, 0x73, 0x6f, 0x0a, - 0x74, 0x65, 0x6f, 0x72, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x74, 0x65, 0x72, - 0x61, 0x70, 0x69, 0x61, 0x0a, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x0a, 0x74, - 0x65, 0xcc, 0x81, 0x72, 0x6d, 0x69, 0x6e, 0x6f, 0x0a, 0x74, 0x65, 0x72, - 0x6e, 0x75, 0x72, 0x61, 0x0a, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0a, - 0x74, 0x65, 0x73, 0x69, 0x73, 0x0a, 0x74, 0x65, 0x73, 0x6f, 0x72, 0x6f, - 0x0a, 0x74, 0x65, 0x73, 0x74, 0x69, 0x67, 0x6f, 0x0a, 0x74, 0x65, 0x74, - 0x65, 0x72, 0x61, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x6f, 0x0a, 0x74, 0x65, - 0x7a, 0x0a, 0x74, 0x69, 0x62, 0x69, 0x6f, 0x0a, 0x74, 0x69, 0x62, 0x75, - 0x72, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x74, 0x69, 0x65, 0x6d, 0x70, 0x6f, - 0x0a, 0x74, 0x69, 0x65, 0x6e, 0x64, 0x61, 0x0a, 0x74, 0x69, 0x65, 0x72, - 0x72, 0x61, 0x0a, 0x74, 0x69, 0x65, 0x73, 0x6f, 0x0a, 0x74, 0x69, 0x67, - 0x72, 0x65, 0x0a, 0x74, 0x69, 0x6a, 0x65, 0x72, 0x61, 0x0a, 0x74, 0x69, - 0x6c, 0x64, 0x65, 0x0a, 0x74, 0x69, 0x6d, 0x62, 0x72, 0x65, 0x0a, 0x74, - 0x69, 0xcc, 0x81, 0x6d, 0x69, 0x64, 0x6f, 0x0a, 0x74, 0x69, 0x6d, 0x6f, - 0x0a, 0x74, 0x69, 0x6e, 0x74, 0x61, 0x0a, 0x74, 0x69, 0xcc, 0x81, 0x6f, - 0x0a, 0x74, 0x69, 0xcc, 0x81, 0x70, 0x69, 0x63, 0x6f, 0x0a, 0x74, 0x69, - 0x70, 0x6f, 0x0a, 0x74, 0x69, 0x72, 0x61, 0x0a, 0x74, 0x69, 0x72, 0x6f, - 0xcc, 0x81, 0x6e, 0x0a, 0x74, 0x69, 0x74, 0x61, 0xcc, 0x81, 0x6e, 0x0a, - 0x74, 0x69, 0xcc, 0x81, 0x74, 0x65, 0x72, 0x65, 0x0a, 0x74, 0x69, 0xcc, - 0x81, 0x74, 0x75, 0x6c, 0x6f, 0x0a, 0x74, 0x69, 0x7a, 0x61, 0x0a, 0x74, - 0x6f, 0x61, 0x6c, 0x6c, 0x61, 0x0a, 0x74, 0x6f, 0x62, 0x69, 0x6c, 0x6c, - 0x6f, 0x0a, 0x74, 0x6f, 0x63, 0x61, 0x72, 0x0a, 0x74, 0x6f, 0x63, 0x69, - 0x6e, 0x6f, 0x0a, 0x74, 0x6f, 0x64, 0x6f, 0x0a, 0x74, 0x6f, 0x67, 0x61, - 0x0a, 0x74, 0x6f, 0x6c, 0x64, 0x6f, 0x0a, 0x74, 0x6f, 0x6d, 0x61, 0x72, - 0x0a, 0x74, 0x6f, 0x6e, 0x6f, 0x0a, 0x74, 0x6f, 0x6e, 0x74, 0x6f, 0x0a, - 0x74, 0x6f, 0x70, 0x61, 0x72, 0x0a, 0x74, 0x6f, 0x70, 0x65, 0x0a, 0x74, - 0x6f, 0x71, 0x75, 0x65, 0x0a, 0x74, 0x6f, 0xcc, 0x81, 0x72, 0x61, 0x78, - 0x0a, 0x74, 0x6f, 0x72, 0x65, 0x72, 0x6f, 0x0a, 0x74, 0x6f, 0x72, 0x6d, - 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x74, 0x6f, 0x72, 0x6e, 0x65, 0x6f, 0x0a, - 0x74, 0x6f, 0x72, 0x6f, 0x0a, 0x74, 0x6f, 0x72, 0x70, 0x65, 0x64, 0x6f, - 0x0a, 0x74, 0x6f, 0x72, 0x72, 0x65, 0x0a, 0x74, 0x6f, 0x72, 0x73, 0x6f, - 0x0a, 0x74, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x0a, 0x74, 0x6f, 0x73, - 0x0a, 0x74, 0x6f, 0x73, 0x63, 0x6f, 0x0a, 0x74, 0x6f, 0x73, 0x65, 0x72, - 0x0a, 0x74, 0x6f, 0xcc, 0x81, 0x78, 0x69, 0x63, 0x6f, 0x0a, 0x74, 0x72, - 0x61, 0x62, 0x61, 0x6a, 0x6f, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, - 0x72, 0x0a, 0x74, 0x72, 0x61, 0x65, 0x72, 0x0a, 0x74, 0x72, 0x61, 0xcc, - 0x81, 0x66, 0x69, 0x63, 0x6f, 0x0a, 0x74, 0x72, 0x61, 0x67, 0x6f, 0x0a, - 0x74, 0x72, 0x61, 0x6a, 0x65, 0x0a, 0x74, 0x72, 0x61, 0x6d, 0x6f, 0x0a, - 0x74, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x0a, 0x74, 0x72, 0x61, 0x74, 0x6f, - 0x0a, 0x74, 0x72, 0x61, 0x75, 0x6d, 0x61, 0x0a, 0x74, 0x72, 0x61, 0x7a, - 0x61, 0x72, 0x0a, 0x74, 0x72, 0x65, 0xcc, 0x81, 0x62, 0x6f, 0x6c, 0x0a, - 0x74, 0x72, 0x65, 0x67, 0x75, 0x61, 0x0a, 0x74, 0x72, 0x65, 0x69, 0x6e, - 0x74, 0x61, 0x0a, 0x74, 0x72, 0x65, 0x6e, 0x0a, 0x74, 0x72, 0x65, 0x70, - 0x61, 0x72, 0x0a, 0x74, 0x72, 0x65, 0x73, 0x0a, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x0a, 0x74, 0x72, 0x69, 0x67, 0x6f, 0x0a, 0x74, 0x72, 0x69, 0x70, - 0x61, 0x0a, 0x74, 0x72, 0x69, 0x73, 0x74, 0x65, 0x0a, 0x74, 0x72, 0x69, - 0x75, 0x6e, 0x66, 0x6f, 0x0a, 0x74, 0x72, 0x6f, 0x66, 0x65, 0x6f, 0x0a, - 0x74, 0x72, 0x6f, 0x6d, 0x70, 0x61, 0x0a, 0x74, 0x72, 0x6f, 0x6e, 0x63, - 0x6f, 0x0a, 0x74, 0x72, 0x6f, 0x70, 0x61, 0x0a, 0x74, 0x72, 0x6f, 0x74, - 0x65, 0x0a, 0x74, 0x72, 0x6f, 0x7a, 0x6f, 0x0a, 0x74, 0x72, 0x75, 0x63, - 0x6f, 0x0a, 0x74, 0x72, 0x75, 0x65, 0x6e, 0x6f, 0x0a, 0x74, 0x72, 0x75, - 0x66, 0x61, 0x0a, 0x74, 0x75, 0x62, 0x65, 0x72, 0x69, 0xcc, 0x81, 0x61, - 0x0a, 0x74, 0x75, 0x62, 0x6f, 0x0a, 0x74, 0x75, 0x65, 0x72, 0x74, 0x6f, - 0x0a, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x0a, 0x74, 0x75, 0x6d, 0x6f, 0x72, - 0x0a, 0x74, 0x75, 0xcc, 0x81, 0x6e, 0x65, 0x6c, 0x0a, 0x74, 0x75, 0xcc, - 0x81, 0x6e, 0x69, 0x63, 0x61, 0x0a, 0x74, 0x75, 0x72, 0x62, 0x69, 0x6e, - 0x61, 0x0a, 0x74, 0x75, 0x72, 0x69, 0x73, 0x6d, 0x6f, 0x0a, 0x74, 0x75, - 0x72, 0x6e, 0x6f, 0x0a, 0x74, 0x75, 0x74, 0x6f, 0x72, 0x0a, 0x75, 0x62, - 0x69, 0x63, 0x61, 0x72, 0x0a, 0x75, 0xcc, 0x81, 0x6c, 0x63, 0x65, 0x72, - 0x61, 0x0a, 0x75, 0x6d, 0x62, 0x72, 0x61, 0x6c, 0x0a, 0x75, 0x6e, 0x69, - 0x64, 0x61, 0x64, 0x0a, 0x75, 0x6e, 0x69, 0x72, 0x0a, 0x75, 0x6e, 0x69, - 0x76, 0x65, 0x72, 0x73, 0x6f, 0x0a, 0x75, 0x6e, 0x6f, 0x0a, 0x75, 0x6e, - 0x74, 0x61, 0x72, 0x0a, 0x75, 0x6e, 0xcc, 0x83, 0x61, 0x0a, 0x75, 0x72, - 0x62, 0x61, 0x6e, 0x6f, 0x0a, 0x75, 0x72, 0x62, 0x65, 0x0a, 0x75, 0x72, - 0x67, 0x65, 0x6e, 0x74, 0x65, 0x0a, 0x75, 0x72, 0x6e, 0x61, 0x0a, 0x75, - 0x73, 0x61, 0x72, 0x0a, 0x75, 0x73, 0x75, 0x61, 0x72, 0x69, 0x6f, 0x0a, - 0x75, 0xcc, 0x81, 0x74, 0x69, 0x6c, 0x0a, 0x75, 0x74, 0x6f, 0x70, 0x69, - 0xcc, 0x81, 0x61, 0x0a, 0x75, 0x76, 0x61, 0x0a, 0x76, 0x61, 0x63, 0x61, - 0x0a, 0x76, 0x61, 0x63, 0x69, 0xcc, 0x81, 0x6f, 0x0a, 0x76, 0x61, 0x63, - 0x75, 0x6e, 0x61, 0x0a, 0x76, 0x61, 0x67, 0x61, 0x72, 0x0a, 0x76, 0x61, - 0x67, 0x6f, 0x0a, 0x76, 0x61, 0x69, 0x6e, 0x61, 0x0a, 0x76, 0x61, 0x6a, - 0x69, 0x6c, 0x6c, 0x61, 0x0a, 0x76, 0x61, 0x6c, 0x65, 0x0a, 0x76, 0x61, - 0xcc, 0x81, 0x6c, 0x69, 0x64, 0x6f, 0x0a, 0x76, 0x61, 0x6c, 0x6c, 0x65, - 0x0a, 0x76, 0x61, 0x6c, 0x6f, 0x72, 0x0a, 0x76, 0x61, 0xcc, 0x81, 0x6c, - 0x76, 0x75, 0x6c, 0x61, 0x0a, 0x76, 0x61, 0x6d, 0x70, 0x69, 0x72, 0x6f, - 0x0a, 0x76, 0x61, 0x72, 0x61, 0x0a, 0x76, 0x61, 0x72, 0x69, 0x61, 0x72, - 0x0a, 0x76, 0x61, 0x72, 0x6f, 0xcc, 0x81, 0x6e, 0x0a, 0x76, 0x61, 0x73, - 0x6f, 0x0a, 0x76, 0x65, 0x63, 0x69, 0x6e, 0x6f, 0x0a, 0x76, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x0a, 0x76, 0x65, 0x68, 0x69, 0xcc, 0x81, 0x63, 0x75, - 0x6c, 0x6f, 0x0a, 0x76, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x0a, 0x76, 0x65, - 0x6a, 0x65, 0x7a, 0x0a, 0x76, 0x65, 0x6c, 0x61, 0x0a, 0x76, 0x65, 0x6c, - 0x65, 0x72, 0x6f, 0x0a, 0x76, 0x65, 0x6c, 0x6f, 0x7a, 0x0a, 0x76, 0x65, - 0x6e, 0x61, 0x0a, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x0a, 0x76, 0x65, - 0x6e, 0x64, 0x61, 0x0a, 0x76, 0x65, 0x6e, 0x65, 0x6e, 0x6f, 0x0a, 0x76, - 0x65, 0x6e, 0x67, 0x61, 0x72, 0x0a, 0x76, 0x65, 0x6e, 0x69, 0x72, 0x0a, - 0x76, 0x65, 0x6e, 0x74, 0x61, 0x0a, 0x76, 0x65, 0x6e, 0x75, 0x73, 0x0a, - 0x76, 0x65, 0x72, 0x0a, 0x76, 0x65, 0x72, 0x61, 0x6e, 0x6f, 0x0a, 0x76, - 0x65, 0x72, 0x62, 0x6f, 0x0a, 0x76, 0x65, 0x72, 0x64, 0x65, 0x0a, 0x76, - 0x65, 0x72, 0x65, 0x64, 0x61, 0x0a, 0x76, 0x65, 0x72, 0x6a, 0x61, 0x0a, - 0x76, 0x65, 0x72, 0x73, 0x6f, 0x0a, 0x76, 0x65, 0x72, 0x74, 0x65, 0x72, - 0x0a, 0x76, 0x69, 0xcc, 0x81, 0x61, 0x0a, 0x76, 0x69, 0x61, 0x6a, 0x65, - 0x0a, 0x76, 0x69, 0x62, 0x72, 0x61, 0x72, 0x0a, 0x76, 0x69, 0x63, 0x69, - 0x6f, 0x0a, 0x76, 0x69, 0xcc, 0x81, 0x63, 0x74, 0x69, 0x6d, 0x61, 0x0a, - 0x76, 0x69, 0x64, 0x61, 0x0a, 0x76, 0x69, 0xcc, 0x81, 0x64, 0x65, 0x6f, - 0x0a, 0x76, 0x69, 0x64, 0x72, 0x69, 0x6f, 0x0a, 0x76, 0x69, 0x65, 0x6a, - 0x6f, 0x0a, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x0a, 0x76, 0x69, - 0x67, 0x6f, 0x72, 0x0a, 0x76, 0x69, 0x6c, 0x0a, 0x76, 0x69, 0x6c, 0x6c, - 0x61, 0x0a, 0x76, 0x69, 0x6e, 0x61, 0x67, 0x72, 0x65, 0x0a, 0x76, 0x69, - 0x6e, 0x6f, 0x0a, 0x76, 0x69, 0x6e, 0xcc, 0x83, 0x65, 0x64, 0x6f, 0x0a, - 0x76, 0x69, 0x6f, 0x6c, 0x69, 0xcc, 0x81, 0x6e, 0x0a, 0x76, 0x69, 0x72, - 0x61, 0x6c, 0x0a, 0x76, 0x69, 0x72, 0x67, 0x6f, 0x0a, 0x76, 0x69, 0x72, - 0x74, 0x75, 0x64, 0x0a, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x0a, 0x76, 0x69, - 0xcc, 0x81, 0x73, 0x70, 0x65, 0x72, 0x61, 0x0a, 0x76, 0x69, 0x73, 0x74, - 0x61, 0x0a, 0x76, 0x69, 0x74, 0x61, 0x6d, 0x69, 0x6e, 0x61, 0x0a, 0x76, - 0x69, 0x75, 0x64, 0x6f, 0x0a, 0x76, 0x69, 0x76, 0x61, 0x7a, 0x0a, 0x76, - 0x69, 0x76, 0x65, 0x72, 0x6f, 0x0a, 0x76, 0x69, 0x76, 0x69, 0x72, 0x0a, - 0x76, 0x69, 0x76, 0x6f, 0x0a, 0x76, 0x6f, 0x6c, 0x63, 0x61, 0xcc, 0x81, - 0x6e, 0x0a, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x6e, 0x0a, 0x76, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x0a, 0x76, 0x6f, 0x72, 0x61, 0x7a, 0x0a, 0x76, - 0x6f, 0x74, 0x61, 0x72, 0x0a, 0x76, 0x6f, 0x74, 0x6f, 0x0a, 0x76, 0x6f, - 0x7a, 0x0a, 0x76, 0x75, 0x65, 0x6c, 0x6f, 0x0a, 0x76, 0x75, 0x6c, 0x67, - 0x61, 0x72, 0x0a, 0x79, 0x61, 0x63, 0x65, 0x72, 0x0a, 0x79, 0x61, 0x74, - 0x65, 0x0a, 0x79, 0x65, 0x67, 0x75, 0x61, 0x0a, 0x79, 0x65, 0x6d, 0x61, - 0x0a, 0x79, 0x65, 0x72, 0x6e, 0x6f, 0x0a, 0x79, 0x65, 0x73, 0x6f, 0x0a, - 0x79, 0x6f, 0x64, 0x6f, 0x0a, 0x79, 0x6f, 0x67, 0x61, 0x0a, 0x79, 0x6f, - 0x67, 0x75, 0x72, 0x0a, 0x7a, 0x61, 0x66, 0x69, 0x72, 0x6f, 0x0a, 0x7a, - 0x61, 0x6e, 0x6a, 0x61, 0x0a, 0x7a, 0x61, 0x70, 0x61, 0x74, 0x6f, 0x0a, - 0x7a, 0x61, 0x72, 0x7a, 0x61, 0x0a, 0x7a, 0x6f, 0x6e, 0x61, 0x0a, 0x7a, - 0x6f, 0x72, 0x72, 0x6f, 0x0a, 0x7a, 0x75, 0x6d, 0x6f, 0x0a, 0x7a, 0x75, - 0x72, 0x64, 0x6f, 0x0a +// SPDX-FileCopyrightText: © 2025 ALIAS Developers +// SPDX-FileCopyrightText: © 2020 Alias Developers +// SPDX-FileCopyrightText: © 2016 SpectreCoin Developers +// SPDX-FileCopyrightText: © 2009 Bitcoin Developers +// SPDX-FileCopyrightText: © 2009 Satoshi Nakamoto +// +// SPDX-License-Identifier: MIT + +#ifndef BITCOIN_DB_H +#define BITCOIN_DB_H + +#include "main.h" + +#include +#include +#include + +#include + +class CAddress; +class CAddrMan; +class CBlockLocator; +class CDiskBlockIndex; +class CDiskTxPos; +class CMasterKey; +class COutPoint; +class CTxIndex; +class CWallet; +class CWalletTx; + +extern unsigned int nWalletDBUpdated; + +void ThreadFlushWalletDB(const std::string& strFile); +bool BackupWallet(const CWallet& wallet, const std::string& strDest); + + +class CDBEnv +{ +private: + bool fDetachDB; + bool fDbEnvInit; + bool fMockDb; + fs::path pathEnv; + std::string strPath; + + void EnvShutdown(); + +public: + mutable CCriticalSection cs_db; + DbEnv dbenv; + std::map mapFileUseCount; + std::map mapDb; + + CDBEnv(); + ~CDBEnv(); + void MakeMock(); + bool IsMock() { return fMockDb; }; + + /* + * Verify that database file strFile is OK. If it is not, + * call the callback to try to recover. + * This must be called BEFORE strFile is opened. + * Returns true if strFile is OK. + */ + enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; + VerifyResult Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile)); + /* + * Salvage data from a file that Verify says is bad. + * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). + * Appends binary key/value pairs to vResult, returns true if successful. + * NOTE: reads the entire database into memory, so cannot be used + * for huge databases. + */ + typedef std::pair, std::vector > KeyValPair; + bool Salvage(std::string strFile, bool fAggressive, std::vector& vResult); + + bool Open(fs::path pathEnv_); + void Close(); + void Flush(bool fShutdown); + + void CheckpointLSN(const std::string& strFile); + void SetDetach(bool fDetachDB_) { fDetachDB = fDetachDB_; } + bool GetDetach() { return fDetachDB; } + + void CloseDb(const std::string& strFile); + bool RemoveDb(const std::string& strFile); + + DbTxn *TxnBegin(int flags=DB_TXN_WRITE_NOSYNC) + { + DbTxn* ptxn = nullptr; + int ret = dbenv.txn_begin(nullptr, &ptxn, flags); + if (!ptxn || ret != 0) + return nullptr; + return ptxn; + } }; -unsigned int spanish_txt_len = 13996; + +extern CDBEnv bitdb; + + +/** RAII class that provides access to a Berkeley database */ +class CDB +{ +protected: + Db* pdb; + std::string strFile; + DbTxn *activeTxn; + bool fReadOnly; + + explicit CDB(const std::string& strFilename, const char* pszMode="r+"); + ~CDB() { Close(); } + +public: + void Close(); + +private: + CDB(const CDB&); + void operator=(const CDB&); + +protected: + template + bool Read(const K& key, T& value, uint32_t nFlags=0) + { + if (!pdb) + return false; + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Read + Dbt datValue; + datValue.set_flags(DB_DBT_MALLOC); + int ret = pdb->get(activeTxn, &datKey, &datValue, nFlags); + memset(datKey.get_data(), 0, datKey.get_size()); + if (datValue.get_data() == nullptr) + return false; + + // Unserialize value + try { + CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION); + ssValue >> value; + } + catch (std::exception &e) { + return false; + } + + // Clear and free memory + memset(datValue.get_data(), 0, datValue.get_size()); + free(datValue.get_data()); + return (ret == 0); + } + + template + bool Write(const K& key, const T& value, bool fOverwrite=true) + { + if (!pdb) + return false; + + if (fReadOnly) + assert(!"Write called on database in read-only mode"); + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Value + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.reserve(10000); + ssValue << value; + Dbt datValue(&ssValue[0], ssValue.size()); + + // Write + int ret = pdb->put(activeTxn, &datKey, &datValue, (fOverwrite ? 0 : DB_NOOVERWRITE)); + + // Clear memory in case it was a private key + memset(datKey.get_data(), 0, datKey.get_size()); + memset(datValue.get_data(), 0, datValue.get_size()); + + return (ret == 0); + } + + template + bool Erase(const K& key) + { + if (!pdb) + return false; + if (fReadOnly) + assert(!"Erase called on database in read-only mode"); + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Erase + int ret = pdb->del(activeTxn, &datKey, 0); + + // Clear memory + memset(datKey.get_data(), 0, datKey.get_size()); + return (ret == 0 || ret == DB_NOTFOUND); + } + + template + bool Exists(const K& key) + { + if (!pdb) + return false; + + // Key + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + ssKey.reserve(1000); + ssKey << key; + Dbt datKey(&ssKey[0], ssKey.size()); + + // Exists + int ret = pdb->exists(activeTxn, &datKey, 0); + + // Clear memory + memset(datKey.get_data(), 0, datKey.get_size()); + return (ret == 0); + } + + Dbc* GetCursor() + { + if (!pdb) + return nullptr; + Dbc* pcursor = nullptr; + int ret = pdb->cursor(nullptr, &pcursor, 0); + if (ret != 0) + return nullptr; + return pcursor; + } + + +public: + + int ReadAtCursor(Dbc* pcursor, CDataStream& ssKey, CDataStream& ssValue, unsigned int fFlags=DB_NEXT) + { + // Read at cursor + Dbt datKey; + if (fFlags == DB_SET || fFlags == DB_SET_RANGE || fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) + { + datKey.set_data(&ssKey[0]); + datKey.set_size(ssKey.size()); + } + Dbt datValue; + if (fFlags == DB_GET_BOTH || fFlags == DB_GET_BOTH_RANGE) + { + datValue.set_data(&ssValue[0]); + datValue.set_size(ssValue.size()); + } + datKey.set_flags(DB_DBT_MALLOC); + datValue.set_flags(DB_DBT_MALLOC); + int ret = pcursor->get(&datKey, &datValue, fFlags); + if (ret != 0) + return ret; + else if (datKey.get_data() == nullptr || datValue.get_data() == nullptr) + return 99999; + + // Convert to streams + ssKey.SetType(SER_DISK); + ssKey.clear(); + ssKey.write((char*)datKey.get_data(), datKey.get_size()); + ssValue.SetType(SER_DISK); + ssValue.clear(); + ssValue.write((char*)datValue.get_data(), datValue.get_size()); + + // Clear and free memory + memset(datKey.get_data(), 0, datKey.get_size()); + memset(datValue.get_data(), 0, datValue.get_size()); + free(datKey.get_data()); + free(datValue.get_data()); + return 0; + } + + bool TxnBegin() + { + if (!pdb || activeTxn) + return false; + DbTxn* ptxn = bitdb.TxnBegin(); + if (!ptxn) + return false; + activeTxn = ptxn; + return true; + } + + bool TxnCommit() + { + if (!pdb || !activeTxn) + return false; + int ret = activeTxn->commit(0); + activeTxn = nullptr; + return (ret == 0); + } + + bool TxnAbort() + { + if (!pdb || !activeTxn) + return false; + int ret = activeTxn->abort(); + activeTxn = nullptr; + return (ret == 0); + } + + bool ReadVersion(int& nVersion) + { + nVersion = 0; + return Read(std::string("version"), nVersion); + } + + bool WriteVersion(int nVersion) + { + return Write(std::string("version"), nVersion); + } + + bool static Rewrite(const std::string& strFile, const char* pszSkip = nullptr); +}; + + +/** Access to the (IP) address database (peers.dat) */ +class CAddrDB +{ +private: + fs::path pathAddr; +public: + CAddrDB(); + bool Write(const CAddrMan& addr); + bool Read(CAddrMan& addr); +}; + +#endif // BITCOIN_DB_H diff --git a/src/xxhash/CMakeLists.txt b/src/xxhash/CMakeLists.txt new file mode 100644 index 0000000000..8a9f6feca9 --- /dev/null +++ b/src/xxhash/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: © 2025 ALIAS Developers +# SPDX-FileCopyrightText: © 2020 Alias Developers +# SPDX-FileCopyrightText: © 2019 SpectreCoin Developers +# SPDX-License-Identifier: MIT + +target_sources(aliaswallet_lib + PUBLIC + "${CMAKE_CURRENT_LIST_DIR}/xxhash.h" + PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/xxhash.c" +) \ No newline at end of file diff --git a/src/leveldb/LICENSE b/src/xxhash/LICENSE.txt similarity index 74% rename from src/leveldb/LICENSE rename to src/xxhash/LICENSE.txt index 8e80208cd7..26ad11f7c5 100644 --- a/src/leveldb/LICENSE +++ b/src/xxhash/LICENSE.txt @@ -1,18 +1,17 @@ -Copyright (c) 2011 The LevelDB Authors. All rights reserved. +xxHash - Fast Hash algorithm +Copyright (C) 2012-2014, Yann Collet. +BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above +* 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. - * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT diff --git a/src/xxhash/xxhash.c b/src/xxhash/xxhash.c index c55b33985e..e05ed43ee7 100644 --- a/src/xxhash/xxhash.c +++ b/src/xxhash/xxhash.c @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 2012 Yann Collet +// +// SPDX-License-Identifier: BSD-2-Clause + /* xxHash - Fast Hash algorithm Copyright (C) 2012-2014, Yann Collet. @@ -69,7 +73,7 @@ You can contact the author at : #ifdef _MSC_VER // Visual Studio # define FORCE_INLINE static __forceinline -#else +#else # ifdef __GNUC__ # define FORCE_INLINE static inline __attribute__((always_inline)) # else @@ -191,11 +195,11 @@ typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align) -{ +{ if (align==XXH_unaligned) - return endian==XXH_littleEndian ? A32_XXH(ptr) : XXH_swap32(A32_XXH(ptr)); + return endian==XXH_littleEndian ? A32_XXH(ptr) : XXH_swap32(A32_XXH(ptr)); else - return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); + return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); } FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } @@ -308,15 +312,15 @@ struct XXH_state32_t }; -int XXH32_sizeofState() +int XXH32_sizeofState() { XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough - return sizeof(struct XXH_state32_t); + return sizeof(struct XXH_state32_t); } XXH_errorcode XXH32_resetState(void* state_in, U32 seed) -{ +{ struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; state->seed = seed; state->v1 = seed + PRIME32_1 + PRIME32_2; @@ -362,7 +366,7 @@ FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* inpu { const U32* p32 = (const U32*)state->memory; state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; - state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; + state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; } @@ -404,7 +408,7 @@ FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* inpu XXH_errorcode XXH32_update (void* state_in, const void* input, int len) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_update_endian(state_in, input, len, XXH_littleEndian); else @@ -458,7 +462,7 @@ FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess U32 XXH32_intermediateDigest (void* state_in) { XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian); else diff --git a/src/xxhash/xxhash.h b/src/xxhash/xxhash.h index 84910994f9..69ec806080 100644 --- a/src/xxhash/xxhash.h +++ b/src/xxhash/xxhash.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: © 2012 Yann Collet +// +// SPDX-License-Identifier: BSD-2-Clause + /* xxHash - Fast Hash algorithm Header File @@ -7,14 +11,14 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -52,8 +56,8 @@ CRC32 0.43 GB/s 9 MD5-32 0.33 GB/s 10 Ronald L. Rivest SHA1-32 0.28 GB/s 10 -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. 10 is a perfect score. */ @@ -110,8 +114,8 @@ This pointer must be provided as "void* state" parameter for XXH32_update(). XXH32_update() can be called as many times as necessary. The user must provide a valid (allocated) input. The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. -Note that "len" is type "int", which means it is limited to 2^31-1. -If your data is larger, it is recommended to chunk your data into blocks +Note that "len" is type "int", which means it is limited to 2^31-1. +If your data is larger, it is recommended to chunk your data into blocks of size for example 2^30 (1GB) to avoid any "int" overflow issue. Finally, you can end the calculation anytime, by using XXH32_digest().