diff --git a/.gitignore b/.gitignore index 09fcc1ee..7a767137 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,6 @@ local.properties # VS Code .vscode + +# Document +doc diff --git a/.travis.yml b/.travis.yml index 04bd608f..3f613680 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ cache: apt: true os: linux +dist: trusty addons: apt: @@ -86,6 +87,17 @@ matrix: env: - COMPILERS="CC=gcc-7 CXX=g++-7" - COMPILE=main + - name: g++-7 daemon DISABLE x86 64bit elliptic curve + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: + - COMPILERS="CC=gcc-7 CXX=g++-7" + - DEF_CMAKE_OPTIONS="CMAKE_OPTIONS=-DUSE_EC_64=OFF" + - COMPILE=main - name: g++-7 test addons: apt: @@ -176,6 +188,7 @@ install: sudo apt-get install -y libldns-dev; sudo apt-get install -y libgtest-dev; sudo apt-get install -y libunwind8-dev; + sudo apt-get install -y nasm; fi # clang 5.0 ships libunwind in own lib folder - if [ "$CC" == "clang-5.0" ] ; then @@ -184,14 +197,15 @@ install: script: - eval "${COMPILERS}" + - eval "${DEF_CMAKE_OPTIONS}" - cd $HOME - | if [ "$COMPILE" == "main" ] ; then - mkdir linux-x64-build - cd linux-x64-build - cmake -DCMAKE_INSTALL_PREFIX=$HOME/ryo-linux-x64-release -DARCH="x86-64" -DBUILD_64=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_TAG="linux-x64-release" $TRAVIS_BUILD_DIR - make -j "$NUMBER_OF_CPUS" - make install + mkdir linux-x64-build && + cd linux-x64-build && + cmake -DCMAKE_INSTALL_PREFIX=$HOME/ryo-linux-x64-release -DARCH="x86-64" -DBUILD_64=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_TAG="linux-x64-release" $CMAKE_OPTIONS $TRAVIS_BUILD_DIR && + make -j "$NUMBER_OF_CPUS" && + make install && cd bin # runtime tests are currently disabled because the help is exiting with error code 1 #for prog in $(find . -type f -executable) @@ -201,14 +215,14 @@ script: #done elif [ "$COMPILE" == "tests" ] ; then # compile tests - cd $HOME - mkdir linux-x64-tests-build - cd linux-x64-tests-build - cmake -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug $TRAVIS_BUILD_DIR + cd $HOME && + mkdir linux-x64-tests-build && + cd linux-x64-tests-build && + cmake -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug $CMAKE_OPTIONS $TRAVIS_BUILD_DIR && # build all tests - make -j "$NUMBER_OF_CPUS" + make -j "$NUMBER_OF_CPUS" && # run unit tests - cd tests + cd tests && ctest -V else echo "not supported compile option '$COMPILE'" diff --git a/CMakeLists.txt b/CMakeLists.txt index 97bf2d1d..4f60f93b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Copyright (c) 2014-2018, The Monero Project # # All rights reserved. @@ -29,7 +29,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -58,6 +58,65 @@ cmake_minimum_required(VERSION 3.1.0) project(ryo) +# enforce C++11 +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD 11) + +# enforce C11 +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_C_STANDARD 11) + +# helper function to generate options +function(ryo_option name description default) + set(USE_${name} ${default} CACHE STRING "${description}") + set_property(CACHE USE_${name} PROPERTY + STRINGS "ON;TRUE;AUTO;OFF;FALSE") + if(HAVE_${name}) + set(HAVE_${name} TRUE PARENT_SCOPE) + else() + set(HAVE_${name} PARENT_SCOPE) + endif() +endfunction() + +# detect 64bit x86 architecture and set ARCH_X86_64 +if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") + set(ARCH_X86_64 TRUE) +elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") + set(ARCH_X86_64 TRUE) +elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") + # cmake reports AMD64 on Windows, but we might be building for 32-bit. + if (CMAKE_CL_64) + set(ARCH_X86_64 TRUE) + endif() +endif() + +################################################################################ +### ELLIPTIC CURVE +ryo_option(EC_64 "use optimized x86 64bit elliptic curve implementation" AUTO) +# check if x86_64 elliptic curve implementation can be used +if(USE_EC_64 STREQUAL AUTO) + enable_language(ASM_NASM OPTIONAL) + if(ARCH_X86_64 AND CMAKE_ASM_NASM_COMPILER) + set(HAVE_EC_64 TRUE) + endif() +elseif(USE_EC_64) + enable_language(ASM_NASM) + if(NOT CMAKE_ASM_NASM_COMPILER_LOADED) + message(FATAL_ERROR "Could not load NASM compiler.") + endif() + set(HAVE_EC_64 TRUE) +endif() + +if(HAVE_EC_64) + message(STATUS "Using 64bit elliptic curve implementation for x68_64") + add_definitions("-DHAVE_EC_64") +endif() + +### ELLIPTIC CURVE +################################################################################ + function (die msg) if (NOT WIN32) string(ASCII 27 Esc) @@ -248,7 +307,7 @@ endif() # elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*") # set(BSDI TRUE) -include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external) +include_directories(external/rapidjson/include src contrib/epee/include external) if(APPLE) include_directories(SYSTEM /usr/include/malloc) @@ -369,10 +428,6 @@ add_definitions("-DBLOCKCHAIN_DB=${BLOCKCHAIN_DB}") if (APPLE) set(DEFAULT_STACK_TRACE OFF) set(LIBUNWIND_LIBRARIES "") -elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW) - set(DEFAULT_STACK_TRACE ON) - set(STACK_TRACE_LIB "easylogging++") # for diag output only - set(LIBUNWIND_LIBRARIES "") elseif (ARM AND STATIC) set(DEFAULT_STACK_TRACE OFF) set(LIBUNWIND_LIBRARIES "") @@ -430,8 +485,6 @@ add_definition_if_library_exists(c memset_s "string.h" HAVE_MEMSET_S) add_definition_if_library_exists(c explicit_bzero "strings.h" HAVE_EXPLICIT_BZERO) add_definition_if_function_found(strptime HAVE_STRPTIME) -add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP) - # Generate header for embedded translations include(ExternalProject) ExternalProject_Add(generate_translations_header @@ -446,10 +499,6 @@ add_subdirectory(external) include_directories(${UNBOUND_INCLUDE}) link_directories(${UNBOUND_LIBRARY_DIRS}) -# Final setup for easylogging++ -include_directories(${EASYLOGGING_INCLUDE}) -link_directories(${EASYLOGGING_LIBRARY_DIRS}) - # Final setup for liblmdb include_directories(${LMDB_INCLUDE}) @@ -621,8 +670,8 @@ else() message(STATUS "AES support disabled") endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS}") # With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that @@ -786,6 +835,11 @@ if (${BOOST_IGNORE_SYSTEM_PATHS} STREQUAL "ON") endif() set(OLD_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + +if(MINGW) + set(Boost_NO_BOOST_CMAKE ON) +endif() + if(STATIC) if(MINGW) set(CMAKE_FIND_LIBRARY_SUFFIXES .a) @@ -801,7 +855,7 @@ if(NOT Boost_FOUND) die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (1.58) or the equivalent") elseif(Boost_FOUND) message(STATUS "Found Boost Version: ${Boost_VERSION}") - if (Boost_VERSION VERSION_LESS 106200 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1)) + if (Boost_VERSION VERSION_LESS 1.62.0 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1)) message(FATAL_ERROR "Boost older than 1.62 is too old to link with OpenSSL 1.1 or newer. " "Update Boost or install OpenSSL 1.0 and set path to it when running cmake: " "cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0;/usr/lib/openssl-1.0'") diff --git a/Doxyfile b/Doxyfile index f622c618..51d5d223 100644 --- a/Doxyfile +++ b/Doxyfile @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Monero" +PROJECT_NAME = "Ryo" # 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 diff --git a/LICENSE b/LICENSE index 344aa641..8a208b4f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2018, Ryo Currency Project +Copyright (c) 2019, Ryo Currency Project Portions of this software are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ As long as the following conditions are met: Authors and copyright holders agree that: 8. This licence expires and the work covered by it is released into the - public domain on 1st of February 2019 + public domain on 1st of February 2020 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 diff --git a/README.md b/README.md index 432e4efb..919ee5fd 100644 --- a/README.md +++ b/README.md @@ -1,592 +1,113 @@ -# Ryo +[](https://ryo-currency.com/ryo-serious-competitor-to-monero) -Copyright (c) 2018, Ryo Currency Project - -Copyright (c) 2014-2017, The Monero Project - -Copyright (c) 2012-2013, The Cryptonote developers - -Copyright (c) 2017, Sumokoin.org - - -## Development Resources - -- Web: [ryo-currency.com](https://ryo-currency.com) +Ryo is one of very few cryptonote currencies that does actual, rapid development. Its team is led by fireice_uk, mosu_forge and psychocrypt who are the developers of [Cryptonight-GPU](https://medium.com/@crypto_ryo/cryptonight-gpu-fpga-proof-pow-algorithm-based-on-floating-point-instructions-92524debf8e8) and [Cryptonight-Heavy](https://github.com/ryo-currency/ryo-writeups/blob/master/cn-heavy.md) mining algorithms, GUI Wallet with built-in GPU solo mining feature called [Ryo Wallet Atom](https://ryo-currency.com/atom) and [Xmr-Stak](https://github.com/fireice-uk/xmr-stak/releases) miner. +- Website: [ryo-currency.com](https://ryo-currency.com) - Mail: [contact@ryo-currency.com](mailto:contact@ryo-currency.com) -Please note that code is developed on the [dev branch](https://github.com/ryo-currency/ryo-currency/tree/dev), if you want to check out the latest updates, before they are merged on main branch, please refer there. Master branch will always point to a version that we consider stable, so you can download the code by simply typing `git clone https://github.com/ryo-currency/ryo-currency.git` +## Contents +| | | +| --- | --- | +| 1. [Introduction](#introduction) | 7. [Community](#community) | +| 2. [Check Development and get release binaries](#check-development-and-get-release-binaries) | 8. [Compiling Ryo from source](doc/compiling.md) | +| 3. [Project Roadmap](#project-roadmap) | 9. [Debugging](doc/debugging.md) | +| 4. [Features](#features) | 10. [LMDB](doc/lmdb.md) | +| 5. [Research and contributing](#research-and-contributing) | 11. [Using Ryo with TOR and Readline](doc/tor_readline.md) | +| 6. [Coin Supply & Emission](#coin-supply--emission) | 12. [Licensing details](#licensing-details) | + ## Introduction +Ryo (両 in Japanese: one syllable) is the most **secure, private and untraceable cryptocurrency out there**. Ryo originated from the [_Tael_](https://en.wikipedia.org/wiki/Ry%C5%8D), an ancient Far East unit of weight standard used for exchanging gold and silver. Based on the foundations of Monero, Ryo emerged and is poised to dominate the privacy conscious crypto scene. Ryo is a fork of Sumokoin. You can read all fork-related information [here](doc/sumokoin.md). -Ryo (両 in Japanese: one syllable) is the most **secure, private and untraceable cryptocurrency out there**. Ryo originated from the _Tael_, an ancient Far East unit of weight standard used for exchanging gold and silver. Based on the foundations of Monero, Ryo emerged and is poised to dominate the privacy conscious crypto scene. Backed by a full featured and balanced development team headed by the legendary fireice_uk and psychocrypt. +## Check Development and get release binaries +[](https://github.com/ryo-currency/ryo-currency/commits/dev) -Our blockchain ensures the highest level of privacy out there by -from the get-go having(1) **Ring Confidential Transactions (RingCT)** (2) and hardcoding **minimum transaction _mixin_ to 12**. These settings significantly reduce the chance of being identified, traced or attacked by blockchain statistical analysis. +Please note that code is developed on the [dev branch](https://github.com/ryo-currency/ryo-currency/tree/dev), if you want to check out the latest updates, before they are merged on main branch, please refer there. Master branch will always point to a version that we consider stable, so you can download the code by simply typing `git clone https://github.com/ryo-currency/ryo-currency.git` -Ryo has a very high privacy setting that is suitable for all high confidential transactions as well as for storage of value without being traced, monitored or identified. We call this **true fungibility**. This means that each coin is **equal** and **interchangable**; it is highly unlikely that any coin can ever by blacklisted due to previous transactions. Over the course of many years these characteristics will pay off as crypto attacks become more sophisticated with much greater computation power in the future. +Along with each release you can find our [precompiled binaries](https://github.com/ryo-currency/ryo-currency/releases). +To verify that the downloaded binaries are created by one of our developer please verify the checksums. +The authenticity of the checksums can be verified with the [PGP-key's](doc/pgp_keys.md). + + +## Project Roadmap +The Ryo dev team has several vectors of development, and it has already brought results that we can see. +[](https://ryo-currency.com#roadmap) +Navigate to Ryo official website to explore development track record and [roadmap](https://ryo-currency.com#roadmap) details. + + +## Features +We have a solid track record and unique features that are not copied from other projects: + + +[](https://github.com/ryo-currency/ryo-currency/pull/206) +### Core: +- **Built-in elliptic curve library**. This library significantly increases wallet scan speeds compared to other CN projects. +- **[Cryptonight-GPU mining algorithm](https://medium.com/@crypto_ryo/cryptonight-gpu-fpga-proof-pow-algorithm-based-on-floating-point-instructions-92524debf8e8)**. ASIC/FPGA/BOTNET resistant mining algorithm. GPU friendly and suitable for both AMD and Nvidia cards. +- **Uniform payment ID-s**. Our uniform payment ID system, makes transactions that use payment ID-s untraceable and hides the very fact that you use ID-s. +- **Default ring size of transactions set to 25**. Increased default ring size significantly reduces the chance of being identified, traced or attacked by blockchain statistical analysis. +- **QWMA mining difficulty algorithm**. Reworked network difficulty adjustment algorithm, to make it more adaptive to network hashrate fluctuations thus bringing more stabillity. +- **[Poisson probability check](https://github.com/ryo-currency/ryo-writeups/blob/master/poisson-writeup.md)**. This feature stops Verge-like offline timestamp attacks. +- **(Optional) Short address format**. Short address format for users who don't need viewkey. +- **CRC-12 mnemonic seed validation** / **Non-latin characters support** / **Varios critical bugfixes** + +### Infrastructure +- **[Ryo Wallet Atom](https://ryo-currency.com/atom)**. Modern, intuitive and rich with feature GUI wallet. Available for Windows, Linux and MacOSX. +- **[Quasar Web wallet](https://ryowebwallet.com)**. Ultra-fast WEB based wallet that shares same design with Atom wallet. +- **[Solo mining in GUI wallet](https://solo-pool.ryoblocks.com/getting-started)**. Built-in pool software with workers support, statistics and charts display. +- **[Woo commerce plugin](https://github.com/ryo-currency/ryo-payments-woocommerce-gateway)**. Plug-in for web developers, to implement accepting Ryo on website. +- **[Ryo Business room](https://ryo-currency.com/ryo-business-room)**. Business community of people fostering ecosystem development. + +GUI wallet | Web wallet | Cli wallet | Mobile | Hardware +--- | --- | --- | --- | --- +[v. 1.4.0](https://github.com/ryo-currency/ryo-wallet/releases/latest) | [Ryowebwallet](https://www.ryowebwallet.com/wallet-select) | [v. 0.4.1.0](https://github.com/ryo-currency/ryo-currency/releases/latest) | Developing | Planned + +## Research and contributing +With privacy and security as the core foundation of Ryo, we invest time and effort into security research as well as investigate and analyze issues with the Cryptonote protocol in order to bring true default anonymity for users. +- [Hiding your IP while using Ryo or other Cryptonotes](https://www.reddit.com/r/ryocurrency/comments/a4mppi/hiding_your_ip_while_using_ryo_or_other/) +- [Tracing Cryptonote ring signatures using external metadata](https://medium.com/@crypto_ryo/tracing-cryptonote-ring-signatures-using-external-metadata-8e4866810006). +- [How buying pot with Monero will get you busted — Knacc attack on Cryptonote coins](https://medium.com/@crypto_ryo/how-buying-pot-with-monero-will-get-you-busted-knacc-attack-on-cryptonote-coins-b157cd97e82f). +- [On-chain tracking of Monero and other Cryptonotes](https://medium.com/@crypto_ryo/on-chain-tracking-of-monero-and-other-cryptonotes-e0afc6752527). +You can find all write-ups in our [Ryo library](https://ryo-currency.com/library/) on the website. + +Although Ryo Currency code in main repository is source available until February 2020, we have contributed back bug fixes and features to Monero project: +- [Add Unicode input line](https://github.com/monero-project/monero/pull/4390). +- [Fix for a wallet caching bug](https://github.com/monero-project/monero/pull/4247). +Loki Project decided to use own version of wallet, based on Ryo Wallet Atom [(libre repository)](https://github.com/ryo-currency/ryo-wallet-libre) as official GUI wallet. Triton Project uses GUI wallet that is based on Ryo Wallet Atom too. + ## Coin Supply & Emission - -- **Total supply**: **80,188,888** coins in 20 years, then **263,000** coins will be emitted yearly to account for inflation. +- **Total supply**: **88,188,888** coins in 20 years, then **263,000** coins will be emitted yearly to account for inflation. - More than **80 million coins are available** for community mining. -- 8,790,000 Ryo coins were burned to get rid of the original Sumokoin premine. Additionally, 100,000 coins were premined and instantly unlocked to Sumokoin devs in 2017. +- 8,790,000 Ryo coins were burned to get rid of the original Sumokoin premine. (You can check [burned premine keyimages](https://github.com/ryo-currency/ryo-currency/tree/master/utils/burned_premine_keyimages)). Additionally, 100,000 coins were premined and instantly unlocked to Sumokoin devs in 2017. The pre-mined coins have been [frozen/burned](https://github.com/ryo-currency/ryo-currency/blob/917dbb993178bb8a2ea571f214b15adcbb7c708f/src/blockchain_db/blockchain_db.cpp#L364) as announced on [reddit](https://www.reddit.com/r/ryocurrency/comments/8nb8eq/direction_for_ryo/). This can be verified using [those](/doc/verify_premine_burn_instructions.md) instructions. -The pre-mined coins have been frozen/burned in commit [c3a3cb6](https://github.com/ryo-currency/ryo-emergency/commit/c3a3cb620488e88be7c52e017072261a3063b872)/ [blockchain_db/blockchain_db.cpp#L250-L258](https://github.com/ryo-currency/ryo-emergency/blob/c3a3cb620488e88be7c52e017072261a3063b872/src/blockchain_db/blockchain_db.cpp#L250-L258) as announced on [reddit](https://www.reddit.com/r/ryocurrency/comments/8nb8eq/direction_for_ryo/). +- After 2 rounds of community debates [(pt1](https://www.reddit.com/r/ryocurrency/comments/8xsyqo/community_debate_lets_talk_about_the_development/e26i1vw/) / [pt2)](https://github.com/ryo-currency/ryo-writeups/blob/master/dev-fund.md) **8,000,000** Ryo coins were introduced as development fund which is located in 2/3 multisig wallet and emitted on weekly basis next 6 years. In an effort to provide transparency to the community on how the development fund is allocated, Ryo dev team built the following [dev-fund explorer page](https://ryo-currency.com/dev-fund/). - **Coin symbol**: **RYO** +- **Hash algorithm**: CryptoNight-GPU (ASIC/FPGA/Botnet resistant Proof-Of-Work) +- **Total supply**: **88,188,888** coins in 20 years (including 8M dev. fund). Then 263,000 coins each year for inflation. +- **Block time**: **240 seconds** (difficulty is adjusted every block) - **Coin Units**: + 1 nanoRyo  = 0.000000001 **RYO** (10-9-_the smallest coin unit_) + 1 microRyo = 0.000001 **RYO** (10-6) + 1 milliRyo = 0.001 **RYO** (10-3) -- **Hash algorithm**: CryptoNight Heavy (Proof-Of-Work) -- **Emission scheme**: Ryo's block reward changes _every 6-months_ according to the following "Camel" distribution*. Our emission scheme is inspired by real-world mining production comparable to crude oil, coal and gas which is often slow at first, accelerated in the next few years before declining and becoming depleted. However, the emission path of Ryo is generally not that far apart from Bitcoin. - -![](https://ryo-currency.com/img/png/dark-block-reward-by-year.png) - -![](https://ryo-currency.com/img/png/dark-block-reward-by-month.png) - -![](https://ryo-currency.com/img/png/dark-emission-speed.png) - -\* The emulated algorithm of Ryo block-reward emission can be found in Python and C++ scripts at [scripts](scripts) directory. - -## I have Sumokoin, how can i claim my Ryo? -- You can claim your Ryo, if you had Sumokoin before they forked at block #137500. Ryo Currency as a chain fork kept all the transactions -and thus coins you had in your wallet- up and until Sumokoin forked at block #137500. To further secure your Ryo, we're going to tie the coins to a block after the fork. -- First, install the latest Ryo wallet. Run it and generate a new wallet. Write down the seeds. Copy the MAIN ADDRESS under the RECEIVE tab. Then from the Ryo gui, click SETTINGS » NEW WALLET and restore your Ryo from the same seeds used for your old Sumokoin wallet in the Ryo GUI. -- Send all your coins to the new Ryo MAIN ADDRESS you copied before. -After this, you can safely transact Sumokoin, it's important to first move your Ryo, before you move your Sumokoin. -- If you are comfortable using the CLI, you can just SWEEP ALL Ryo to yourself instead of all the above. - -## About this Project - -This is the core implementation of Ryo. It is open source and completely free to use without restrictions, except for those specified in the license agreement below. There are no restrictions on anyone creating an alternative implementation of Ryo that uses the protocol and network in a compatible manner. - -## Precompiled binaries - -Along with each release you can find our [precompiled binaries](https://github.com/ryo-currency/ryo-currency/releases). -To verify that the downloaded binaries are created by one of our developer please verify the checksums. -The authenticity of the checksums can by verified with the [PGP-key's](docs/pgp_keys.md). - -## Compiling Ryo from source - -### Dependencies - -The following table summarizes the tools and libraries required to build. A -few of the libraries are also included in this repository (marked as -"Vendored"). By default, the build uses the library installed on the system, -and ignores the vendored sources. However, if no library is found installed on -the system, then the vendored source will be built and used. The vendored -sources are also used for statically-linked builds because distribution -packages often include only shared library binaries (`.so`) but not static -library archives (`.a`). - -| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Fedora | Optional | Purpose | -| ------------ | ------------- | -------- | ------------------ | ------------ | ----------------- | -------- | -------------- | -| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | `gcc` | NO | | -| CMake | 3.0.0 | NO | `cmake` | `cmake` | `cmake` | NO | | -| pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | | -| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | NO | C++ libraries | -| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum | -| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `cppzmq-devel` | NO | ZeroMQ library | -| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver | -| libsodium | ? | NO | `libsodium-dev` | ? | `libsodium-devel` | NO | libsodium | -| libminiupnpc | 2.0 | YES | `libminiupnpc-dev` | `miniupnpc` | `miniupnpc-devel` | YES | NAT punching | -| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces | -| liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind | -| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | YES | Input editing | -| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit | -| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing | -| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite | -| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | -| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | - - -[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must -build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ``` - -### Cloning the repository - -Clone recursively to pull-in needed submodule(s): - -`$ git clone https://github.com/ryo-currency/ryo-currency.git` - -If you already have a repo cloned, initialize and update: - -`$ cd ryo-currency` - -### Build instructions - -Ryo uses the CMake build system and a top-level [Makefile](Makefile) that -invokes cmake commands as needed. - -#### On Linux and OS X - -* Install the dependencies -* Change to the root of the source code directory, change to the most recent release branch, and build: - - cd ryo-currency - git checkout tags/0.2.0 - make - - *Optional*: If your machine has several cores and enough memory, enable - parallel build by running `make -j` instead of `make`. For - this to be worthwhile, the machine should have one core and about 2GB of RAM - available per thread. - - *Note*: If cmake can not find zmq.hpp file on OS X, installing `zmq.hpp` from - https://github.com/zeromq/cppzmq to `/usr/local/include` should fix that error. - - *Note*: The instructions above will compile the most stable release of the - Ryo software. If you would like to use and test the most recent software, - use ```git checkout master```. The master branch may contain updates that are - both unstable and incompatible with release software, though testing is always - encouraged. - -* The resulting executables can be found in `build/release/bin` - -* Add `PATH="$PATH:$HOME/ryo/build/release/bin"` to `.profile` - -* Run Ryo with `ryod --detach` - -* **Optional**: build and run the test suite to verify the binaries: - - make release-test - - *NOTE*: `core_tests` test may take a few hours to complete. - -* **Optional**: to build binaries suitable for debugging: - - make debug - -* **Optional**: to build statically-linked binaries: - - make release-static - -Dependencies need to be built with -fPIC. Static libraries usually aren't, so you may have to build them yourself with -fPIC. Refer to their documentation for how to build them. - -* **Optional**: build documentation in `doc/html` (omit `HAVE_DOT=YES` if `graphviz` is not installed): - - HAVE_DOT=YES doxygen Doxyfile - -#### On the Raspberry Pi - -Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (2017-09-07 or later) from https://www.raspberrypi.org/downloads/raspbian/. If you are using Raspian Jessie, [please see note in the following section](#note-for-raspbian-jessie-users). - -* `apt-get update && apt-get upgrade` to install all of the latest software - -* Install the dependencies for Ryo from the 'Debian' column in the table above. - -* Enable zram: -``` - sudo zramctl --find --size=1024M # Note the device name - sudo mkswap - sudo swapon -``` -* Clone ryo and checkout most recent release version: -``` - git clone https://github.com/ryo-currency/ryo-currency.git - cd ryo-currency - git checkout tags/0.2.0 -``` -* Build: -``` - make release -``` -* Wait 4-6 hours - -* The resulting executables can be found in `build/release/bin` - -* Add `PATH="$PATH:$HOME/ryo/build/release/bin"` to `.profile` - -* Run Ryo with `ryod --detach` - -* You may wish to reduce the size of the swap file after the build has finished, and delete the boost directory from your home directory - -#### *Note for Raspbian Jessie users:* - -If you are using the older Raspbian Jessie image, compiling Ryo is a bit more complicated. The version of Boost available in the Debian Jessie repositories is too old to use with Ryo, and thus you must compile a newer version yourself. The following explains the extra steps, and has been tested on a Raspberry Pi 2 with a clean install of minimal Raspbian Jessie. - -* As before, `apt-get update && apt-get upgrade` to install all of the latest software, and enable zram - -``` - sudo zramctl --find --size=1024M # Note the device name - sudo mkswap - sudo swapon -``` - -* Then, install the dependencies for Ryo except `libunwind` and `libboost-all-dev` - -* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*` to remove a previous version if you're not using a clean install): -``` - cd - wget https://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_64_0.tar.bz2 - tar xvfo boost_1_64_0.tar.bz2 - cd boost_1_64_0 - ./bootstrap.sh - sudo ./b2 -``` -* Wait ~8 hours -``` - sudo ./bjam install -``` -* Wait ~4 hours - -* From here, follow the [general Raspberry Pi instructions](#on-the-raspberry-pi) from the "Clone ryo and checkout most recent release version" step. - -#### On Windows: - -Binaries for Windows are built on Windows using the MinGW toolchain within -[MSYS2 environment](http://msys2.github.io). The MSYS2 environment emulates a -POSIX system. The toolchain runs within the environment and *cross-compiles* -binaries that can run outside of the environment as a regular Windows -application. - -**Preparing the Build Environment** - -* Download and install the [MSYS2 installer](http://msys2.github.io), either the 64-bit or the 32-bit package, depending on your system. -* Open the MSYS shell via the `MSYS2 Shell` shortcut -* Update packages using pacman: - - pacman -Syuu - -* Exit the MSYS shell using Alt+F4 -* Edit the properties for the `MSYS2 Shell` shortcut changing "msys2_shell.bat" to "msys2_shell.cmd -mingw64" for 64-bit builds or "msys2_shell.cmd -mingw32" for 32-bit builds -* Restart MSYS shell via modified shortcut and update packages again using pacman: - - pacman -Syuu - - -* Install dependencies: - - To build for 64-bit Windows: - - pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium - - To build for 32-bit Windows: - - pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium - -* Open the MingW shell via `MinGW-w64-Win64 Shell` shortcut on 64-bit Windows - or `MinGW-w64-Win64 Shell` shortcut on 32-bit Windows. Note that if you are - running 64-bit Windows, you will have both 64-bit and 32-bit MinGW shells. - -**Cloning** - -* To git clone, run: - - git clone https://github.com/ryo-currency/ryo-currency.git - -**Building** - -* Change to the cloned directory, run: - - cd ryo-currency - -* If you would like a specific [version/tag](https://github.com/ryo-currency/ryo-currency/tags), do a git checkout for that version. eg. '0.2.0'. If you dont care about the version and just want binaries from master, skip this step: - - git checkout 0.2.0 - -* If you are on a 64-bit system, run: - - make release-static-win64 - -* If you are on a 32-bit system, run: - - make release-static-win32 +- **Emission scheme**: Ryo's block reward changes _every 6-months_ according to the following "Plateau" distribution*. Our emission scheme is inspired by real-world mining production comparable to crude oil, coal and gas which is often slow at first, accelerated in the next few years before declining and becoming depleted. However, the emission path of Ryo is generally not that far apart from Bitcoin. The emission curve for Ryo was one of the final aspects of the code we inherited from Sumokoin that was re-written and had to be even [fixed](https://medium.com/@ryo.currency/fixing-a-broken-emission-curve-818300e145a2) during May 2019 [community debates](https://github.com/ryo-currency/ryo-writeups/blob/master/emission-change-part-two.md). -* The resulting executables can be found in `build/release/bin` +![Plateau emission curve](doc/img/emission-curve.png) -* **Optional**: to build Windows binaries suitable for debugging on a 64-bit system, run: +![Plateau emission block reward](doc/img/emission-block.png) - make debug-static-win64 -* **Optional**: to build Windows binaries suitable for debugging on a 32-bit system, run: +## Community +You can join our [community](https://ryo-currency.com/social) and ask the developers about their perspectives, ask for technical support, and get the latest news - make debug-static-win32 +## Licensing details +This is the core implementation of Ryo. It is free to get and modify for your own usage, however, you [can't](https://www.reddit.com/r/ryocurrency/comments/8tc5tg/decision_our_source_code_will_be_sourceavailable) distribute modified copies from this repository. -* The resulting executables can be found in `build/debug/bin` +[Ryo-libre](https://github.com/ryo-currency/ryo-libre) is open source and completely free to use version of this repository without restrictions which is updated on yearly basis. There are no restrictions on anyone creating an alternative implementation of Ryo that uses the protocol and network in a compatible manner. [(Read more about Ryo-libre)](https://www.reddit.com/r/ryocurrency/comments/am4g0y/ann_ryolibre_open_source_repository_of_ryo) -### On FreeBSD: +Copyright (c) 2019, Ryo Currency Project -The project can be built from scratch by following instructions for Linux above. If you are running ryo in a jail you need to add the flag: `allow.sysvipc=1` to your jail configuration, otherwise lmdb will throw the error message: `Failed to open lmdb environment: Function not implemented`. - -We expect to add Ryo into the ports tree in the near future, which will aid in managing installations using ports or packages. - -### On OpenBSD: - -#### OpenBSD < 6.2 - -This has been tested on OpenBSD 5.8. - -You will need to add a few packages to your system. `pkg_add db cmake gcc gcc-libs g++ miniupnpc gtest`. - -The doxygen and graphviz packages are optional and require the xbase set. - -The Boost package has a bug that will prevent librpc.a from building correctly. In order to fix this, you will have to Build boost yourself from scratch. Follow the directions here (under "Building Boost"): -https://github.com/bitcoin/bitcoin/blob/master/doc/build-openbsd.md - -You will have to add the serialization, date_time, and regex modules to Boost when building as they are needed by Ryo. - -To build: `env CC=egcc CXX=eg++ CPP=ecpp DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/path/to/the/boost/you/built make release-static-64` - -#### OpenBSD >= 6.2 - -You will need to add a few packages to your system. `pkg_add cmake miniupnpc zeromq libiconv`. - -The doxygen and graphviz packages are optional and require the xbase set. - - -Build the Boost library using clang. This guide is derived from: https://github.com/bitcoin/bitcoin/blob/master/doc/build-openbsd.md - -We assume you are compiling with a non-root user and you have `doas` enabled. - -Note: do not use the boost package provided by OpenBSD, as we are installing boost to `/usr/local`. - -``` -# Create boost building directory -mkdir ~/boost -cd ~/boost - -# Fetch boost source -ftp -o boost_1_64_0.tar.bz2 https://netcologne.dl.sourceforge.net/project/boost/boost/1.64.0/boost_1_64_0.tar.bz2 - -# MUST output: (SHA256) boost_1_64_0.tar.bz2: OK -echo "7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332 boost_1_64_0.tar.bz2" | sha256 -c -tar xfj boost_1_64_0.tar.bz2 - -# Fetch and apply boost patches, required for OpenBSD -ftp -o boost_test_impl_execution_monitor_ipp.patch https://raw.githubusercontent.com/openbsd/ports/bee9e6df517077a7269ff0dfd57995f5c6a10379/devel/boost/patches/patch-boost_test_impl_execution_monitor_ipp -ftp -o boost_config_platform_bsd_hpp.patch https://raw.githubusercontent.com/openbsd/ports/90658284fb786f5a60dd9d6e8d14500c167bdaa0/devel/boost/patches/patch-boost_config_platform_bsd_hpp - -# MUST output: (SHA256) boost_config_platform_bsd_hpp.patch: OK -echo "1f5e59d1154f16ee1e0cc169395f30d5e7d22a5bd9f86358f738b0ccaea5e51d boost_config_platform_bsd_hpp.patch" | sha256 -c -# MUST output: (SHA256) boost_test_impl_execution_monitor_ipp.patch: OK -echo "30cec182a1437d40c3e0bd9a866ab5ddc1400a56185b7e671bb3782634ed0206 boost_test_impl_execution_monitor_ipp.patch" | sha256 -c - -cd boost_1_64_0 -patch -p0 < ../boost_test_impl_execution_monitor_ipp.patch -patch -p0 < ../boost_config_platform_bsd_hpp.patch - -# Start building boost -echo 'using clang : : c++ : "-fvisibility=hidden -fPIC" "" "ar" "strip" "ranlib" "" : ;' > user-config.jam -./bootstrap.sh --without-icu --with-libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale --with-toolset=clang -./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -sICONV_PATH=/usr/local -doas ./b2 -d0 runtime-link=shared threadapi=pthread threading=multi link=static variant=release --layout=tagged --build-type=complete --user-config=user-config.jam -sNO_BZIP2=1 -sICONV_PATH=/usr/local --prefix=/usr/local install -``` - -Build cppzmq - -Build the cppzmq bindings. - -We assume you are compiling with a non-root user and you have `doas` enabled. - -``` -# Create cppzmq building directory -mkdir ~/cppzmq -cd ~/cppzmq - -# Fetch cppzmq source -ftp -o cppzmq-4.2.3.tar.gz https://github.com/zeromq/cppzmq/archive/v4.2.3.tar.gz - -# MUST output: (SHA256) cppzmq-4.2.3.tar.gz: OK -echo "3e6b57bf49115f4ae893b1ff7848ead7267013087dc7be1ab27636a97144d373 cppzmq-4.2.3.tar.gz" | sha256 -c -tar xfz cppzmq-4.2.3.tar.gz - -# Start building cppzmq -cd cppzmq-4.2.3 -mkdir build -cd build -cmake .. -doas make install -``` - -Build Ryo: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local make release-static` - -### On Solaris: - -The default Solaris linker can't be used, you have to install GNU ld, then run cmake manually with the path to your copy of GNU ld: - - mkdir -p build/release - cd build/release - cmake -DCMAKE_LINKER=/path/to/ld -D CMAKE_BUILD_TYPE=Release ../.. - cd ../.. - -Then you can run make as usual. - -### On Linux for Android (using docker): - - # Build image (select android64.Dockerfile for aarch64) - cd utils/build_scripts/ && docker build -f android32.Dockerfile -t ryo-android . - # Create container - docker create -it --name ryo-android ryo-android bash - # Get binaries - docker cp ryo-android:/opt/android/ryo/build/release/bin . - -### Building portable statically linked binaries - -By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets: - -* ```make release-static-linux-x86_64``` builds binaries on Linux on x86_64 portable across POSIX systems on x86_64 processors -* ```make release-static-linux-i686``` builds binaries on Linux on x86_64 or i686 portable across POSIX systems on i686 processors -* ```make release-static-linux-armv8``` builds binaries on Linux portable across POSIX systems on armv8 processors -* ```make release-static-linux-armv7``` builds binaries on Linux portable across POSIX systems on armv7 processors -* ```make release-static-linux-armv6``` builds binaries on Linux portable across POSIX systems on armv6 processors -* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems -* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems - -## Installing Ryo from a package - -**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.** - -Packages are available for - -* Docker - - # Build using all available cores - `docker build -t ryo .` - - # or build using a specific number of cores (reduce RAM requirement) - `docker build --build-arg NPROC=1 -t ryo .` - - # either run in foreground - `docker run -it -v /ryo/chain:/root/.ryo -v /ryo/wallet:/wallet -p 18080:18080 ryo` - - # or in background - `docker run -it -d -v /ryo/chain:/root/.ryo -v /ryo/wallet:/wallet -p 18080:18080 ryo` - -Packaging for your favorite distribution would be a welcome contribution! - -## Running ryod - -The build places the binary in `bin/` sub-directory within the build directory -from which cmake was invoked (repository root by default). To run in -foreground: - - ./bin/ryod - -To list all available options, run `./bin/ryod --help`. Options can be -specified either on the command line or in a configuration file passed by the -`--config-file` argument. To specify an option in the configuration file, add -a line with the syntax `argumentname=value`, where `argumentname` is the name -of the argument without the leading dashes, for example `log-level=1`. - -To run in background: - - ./bin/ryod --log-file ryod.log --detach - -To run as a systemd service, copy -[ryod.service](utils/systemd/ryod.service) to `/etc/systemd/system/` and -[ryod.conf](utils/conf/ryod.conf) to `/etc/`. The [example -service](utils/systemd/ryod.service) assumes that the user `ryo` exists -and its home is the data directory specified in the [example -config](utils/conf/ryod.conf). - -If you're on Mac, you may need to add the `--max-concurrency 1` option to -ryo-wallet-cli, and possibly ryod, if you get crashes refreshing. - -## Using Tor - -While Ryo isn't made to integrate with Tor, it can be used wrapped with torsocks, by -setting the following configuration parameters and environment variables: - -* `--p2p-bind-ip 127.0.0.1` on the command line or `p2p-bind-ip=127.0.0.1` in - ryod.conf to disable listening for connections on external interfaces. -* `--no-igd` on the command line or `no-igd=1` in ryod.conf to disable IGD - (UPnP port forwarding negotiation), which is pointless with Tor. -* `DNS_PUBLIC=tcp` or `DNS_PUBLIC=tcp://x.x.x.x` where x.x.x.x is the IP of the - desired DNS server, for DNS requests to go over TCP, so that they are routed - through Tor. When IP is not specified, ryod uses the default list of - servers defined in [src/common/dns_utils.cpp](src/common/dns_utils.cpp). -* `TORSOCKS_ALLOW_INBOUND=1` to tell torsocks to allow ryod to bind to interfaces - to accept connections from the wallet. On some Linux systems, torsocks - allows binding to localhost by default, so setting this variable is only - necessary to allow binding to local LAN/VPN interfaces to allow wallets to - connect from remote hosts. On other systems, it may be needed for local wallets - as well. -* Do NOT pass `--detach` when running through torsocks with systemd, (see - [utils/systemd/ryod.service](utils/systemd/ryod.service) for details). -* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050), - then use `--untrusted-daemon` unless it is your own hidden service. - -Example command line to start ryod through Tor: - - DNS_PUBLIC=tcp torsocks ryod --p2p-bind-ip 127.0.0.1 --no-igd - -### Using Tor on Tails - -TAILS ships with a very restrictive set of firewall rules. Therefore, you need -to add a rule to allow this connection too, in addition to telling torsocks to -allow inbound connections. Full example: - - sudo iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 18081 -j ACCEPT - DNS_PUBLIC=tcp torsocks ./ryod --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip 127.0.0.1 \ - --data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain - -## Using readline - -While `ryod` and `ryo-wallet-cli` do not use readline directly, most of the functionality can be obtained by running them via `rlwrap`. This allows command recall, edit capabilities, etc. It does not give autocompletion without an extra completion file, however. To use rlwrap, simply prepend `rlwrap` to the command line, eg: - -`rlwrap bin/ryo-wallet-cli --wallet-file /path/to/wallet` - -Note: rlwrap will save things like your seed and private keys, if you supply them on prompt. You may want to not use rlwrap when you use simplewallet to restore from seed, etc. - -# Debugging - -This section contains general instructions for debugging failed installs or problems encountered with Ryo. First ensure you are running the latest version built from the github repo. - -### Obtaining stack traces and core dumps on Unix systems - -We generally use the tool `gdb` (GNU debugger) to provide stack trace functionality, and `ulimit` to provide core dumps in builds which crash or segfault. - -* To use gdb in order to obtain a stack trace for a build that has stalled: - -Run the build. - -Once it stalls, enter the following command: - -``` -gdb /path/to/ryod `pidof ryod` -``` - -Type `thread apply all bt` within gdb in order to obtain the stack trace - -* If however the core dumps or segfaults: - -Enter `ulimit -c unlimited` on the command line to enable unlimited filesizes for core dumps - -Enter `echo core | sudo tee /proc/sys/kernel/core_pattern` to stop cores from being hijacked by other tools - -Run the build. - -When it terminates with an output along the lines of "Segmentation fault (core dumped)", there should be a core dump file in the same directory as ryod. It may be named just `core`, or `core.xxxx` with numbers appended. - -You can now analyse this core dump with `gdb` as follows: - -`gdb /path/to/ryod /path/to/dumpfile` - -Print the stack trace with `bt` - -* To run ryo within gdb: - -Type `gdb /path/to/ryod` - -Pass command-line options with `--args` followed by the relevant arguments - -Type `run` to run ryod - -### Analysing memory corruption - -We use the tool `valgrind` for this. - -Run with `valgrind /path/to/ryod`. It will be slow. - -# LMDB - -There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command: - -`cd ~/ryo/external/db_drivers/liblmdb && make` - -The output of `mdb_stat -ea ` will indicate inconsistencies in the blocks, block_heights and block_info table. +Copyright (c) 2014-2017, The Monero Project -The output of `mdb_dump -s blocks ` and `mdb_dump -s block_info ` is useful for indicating whether blocks and block_info contain the same keys. +Copyright (c) 2012-2013, The Cryptonote developers -These records are dumped as hex data, where the first line is the key and the second line is the data. +Copyright (c) 2017, Sumokoin.org diff --git a/contrib/epee/demo/demo_http_server/stdafx.h b/contrib/epee/demo/demo_http_server/stdafx.h index 6ee6087a..ef268f22 100644 --- a/contrib/epee/demo/demo_http_server/stdafx.h +++ b/contrib/epee/demo/demo_http_server/stdafx.h @@ -32,4 +32,5 @@ #define BOOST_FILESYSTEM_VERSION 3 #define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" +#include "common/gulps.hpp" + diff --git a/contrib/epee/demo/demo_levin_server/stdafx.h b/contrib/epee/demo/demo_levin_server/stdafx.h index 077d9007..1a8bdb53 100644 --- a/contrib/epee/demo/demo_levin_server/stdafx.h +++ b/contrib/epee/demo/demo_levin_server/stdafx.h @@ -33,4 +33,5 @@ #define BOOST_FILESYSTEM_VERSION 3 #define ENABLE_RELEASE_LOGGING #include "log_opt_defs.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" + diff --git a/contrib/epee/demo/iface/transport_defs.h b/contrib/epee/demo/iface/transport_defs.h index b1e3a078..7460c2a3 100644 --- a/contrib/epee/demo/iface/transport_defs.h +++ b/contrib/epee/demo/iface/transport_defs.h @@ -10,7 +10,7 @@ struct some_test_subdata { std::string m_str; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(some_test_subdata) KV_SERIALIZE(m_str) END_KV_SERIALIZE_MAP() }; @@ -44,7 +44,7 @@ struct some_test_data epee::serialization::storage_entry m_storage_entry_int; epee::serialization::storage_entry m_storage_entry_string; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(some_test_data) KV_SERIALIZE(m_str) KV_SERIALIZE(m_uint64) KV_SERIALIZE(m_uint32) @@ -86,7 +86,7 @@ struct COMMAND_EXAMPLE_1 std::string example_string_data; some_test_data sub; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(example_string_data) KV_SERIALIZE(sub) END_KV_SERIALIZE_MAP() @@ -97,7 +97,7 @@ struct COMMAND_EXAMPLE_1 bool m_success; std::list subs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(m_success) KV_SERIALIZE(subs) END_KV_SERIALIZE_MAP() @@ -112,7 +112,7 @@ struct COMMAND_EXAMPLE_2 { std::string example_string_data2; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(example_string_data2) END_KV_SERIALIZE_MAP() }; @@ -121,7 +121,7 @@ struct COMMAND_EXAMPLE_2 { bool m_success; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(m_success) END_KV_SERIALIZE_MAP() }; diff --git a/contrib/epee/include/ado_db_helper.h b/contrib/epee/include/ado_db_helper.h index cc23bf19..ca047215 100644 --- a/contrib/epee/include/ado_db_helper.h +++ b/contrib/epee/include/ado_db_helper.h @@ -34,6 +34,8 @@ #include #include +#include "common/gulps.hpp" + #define BEGIN_TRY_SECTION() \ try \ { @@ -44,7 +46,8 @@ } \ catch(const std::exception &ex) \ { \ - LOG_PRINT_J("DB_ERROR: " << ex.what(), LOG_LEVEL_0); \ + GULPS_CAT_MAJOR("epee_ado_db_help"); \ + GULPSF_ERROR("DB_ERROR: {}", ex.what(); \ return ret_val; \ } \ catch(const _com_error &comm_err) \ @@ -53,13 +56,15 @@ std::string descr = string_encoding::convert_to_ansii(pstr ? pstr : TEXT("")); \ const TCHAR *pmessage = comm_err.ErrorMessage(); \ pstr = comm_err.Source(); \ + GULPS_CAT_MAJOR("epee_ado_db_help"); \ std::string source = string_encoding::convert_to_ansii(pstr ? pstr : TEXT("")); \ - LOG_PRINT_J("COM_ERROR " << mess_where << ":\n\tDescriprion:" << descr << ", \n\t Message: " << string_encoding::convert_to_ansii(pmessage) << "\n\t Source: " << source, LOG_LEVEL_0); \ + GULPSF_ERROR("COM_ERROR {}:\n\tDescriprion:{}, \n\t Message: {}\n\t Source: {}", mess_where, descr, string_encoding::convert_to_ansii(pmessage), source); \ return ret_val; \ } \ catch(...) \ { \ - LOG_PRINT_J("..._ERROR: Unknown error.", LOG_LEVEL_0); \ + GULPS_CAT_MAJOR("epee_ado_db_help"); \ + GULPS_ERROR("..._ERROR: Unknown error."); \ return ret_val; \ } @@ -82,6 +87,7 @@ struct profile_entry class profiler_manager { + GULPS_CAT_MAJOR("epee_ado_db_help"); public: typedef std::map sqls_map; profiler_manager() {} @@ -352,7 +358,7 @@ inline bool select_helper(ADODB::_CommandPtr cmd, table &result_vector) ADODB::_RecordsetPtr precordset = cmd->Execute(NULL, NULL, NULL); if(!precordset) { - LOG_ERROR("DB_ERROR: cmd->Execute returned NULL!!!"); + GULPS_ERROR("DB_ERROR: cmd->Execute returned NULL!!!"); return false; } @@ -364,7 +370,7 @@ inline bool select_helper(ADODB::_CommandPtr cmd, table &result_vector) { if(precordset->MoveFirst()!= S_OK) { - LOG_ERROR("DB_ERROR: Filed to move first!!!"); + GULPS_ERROR("DB_ERROR: Filed to move first!!!"); return false; } } @@ -956,18 +962,18 @@ class per_thread_connection_pool if(S_OK != conn.CreateInstance(__uuidof(ADODB::Connection))) { - LOG_ERROR("Failed to Create, instance, was CoInitialize called ???!"); + GULPS_ERROR("Failed to Create, instance, was CoInitialize called ???!"); return conn; } HRESULT res = conn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); if(res != S_OK) { - LOG_ERROR("Failed to connect do DB, connection str:" << m_connection_string); + GULPSF_ERROR("Failed to connect do DB, connection str:{}", m_connection_string); return conn; } CATCH_TRY_SECTION_MESS(conn, "while creating another connection"); - LOG_PRINT("New DB Connection added for threadid=" << ::GetCurrentThreadId(), LOG_LEVEL_0); + GULPSF_PRINT("New DB Connection added for threadid={}", ::GetCurrentThreadId()); ado_db_helper::execute_helper(conn, "set enable_seqscan=false;"); return conn; } @@ -994,7 +1000,7 @@ class per_thread_connection_pool HRESULT res = rconn->Open(_bstr_t(m_connection_string.c_str()), _bstr_t(m_login.c_str()), _bstr_t(m_password.c_str()), NULL); if(res != S_OK) { - LOG_PRINT("Failed to restore connection to local AI DB", LOG_LEVEL_1); + GULPS_LOG_L1("Failed to restore connection to local AI DB"); return false; } CATCH_TRY_SECTION(false); @@ -1053,7 +1059,7 @@ bool find_or_add_t(const std::string &sql_select_statment, const std::string &sq template bool find_or_add_t_multiparametred(const std::string &sql_select_statment, const std::string &sql_insert_statment, OUT default_id_type &id, OUT bool &new_object_added, TParams params, t_conn &c) { - + GULPS_CAT_MAJOR("epee_ado_db_help"); //CHECK_CONNECTION(false); new_object_added = false; @@ -1067,8 +1073,8 @@ bool find_or_add_t_multiparametred(const std::string &sql_select_statment, const { //last time try to select res = select_helper_multiparam(c.get_db_connection(), sql_select_statment, params, result_table); - CHECK_AND_ASSERT_MES(res, false, "Failed to execute statment: " << sql_select_statment); - CHECK_AND_ASSERT_MES(result_table.size(), false, "No records returned from statment: " << sql_select_statment); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to execute statment: " , sql_select_statment); + GULPS_CHECK_AND_ASSERT_MES(result_table.size(), false, "No records returned from statment: " , sql_select_statment); } else { diff --git a/contrib/epee/include/console_handler.h b/contrib/epee/include/console_handler.h index 91b2a313..9fdb3095 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -26,7 +26,6 @@ #pragma once -#include "misc_log_ex.h" #include "string_tools.h" #include #include @@ -41,6 +40,8 @@ #include #include +#include "common/gulps.hpp" + #ifdef HAVE_READLINE #include "readline_buffer.h" #endif @@ -288,6 +289,7 @@ bool empty_commands_handler(t_server *psrv, const std::string &command) class async_console_handler { + GULPS_CAT_MAJOR("epee_csl_hand"); public: async_console_handler() { @@ -322,14 +324,12 @@ class async_console_handler color_prompt += " "; color_prompt += "\001\033[0m\002"; m_stdin_reader.get_readline_buffer().set_prompt(color_prompt); -#else - epee::set_console_color(epee::console_color_yellow, true); - std::cout << prompt; - if(' ' != prompt.back()) - std::cout << ' '; - epee::reset_console_color(); - std::cout.flush(); #endif + + if(prompt.back() != ' ') + prompt += ' '; + gulps::inst().log(gulps::message(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), + "cmd_prompt", __FILE__, __LINE__, std::move(prompt), gulps::COLOR_BOLD_YELLOW, false)); } } @@ -357,11 +357,10 @@ class async_console_handler } if(!get_line_ret) { - MERROR("Failed to read line."); + GULPS_ERROR("Failed to read line."); } string_tools::trim(command); - - LOG_PRINT_L2("Read command: " << command); + GULPS_LOG_L2("Read command: ", command); if(command.empty()) { continue; @@ -379,13 +378,13 @@ class async_console_handler #ifdef HAVE_READLINE rdln::suspend_readline pause_readline; #endif - std::cout << "unknown command: " << command << std::endl; - std::cout << usage; + GULPS_PRINT("unknown command: ", command); + GULPS_PRINT(usage); } } catch(const std::exception &ex) { - LOG_ERROR("Exception at [console_handler], what=" << ex.what()); + GULPSF_ERROR("Exception at [console_handler], what={}", ex.what()); } } if(exit_handler) @@ -484,7 +483,7 @@ class command_handler for(auto &x : m_command_handlers) { - ss << x.second.second.first << ENDL; + ss << x.second.second.first << "\n"; } return ss.str(); } diff --git a/contrib/epee/include/gzip_encoding.h b/contrib/epee/include/gzip_encoding.h index f0ab5d98..f6166283 100644 --- a/contrib/epee/include/gzip_encoding.h +++ b/contrib/epee/include/gzip_encoding.h @@ -106,7 +106,7 @@ class content_encoding_gzip : public i_sub_handler int flag = Z_SYNC_FLUSH; int ret = inflate(&m_zstream_in, flag); - CHECK_AND_ASSERT_MES(ret >= 0 || m_zstream_in.avail_out || m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " << ret); + GULPS_CHECK_AND_ASSERT_MES(ret >= 0 || m_zstream_in.avail_out || m_is_deflate_mode, false, "content_encoding_gzip::update_in() Failed to inflate. err = " , ret); if(Z_STREAM_END == ret) m_is_stream_ended = true; @@ -126,7 +126,7 @@ class content_encoding_gzip : public i_sub_handler ret = inflate(&m_zstream_in, Z_NO_FLUSH); if(ret != Z_OK) { - LOCAL_ASSERT(0); + GULPS_LOCAL_ASSERT(0); m_pre_decode.swap(piece_of_transfer); return false; } @@ -136,7 +136,7 @@ class content_encoding_gzip : public i_sub_handler ret = inflate(&m_zstream_in, Z_NO_FLUSH); if(ret != Z_OK) { - LOCAL_ASSERT(0); + GULPS_LOCAL_ASSERT(0); m_pre_decode.swap(piece_of_transfer); return false; } diff --git a/contrib/epee/include/include_base_utils.h b/contrib/epee/include/include_base_utils.h index 3484d842..1e89b0fc 100644 --- a/contrib/epee/include/include_base_utils.h +++ b/contrib/epee/include/include_base_utils.h @@ -29,4 +29,4 @@ #define BOOST_FILESYSTEM_VERSION 3 #define ENABLE_RELEASE_LOGGING -#include "misc_log_ex.h" +#include "common/gulps.hpp" diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h index efaf8b9c..27520bfe 100644 --- a/contrib/epee/include/math_helper.h +++ b/contrib/epee/include/math_helper.h @@ -26,7 +26,7 @@ #pragma once -#include +#include #include #include #include diff --git a/contrib/epee/include/misc_language.h b/contrib/epee/include/misc_language.h index 542a036c..64bbb15a 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -29,6 +29,9 @@ #include #include #include + +#include "common/gulps.hpp" + namespace epee { #define STD_TRY_BEGIN() \ @@ -39,12 +42,14 @@ namespace epee } \ catch(const std::exception &e) \ { \ - LOG_ERROR("EXCEPTION: " << where_ << ", mes: " << e.what()); \ + GULPS_CAT_MAJOR("epee_msc_lang"); \ + GULPSF_ERROR("EXCEPTION: {}, mes: {}", where_, e.what()); \ return ret_val; \ } \ catch(...) \ { \ - LOG_ERROR("EXCEPTION: " << where_); \ + GULPS_CAT_MAJOR("epee_msc_lang"); \ + GULPSF_ERROR("EXCEPTION: {}", where_); \ return ret_val; \ } diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h deleted file mode 100644 index aa7d80fe..00000000 --- a/contrib/epee/include/misc_log_ex.h +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// 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. -// * Neither the name of the Andrey N. Sabelnikov 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 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 _MISC_LOG_EX_H_ -#define _MISC_LOG_EX_H_ - -#include - -#include "easylogging++.h" - -#define RYO_DEFAULT_LOG_CATEGORY "default" -#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes - -#define MCFATAL(cat, x) CLOG(FATAL, cat) << x -#define MCERROR(cat, x) CLOG(ERROR, cat) << x -#define MCWARNING(cat, x) CLOG(WARNING, cat) << x -#define MCINFO(cat, x) CLOG(INFO, cat) << x -#define MCDEBUG(cat, x) CLOG(DEBUG, cat) << x -#define MCTRACE(cat, x) CLOG(TRACE, cat) << x -#define MCLOG(level, cat, x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::NormalLog, cat) << x -#define MCLOG_FILE(level, cat, x) ELPP_WRITE_LOG(el::base::Writer, level, el::base::DispatchAction::FileOnlyLog, cat) << x - -#define MCLOG_COLOR(level, cat, color, x) MCLOG(level, cat, "\033[1;" color "m" << x << "\033[0m") -#define MCLOG_RED(level, cat, x) MCLOG_COLOR(level, cat, "31", x) -#define MCLOG_GREEN(level, cat, x) MCLOG_COLOR(level, cat, "32", x) -#define MCLOG_YELLOW(level, cat, x) MCLOG_COLOR(level, cat, "33", x) -#define MCLOG_BLUE(level, cat, x) MCLOG_COLOR(level, cat, "34", x) -#define MCLOG_MAGENTA(level, cat, x) MCLOG_COLOR(level, cat, "35", x) -#define MCLOG_CYAN(level, cat, x) MCLOG_COLOR(level, cat, "36", x) - -#define MLOG_RED(level, x) MCLOG_RED(level, RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG_GREEN(level, x) MCLOG_GREEN(level, RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG_YELLOW(level, x) MCLOG_YELLOW(level, RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG_BLUE(level, x) MCLOG_BLUE(level, RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG_MAGENTA(level, x) MCLOG_MAGENTA(level, RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG_CYAN(level, x) MCLOG_CYAN(level, RYO_DEFAULT_LOG_CATEGORY, x) - -#define MFATAL(x) MCFATAL(RYO_DEFAULT_LOG_CATEGORY, x) -#define MERROR(x) MCERROR(RYO_DEFAULT_LOG_CATEGORY, x) -#define MWARNING(x) MCWARNING(RYO_DEFAULT_LOG_CATEGORY, x) -#define MINFO(x) MCINFO(RYO_DEFAULT_LOG_CATEGORY, x) -#define MDEBUG(x) MCDEBUG(RYO_DEFAULT_LOG_CATEGORY, x) -#define MTRACE(x) MCTRACE(RYO_DEFAULT_LOG_CATEGORY, x) -#define MLOG(level, x) MCLOG(level, RYO_DEFAULT_LOG_CATEGORY, x) - -#define MGINFO(x) MCINFO("global", x) -#define MGINFO_RED(x) MCLOG_RED(el::Level::Info, "global", x) -#define MGINFO_GREEN(x) MCLOG_GREEN(el::Level::Info, "global", x) -#define MGINFO_YELLOW(x) MCLOG_YELLOW(el::Level::Info, "global", x) -#define MGINFO_BLUE(x) MCLOG_BLUE(el::Level::Info, "global", x) -#define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global", x) -#define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global", x) - -#define LOG_ERROR(x) MERROR(x) -#define LOG_PRINT_L0(x) MWARNING(x) -#define LOG_PRINT_L1(x) MINFO(x) -#define LOG_PRINT_L2(x) MDEBUG(x) -#define LOG_PRINT_L3(x) MTRACE(x) -#define LOG_PRINT_L4(x) MTRACE(x) - -#define _dbg3(x) MTRACE(x) -#define _dbg2(x) MDEBUG(x) -#define _dbg1(x) MDEBUG(x) -#define _info(x) MINFO(x) -#define _note(x) MDEBUG(x) -#define _fact(x) MDEBUG(x) -#define _mark(x) MDEBUG(x) -#define _warn(x) MWARNING(x) -#define _erro(x) MERROR(x) - -#define MLOG_SET_THREAD_NAME(x) el::Helpers::setThreadName(x) - -#ifndef LOCAL_ASSERT -#include -#if(defined _MSC_VER) -#define LOCAL_ASSERT(expr) \ - { \ - if(epee::debug::get_set_enable_assert()) \ - { \ - _ASSERTE(expr); \ - } \ - } -#else -#define LOCAL_ASSERT(expr) -#endif - -#endif - -std::string mlog_get_default_log_path(const char *default_filename); -void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE); -void mlog_set_categories(const char *categories); -std::string mlog_get_categories(); -void mlog_set_log_level(int level); -void mlog_set_log(const char *log); - -namespace epee -{ -namespace debug -{ -inline bool get_set_enable_assert(bool set = false, bool v = false) -{ - static bool e = true; - if(set) - e = v; - return e; -} -} - -#define ENDL std::endl - -#define TRY_ENTRY() \ - try \ - { -#define CATCH_ENTRY(location, return_val) \ - } \ - catch(const std::exception &ex) \ - { \ - (void)(ex); \ - LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \ - return return_val; \ - } \ - catch(...) \ - { \ - LOG_ERROR("Exception at [" << location << "], generic exception \"...\""); \ - return return_val; \ - } - -#define CATCH_ENTRY_L0(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L1(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L2(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L3(lacation, return_val) CATCH_ENTRY(lacation, return_val) -#define CATCH_ENTRY_L4(lacation, return_val) CATCH_ENTRY(lacation, return_val) - -#define ASSERT_MES_AND_THROW(message) \ - { \ - LOG_ERROR(message); \ - std::stringstream ss; \ - ss << message; \ - throw std::runtime_error(ss.str()); \ - } -#define CHECK_AND_ASSERT_THROW_MES(expr, message) \ - do \ - { \ - if(!(expr)) \ - ASSERT_MES_AND_THROW(message); \ - } while(0) - -#ifndef CHECK_AND_ASSERT -#define CHECK_AND_ASSERT(expr, fail_ret_val) \ - do \ - { \ - if(!(expr)) \ - { \ - LOCAL_ASSERT(expr); \ - return fail_ret_val; \ - }; \ - } while(0) -#endif - -#ifndef CHECK_AND_ASSERT_MES -#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) \ - do \ - { \ - if(!(expr)) \ - { \ - LOG_ERROR(message); \ - return fail_ret_val; \ - }; \ - } while(0) -#endif - -#ifndef CHECK_AND_NO_ASSERT_MES_L -#define CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, l, message) \ - do \ - { \ - if(!(expr)) \ - { \ - LOG_PRINT_L##l(message); /*LOCAL_ASSERT(expr);*/ \ - return fail_ret_val; \ - }; \ - } while(0) -#endif - -#ifndef CHECK_AND_NO_ASSERT_MES -#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 0, message) -#endif - -#ifndef CHECK_AND_NO_ASSERT_MES_L1 -#define CHECK_AND_NO_ASSERT_MES_L1(expr, fail_ret_val, message) CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 1, message) -#endif - -#ifndef CHECK_AND_ASSERT_MES_NO_RET -#define CHECK_AND_ASSERT_MES_NO_RET(expr, message) \ - do \ - { \ - if(!(expr)) \ - { \ - LOG_ERROR(message); \ - return; \ - }; \ - } while(0) -#endif - -#ifndef CHECK_AND_ASSERT_MES2 -#define CHECK_AND_ASSERT_MES2(expr, message) \ - do \ - { \ - if(!(expr)) \ - { \ - LOG_ERROR(message); \ - }; \ - } while(0) -#endif - -enum console_colors -{ - console_color_default, - console_color_white, - console_color_red, - console_color_green, - console_color_blue, - console_color_cyan, - console_color_magenta, - console_color_yellow -}; - -bool is_stdout_a_tty(); -void set_console_color(int color, bool bright); -void reset_console_color(); -} -#endif //_MISC_LOG_EX_H_ diff --git a/contrib/epee/include/misc_os_dependent.h b/contrib/epee/include/misc_os_dependent.h index 4c50bcc0..1037ba92 100644 --- a/contrib/epee/include/misc_os_dependent.h +++ b/contrib/epee/include/misc_os_dependent.h @@ -23,6 +23,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // + #ifdef _WIN32 #include #endif @@ -48,6 +49,8 @@ #include #include +#include "common/gulps.hpp" + #pragma once namespace epee { @@ -92,7 +95,8 @@ inline uint64_t get_tick_count() inline int call_sys_cmd(const std::string &cmd) { - std::cout << "# " << cmd << std::endl; + GULPS_CAT_MAJOR("epee_msc_os_dep"); + GULPS_PRINT("# {}", cmd); FILE *fp; //char tstCommand[] ="ls *"; @@ -103,7 +107,7 @@ inline int call_sys_cmd(const std::string &cmd) fp = popen(cmd.c_str(), "r"); #endif while(fgets(path, 1000, fp) != NULL) - std::cout << path; + GULPS_PRINT(path); #if !defined(__GNUC__) _pclose(fp); diff --git a/contrib/epee/include/net/abstract_tcp_server.h b/contrib/epee/include/net/abstract_tcp_server.h index 9a42dbdd..26c3f04e 100644 --- a/contrib/epee/include/net/abstract_tcp_server.h +++ b/contrib/epee/include/net/abstract_tcp_server.h @@ -36,8 +36,9 @@ #pragma comment(lib, "Ws2_32.lib") -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -56,7 +57,8 @@ class soket_sender : public i_service_endpoint if(cb != send(m_sock, (char *)ptr, (int)cb, 0)) { int sock_err = WSAGetLastError(); - LOG_ERROR("soket_sender: Failed to send " << cb << " bytes, Error=" << sock_err); + GULPS_CAT_MAJOR("epee_tcp_srv"); + GULPSF_LOG_ERROR("soket_sender: Failed to send {} bytes, Error={}", cb , sock_err); return false; } return true; @@ -71,6 +73,7 @@ class soket_sender : public i_service_endpoint template class abstract_tcp_server { + GULPS_CAT_MAJOR("epee_tcp_srv"); public: abstract_tcp_server(); @@ -121,7 +124,7 @@ unsigned __stdcall abstract_tcp_server::ConnectionHandlerProc(void *lp ::CoInitialize(NULL); - LOG_PRINT("Handler thread STARTED with socket=" << pthread_context->m_socket, LOG_LEVEL_2); + GULPSF_LOG_L2("Handler thread STARTED with socket={}", pthread_context->m_socket); int res = 0; soket_sender sndr(pthread_context->m_socket); @@ -133,7 +136,7 @@ unsigned __stdcall abstract_tcp_server::ConnectionHandlerProc(void *lp std::string ansver; while((res = recv(pthread_context->m_socket, (char *)buff, 1000, 0)) > 0) { - LOG_PRINT("Data in, " << res << " bytes", LOG_LEVEL_3); + GULPSF_LOG_L3("Data in, {} bytes", res ); if(!srv.handle_recv(buff, res)) break; } @@ -141,7 +144,7 @@ unsigned __stdcall abstract_tcp_server::ConnectionHandlerProc(void *lp closesocket(pthread_context->m_socket); abstract_tcp_server *powner = pthread_context->powner; - LOG_PRINT("Handler thread with socket=" << pthread_context->m_socket << " STOPPED", LOG_LEVEL_2); + GULPSF_LOG_L2("Handler thread with socket={} STOPPED", pthread_context->m_socket ); powner->m_connections_lock.lock(); ::CloseHandle(pthread_context->m_htread); pthread_context->powner->m_connections.erase(pthread_context->m_self_it); @@ -167,7 +170,7 @@ bool abstract_tcp_server::init_server(int port_no) int err = ::WSAStartup(MAKEWORD(2, 2), &wsad); if(err != 0 || LOBYTE(wsad.wVersion) != 2 || HIBYTE(wsad.wVersion) != 2) { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Could not find a usable WinSock DLL, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -177,7 +180,7 @@ bool abstract_tcp_server::init_server(int port_no) if(INVALID_SOCKET == m_listen_socket) { err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to create socket, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -193,7 +196,7 @@ bool abstract_tcp_server::init_server(int port_no) if(SOCKET_ERROR == err) { err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\"", LOG_LEVEL_2); + GULPSF_LOG_L2("Failed to Bind, err = {} \"{}\"", err, socket_errors::get_socket_error_text(err)); deinit_server(); return false; } @@ -217,7 +220,7 @@ bool abstract_tcp_server::deinit_server() if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to closesocket(), err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); } m_listen_socket = INVALID_SOCKET; } @@ -226,7 +229,7 @@ bool abstract_tcp_server::deinit_server() if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to WSACleanup(), err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); } m_initialized = false; @@ -247,11 +250,11 @@ bool abstract_tcp_server::run_server() if(SOCKET_ERROR == err) { err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to listen, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } - LOG_PRINT("Listening port " << m_port << "....", LOG_LEVEL_2); + GULPSF_LOG_L2("Listening port {}....", m_port ); while(!m_stop_server) { @@ -266,7 +269,7 @@ bool abstract_tcp_server::run_server() if(!select_res) continue; SOCKET new_sock = WSAAccept(m_listen_socket, (sockaddr *)&adr_from, &adr_len, NULL, NULL); - LOG_PRINT("Accepted connection on socket=" << new_sock, LOG_LEVEL_2); + GULPSF_LOG_L2("Accepted connection on socket={}", new_sock); invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); } @@ -282,7 +285,7 @@ bool abstract_tcp_server::run_server() ::Sleep(ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL); wait_count++; } - LOG_PRINT("abstract_tcp_server exit with wait count=" << wait_count * ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL << "(max=" << ABSTR_TCP_SRV_WAIT_COUNT_MAX << ")", LOG_LEVEL_0); + GULPSF_PRINT("abstract_tcp_server exit with wait count={}(max={})", wait_count * ABSTR_TCP_SRV_WAIT_COUNT_INTERVAL , ABSTR_TCP_SRV_WAIT_COUNT_MAX ); return true; } diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 5e3906b5..8ca2aa59 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -54,8 +54,7 @@ #include #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" + #define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 1000 @@ -83,6 +82,7 @@ class connection public i_service_endpoint, public connection_basic { + GULPS_CAT_MAJOR("epee_tcp_srv"); public: typedef typename t_protocol_handler::connection_context t_connection_context; /// Construct a connection with the given io_service. diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index b71607ec..257c1f75 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -30,6 +30,7 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // + //#include "net_utils_base.h" #include "misc_language.h" #include "net/local_ip.h" @@ -51,8 +52,9 @@ #include "../../../../src/cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal() -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + #define DEFAULT_TIMEOUT_MS_LOCAL boost::posix_time::milliseconds(120000) // 2 minutes #define DEFAULT_TIMEOUT_MS_REMOTE boost::posix_time::milliseconds(10000) // 10 seconds @@ -83,7 +85,7 @@ connection::connection(boost::asio::io_service &io_service, m_timer(io_service), m_local(false) { - MDEBUG("test, connection constructor set m_connection_type=" << m_connection_type); + GULPSF_LOG_L1("test, connection constructor set m_connection_type={}", m_connection_type); } PRAGMA_WARNING_DISABLE_VS(4355) //--------------------------------------------------------------------------------- @@ -92,11 +94,11 @@ connection::~connection() noexcept(false) { if(!m_was_shutdown) { - _dbg3("[sock " << socket_.native_handle() << "] Socket destroyed without shutdown."); + GULPS_LOG_L2("[sock ", socket_.native_handle() , "] Socket destroyed without shutdown."); shutdown(); } - _dbg3("[sock " << socket_.native_handle() << "] Socket destroyed"); + GULPS_LOG_L2("[sock ", socket_.native_handle(), "] Socket destroyed"); } //--------------------------------------------------------------------------------- template @@ -122,7 +124,7 @@ boost::shared_ptr> connection template bool connection::start(bool is_income, bool is_multithreaded) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted auto self = safe_shared_from_this(); @@ -133,11 +135,11 @@ bool connection::start(bool is_income, bool is_multithreaded boost::system::error_code ec; auto remote_ep = socket_.remote_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value()); - CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4(), false, "IPv6 not supported here"); + GULPS_CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " , ec.message() , ":" , ec.value()); + GULPS_CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4(), false, "IPv6 not supported here"); auto local_ep = socket_.local_endpoint(ec); - CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value()); + GULPS_CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " , ec.message() , ":" , ec.value()); context = boost::value_initialized(); const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())}; @@ -149,11 +151,11 @@ bool connection::start(bool is_income, bool is_multithreaded random_uuid = crypto::rand(); context.set_details(random_uuid, epee::net_utils::ipv4_network_address(ip_, remote_ep.port()), is_income); - _dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << " to " << local_ep.address().to_string() << ':' << local_ep.port() << ", total sockets objects " << m_ref_sock_count); + GULPS_LOG_L3("[sock ", socket_.native_handle(), "] new connection from ", print_connection_context_short(context), " to ", local_ep.address().to_string(), ":", local_ep.port(), ", total sockets objects ", &m_ref_sock_count); if(m_pfilter && !m_pfilter->is_remote_host_allowed(context.m_remote_address)) { - _dbg2("[sock " << socket_.native_handle() << "] host denied " << context.m_remote_address.host_str() << ", shutdowning connection"); + GULPS_LOG_L1("[sock ", socket_.native_handle(), "] host denied " ); close(); return false; } @@ -175,7 +177,7 @@ bool connection::start(bool is_income, bool is_multithreaded boost::asio::detail::socket_option::integer optionTos(tos); socket_.set_option(optionTos); -//_dbg1("Set ToS flag to " << tos); +//GULPSF_LOG_L1("Set ToS flag to {}", tos); #endif boost::asio::ip::tcp::no_delay noDelayOption(false); @@ -183,72 +185,72 @@ bool connection::start(bool is_income, bool is_multithreaded return true; - CATCH_ENTRY_L0("connection::start()", false); + GULPS_CATCH_ENTRY_L0("connection::start()", false); } //--------------------------------------------------------------------------------- template bool connection::request_callback() { - TRY_ENTRY(); - _dbg2("[" << print_connection_context_short(context) << "] request_callback"); + GULPS_TRY_ENTRY(); + GULPSF_LOG_L1("[{}] request_callback", print_connection_context_short(context) ); // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted auto self = safe_shared_from_this(); if(!self) return false; strand_.post(boost::bind(&connection::call_back_starter, self)); - CATCH_ENTRY_L0("connection::request_callback()", false); + GULPS_CATCH_ENTRY_L0("connection::request_callback()", false); return true; } //--------------------------------------------------------------------------------- template boost::asio::io_service &connection::get_io_service() { - return socket_.get_io_service(); + return GET_IO_SERVICE(socket_); } //--------------------------------------------------------------------------------- template bool connection::add_ref() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted auto self = safe_shared_from_this(); if(!self) return false; - //_dbg3("[sock " << socket_.native_handle() << "] add_ref, m_peer_number=" << mI->m_peer_number); + //GULPSF_LOG_L2("[sock {}] add_ref, m_peer_number={}", socket_.native_handle() , mI->m_peer_number); CRITICAL_REGION_LOCAL(self->m_self_refs_lock); - //_dbg3("[sock " << socket_.native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number); + //GULPSF_LOG_L2("[sock {}] add_ref 2, m_peer_number={}", socket_.native_handle() , mI->m_peer_number); if(m_was_shutdown) return false; m_self_refs.push_back(self); return true; - CATCH_ENTRY_L0("connection::add_ref()", false); + GULPS_CATCH_ENTRY_L0("connection::add_ref()", false); } //--------------------------------------------------------------------------------- template bool connection::release() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); boost::shared_ptr> back_connection_copy; - LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] release"); + GULPS_LOG_L2(context, "[sock ", socket_.native_handle() , "] release"); CRITICAL_REGION_BEGIN(m_self_refs_lock); - CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " << socket_.native_handle() << "] m_self_refs empty at connection::release() call"); + GULPS_CHECK_AND_ASSERT_MES(m_self_refs.size(), false, "[sock " , socket_.native_handle() , "] m_self_refs empty at connection::release() call"); //erasing from container without additional copy can cause start deleting object, including m_self_refs back_connection_copy = m_self_refs.back(); m_self_refs.pop_back(); CRITICAL_REGION_END(); return true; - CATCH_ENTRY_L0("connection::release()", false); + GULPS_CATCH_ENTRY_L0("connection::release()", false); } //--------------------------------------------------------------------------------- template void connection::call_back_starter() { - TRY_ENTRY(); - _dbg2("[" << print_connection_context_short(context) << "] fired_callback"); + GULPS_TRY_ENTRY(); + GULPSF_LOG_L1("[{}] fired_callback", print_connection_context_short(context) ); m_protocol_handler.handle_qued_callback(); - CATCH_ENTRY_L0("connection::call_back_starter()", void()); + GULPS_CATCH_ENTRY_L0("connection::call_back_starter()", void()); } //--------------------------------------------------------------------------------- template @@ -268,17 +270,16 @@ void connection::save_dbg_log() address = endpoint.address().to_string(); port = boost::lexical_cast(endpoint.port()); } - MDEBUG(" connection type " << to_string(m_connection_type) << " " - << socket_.local_endpoint().address().to_string() << ":" << socket_.local_endpoint().port() - << " <--> " << address << ":" << port); + GULPSF_LOG_L1(" connection type {} {}:{} <--> {}:{}", to_string(m_connection_type) , socket_.local_endpoint().address().to_string() , socket_.local_endpoint().port() + , address , port); } //--------------------------------------------------------------------------------- template void connection::handle_read(const boost::system::error_code &e, std::size_t bytes_transferred) { - TRY_ENTRY(); - //_info("[sock " << socket_.native_handle() << "] Async read calledback."); + GULPS_TRY_ENTRY(); + //GULPS_INFO("[sock " << socket_.native_handle() << "] Async read calledback."); if(!e) { @@ -299,7 +300,7 @@ void connection::handle_read(const boost::system::error_code { do // keep sleeping if we should sleep { - { //_scope_dbg1("CRITICAL_REGION_LOCAL"); + { //_scopeGULPSF_LOG_L1("CRITICAL_REGION_LOCAL"); CRITICAL_REGION_LOCAL(epee::net_utils::network_throttle_manager::m_lock_get_global_throttle_in); delay = epee::net_utils::network_throttle_manager::get_global_throttle_in().get_sleep_time_after_tick(bytes_transferred); } @@ -314,14 +315,14 @@ void connection::handle_read(const boost::system::error_code } while(delay > 0); } // any form of sleeping - //_info("[sock " << socket_.native_handle() << "] RECV " << bytes_transferred); + //GULPS_INFO("[sock " << socket_.native_handle() << "] RECV " << bytes_transferred); logger_handle_net_read(bytes_transferred); context.m_last_recv = time(NULL); context.m_recv_cnt += bytes_transferred; bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred); if(!recv_res) { - //_info("[sock " << socket_.native_handle() << "] protocol_want_close"); + //GULPS_INFO("[sock " << socket_.native_handle() << "] protocol_want_close"); //some error in protocol, protocol handler ask to close connection boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); @@ -341,15 +342,15 @@ void connection::handle_read(const boost::system::error_code boost::bind(&connection::handle_read, connection::shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - //_info("[sock " << socket_.native_handle() << "]Async read requested."); + //GULPS_INFO("[sock " << socket_.native_handle() << "]Async read requested."); } } else { - _dbg3("[sock " << socket_.native_handle() << "] Some not success at read: " << e.message() << ':' << e.value()); + GULPS_LOG_L2("[sock ", socket_.native_handle(), "] Some not success at read: ", e.message(), ":", e.value()); if(e.value() != 2) { - _dbg3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value()); + GULPS_LOG_L2("[sock ", socket_.native_handle(), "] Some problems at read: " , e.message(), ":" , e.value()); shutdown(); } } @@ -357,17 +358,17 @@ void connection::handle_read(const boost::system::error_code // means that all shared_ptr references to the connection object will // disappear and the object will be destroyed automatically after this // handler returns. The connection class's destructor closes the socket. - CATCH_ENTRY_L0("connection::handle_read", void()); + GULPS_CATCH_ENTRY_L0("connection::handle_read", void()); } //--------------------------------------------------------------------------------- template bool connection::call_run_once_service_io() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!m_is_multithreaded) { //single thread model, we can wait in blocked call - size_t cnt = socket_.get_io_service().run_one(); + size_t cnt = GET_IO_SERVICE(socket_).run_one(); if(!cnt) //service is going to quit return false; } @@ -378,19 +379,19 @@ bool connection::call_run_once_service_io() //if no handlers were called //TODO: Maybe we need to have have critical section + event + callback to upper protocol to //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = socket_.get_io_service().poll_one(); + size_t cnt = GET_IO_SERVICE(socket_).poll_one(); if(!cnt) misc_utils::sleep_no_w(0); } return true; - CATCH_ENTRY_L0("connection::call_run_once_service_io", false); + GULPS_CATCH_ENTRY_L0("connection::call_run_once_service_io", false); } //--------------------------------------------------------------------------------- template bool connection::do_send(const void *ptr, size_t cb) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted auto self = safe_shared_from_this(); @@ -406,7 +407,7 @@ bool connection::do_send(const void *ptr, size_t cb) const t_safe chunksize_max = chunksize_good * 2; const bool allow_split = (m_connection_type == e_connection_type_RPC) ? false : true; // do not split RPC data - CHECK_AND_ASSERT_MES(!(chunksize_max < 0), false, "Negative chunksize_max"); // make sure it is unsigned before removin sign with cast: + GULPS_CHECK_AND_ASSERT_MES(!(chunksize_max < 0), false, "Negative chunksize_max"); // make sure it is unsigned before removin sign with cast: long long unsigned int chunksize_max_unsigned = static_cast(chunksize_max); if(allow_split && (cb > chunksize_max_unsigned)) @@ -414,7 +415,7 @@ bool connection::do_send(const void *ptr, size_t cb) { // LOCK: chunking epee::critical_region_t send_guard(m_chunking_lock); // *** critical *** - MDEBUG("do_send() will SPLIT into small chunks, from packet=" << cb << " B for ptr=" << ptr); + GULPSF_LOG_L1("do_send() will SPLIT into small chunks, from packet={} B for ptr={}", cb , ptr); t_safe all = cb; // all bytes to send t_safe pos = 0; // current sending position // 01234567890 @@ -430,40 +431,39 @@ bool connection::do_send(const void *ptr, size_t cb) { t_safe lenall = all - pos; // length from here to end t_safe len = std::min(chunksize_good, lenall); // take a smaller part - CHECK_AND_ASSERT_MES(len <= chunksize_good, false, "len too large"); + GULPS_CHECK_AND_ASSERT_MES(len <= chunksize_good, false, "len too large"); // pos=8; len=4; all=10; len=3; - CHECK_AND_ASSERT_MES(!(len < 0), false, "negative len"); // check before we cast away sign: + GULPS_CHECK_AND_ASSERT_MES(!(len < 0), false, "negative len"); // check before we cast away sign: unsigned long long int len_unsigned = static_cast(len); - CHECK_AND_ASSERT_MES(len > 0, false, "len not strictly positive"); // (redundant) - CHECK_AND_ASSERT_MES(len_unsigned < std::numeric_limits::max(), false, "Invalid len_unsigned"); // yeap we want strong < then max size, to be sure + GULPS_CHECK_AND_ASSERT_MES(len > 0, false, "len not strictly positive"); // (redundant) + GULPS_CHECK_AND_ASSERT_MES(len_unsigned < std::numeric_limits::max(), false, "Invalid len_unsigned"); // yeap we want strong < then max size, to be sure void *chunk_start = ((char *)ptr) + pos; - MDEBUG("chunk_start=" << chunk_start << " ptr=" << ptr << " pos=" << pos); - CHECK_AND_ASSERT_MES(chunk_start >= ptr, false, "Pointer wraparound"); // not wrapped around address? + GULPSF_LOG_L1("chunk_start={} ptr={} pos={}", chunk_start , ptr , pos); + GULPS_CHECK_AND_ASSERT_MES(chunk_start >= ptr, false, "Pointer wraparound"); // not wrapped around address? //std::memcpy( (void*)buf, chunk_start, len); - MDEBUG("part of " << lenall << ": pos=" << pos << " len=" << len); + GULPSF_LOG_L1("part of {}: pos={} len={}", lenall , pos , len); bool ok = do_send_chunk(chunk_start, len); // <====== *** all_ok = all_ok && ok; if(!all_ok) { - MDEBUG("do_send() DONE ***FAILED*** from packet=" << cb << " B for ptr=" << ptr); - MDEBUG("do_send() SEND was aborted in middle of big package - this is mostly harmless " - << " (e.g. peer closed connection) but if it causes trouble tell us at https://github.com/ryo-currency/ryo. " << cb); + GULPSF_LOG_L1("do_send() DONE ***FAILED*** from packet={} B for ptr={}", cb , ptr); + GULPSF_LOG_L1("do_send() SEND was aborted in middle of big package - this is mostly harmless (e.g. peer closed connection) but if it causes trouble tell us at https://github.com/ryo-currency/ryo. {}", cb); return false; // partial failure in sending } pos = pos + len; - CHECK_AND_ASSERT_MES(pos > 0, false, "pos <= 0"); + GULPS_CHECK_AND_ASSERT_MES(pos > 0, false, "pos <= 0"); // (in catch block, or uniq pointer) delete buf; } // each chunk - MDEBUG("do_send() DONE SPLIT from packet=" << cb << " B for ptr=" << ptr); + GULPSF_LOG_L1("do_send() DONE SPLIT from packet={} B for ptr={}", cb , ptr); - MDEBUG("do_send() m_connection_type = " << m_connection_type); + GULPSF_LOG_L1("do_send() m_connection_type = {}", m_connection_type); return all_ok; // done - e.g. queued - all the chunks of current do_send call } // LOCK: chunking @@ -473,14 +473,14 @@ bool connection::do_send(const void *ptr, size_t cb) return do_send_chunk(ptr, cb); // just send as 1 big chunk } - CATCH_ENTRY_L0("connection::do_send", false); + GULPS_CATCH_ENTRY_L0("connection::do_send", false); } // do_send() //--------------------------------------------------------------------------------- template bool connection::do_send_chunk(const void *ptr, size_t cb) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); // Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted auto self = safe_shared_from_this(); if(!self) @@ -493,7 +493,7 @@ bool connection::do_send_chunk(const void *ptr, size_t cb) context.m_current_speed_up = m_throttle_speed_out.get_current_speed(); } - //_info("[sock " << socket_.native_handle() << "] SEND " << cb); + //GULPS_INFO("[sock " << socket_.native_handle() << "] SEND " << cb); context.m_last_send = time(NULL); context.m_send_cnt += cb; //some data should be wrote to stream @@ -511,20 +511,20 @@ bool connection::do_send_chunk(const void *ptr, size_t cb) retry++; /* if ( ::cryptonote::core::get_is_stopping() ) { // TODO re-add fast stop - _fact("ABORT queue wait due to stopping"); + GULPS_LOG_L1("ABORT queue wait due to stopping"); return false; // aborted }*/ long int ms = 250 + (rand() % 50); - MDEBUG("Sleeping because QUEUE is FULL, in " << __FUNCTION__ << " for " << ms << " ms before packet_size=" << cb); // XXX debug sleep + GULPSF_LOG_L1("Sleeping because QUEUE is FULL, in {} for {} ms before packet_size={}", __FUNCTION__ , ms , cb); // XXX debug sleep m_send_que_lock.unlock(); boost::this_thread::sleep(boost::posix_time::milliseconds(ms)); m_send_que_lock.lock(); - _dbg1("sleep for queue: " << ms); + GULPSF_LOG_L1("sleep for queue: {}", ms); if(retry > retry_limit) { - MWARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection"); + GULPSF_WARN("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT({}), shutting down connection", ABSTRACT_SERVER_SEND_QUE_MAX_COUNT ); shutdown(); return false; } @@ -536,42 +536,42 @@ bool connection::do_send_chunk(const void *ptr, size_t cb) if(m_send_que.size() > 1) { // active operation should be in progress, nothing to do, just wait last operation callback auto size_now = cb; - MDEBUG("do_send() NOW just queues: packet=" << size_now << " B, is added to queue-size=" << m_send_que.size()); + GULPSF_LOG_L1("do_send() NOW just queues: packet={} B, is added to queue-size={}", size_now , m_send_que.size()); //do_send_handler_delayed( ptr , size_now ); // (((H))) // empty function - LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size()); + GULPS_LOG_L2(context, "[sock ", socket_.native_handle(), "] Async send requested ", m_send_que.front().size()); } else { // no active operation if(m_send_que.size() != 1) { - _erro("Looks like no active operations, but send que size != 1!!"); + GULPS_ERROR("Looks like no active operations, but send que size != 1!!"); return false; } auto size_now = m_send_que.front().size(); - MDEBUG("do_send() NOW SENSD: packet=" << size_now << " B"); + GULPSF_LOG_L1("do_send() NOW SENSD: packet={} B", size_now ); if(speed_limit_is_enabled()) do_send_handler_write(ptr, size_now); // (((H))) - CHECK_AND_ASSERT_MES(size_now == m_send_que.front().size(), false, "Unexpected queue size"); + GULPS_CHECK_AND_ASSERT_MES(size_now == m_send_que.front().size(), false, "Unexpected queue size"); reset_timer(get_default_time(), false); boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), size_now), //strand_.wrap( boost::bind(&connection::handle_write, self, _1, _2) //) ); - //_dbg3("(chunk): " << size_now); + //GULPSF_LOG_L2("(chunk): {}", size_now); //logger_handle_net_write(size_now); - //_info("[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size()); + //GULPS_INFO("[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size()); } //do_send_handler_stop( ptr , cb ); // empty function return true; - CATCH_ENTRY_L0("connection::do_send", false); + GULPS_CATCH_ENTRY_L0("connection::do_send", false); } // do_send_chunk //--------------------------------------------------------------------------------- template @@ -598,11 +598,11 @@ void connection::reset_timer(boost::posix_time::milliseconds { if(m_connection_type != e_connection_type_RPC) return; - MTRACE("Setting " << ms << " expiry"); + GULPS_LOG_L2("Setting ", ms, " expiry"); auto self = safe_shared_from_this(); if(!self) { - MERROR("Resetting timer on a dead object"); + GULPS_ERROR("Resetting timer on a dead object"); return; } if(add) @@ -611,7 +611,7 @@ void connection::reset_timer(boost::posix_time::milliseconds m_timer.async_wait([=](const boost::system::error_code &ec) { if(ec == boost::asio::error::operation_aborted) return; - MDEBUG(context << "connection timeout, closing"); + GULPS_LOG_L1(context, "connection timeout, closing"); self->close(); }); } @@ -631,8 +631,8 @@ bool connection::shutdown() template bool connection::close() { - TRY_ENTRY(); - //_info("[sock " << socket_.native_handle() << "] Que Shutdown called."); + GULPS_TRY_ENTRY(); + //GULPS_INFO("[sock " << socket_.native_handle() << "] Que Shutdown called."); m_timer.cancel(); size_t send_que_size = 0; CRITICAL_REGION_BEGIN(m_send_que_lock); @@ -645,7 +645,7 @@ bool connection::close() } return true; - CATCH_ENTRY_L0("connection::close", false); + GULPS_CATCH_ENTRY_L0("connection::close", false); } //--------------------------------------------------------------------------------- template @@ -657,12 +657,12 @@ bool connection::cancel() template void connection::handle_write(const boost::system::error_code &e, size_t cb) { - TRY_ENTRY(); - LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] Async send calledback " << cb); + GULPS_TRY_ENTRY(); + GULPS_LOG_L2(context, "[sock ", socket_.native_handle(), "] Async send calledback ", cb); if(e) { - _dbg1("[sock " << socket_.native_handle() << "] Some problems at write: " << e.message() << ':' << e.value()); + GULPS_LOG_L1("[sock ", socket_.native_handle(), "] Some problems at write: ", e.message(), ":", e.value()); shutdown(); return; } @@ -678,7 +678,7 @@ void connection::handle_write(const boost::system::error_cod CRITICAL_REGION_BEGIN(m_send_que_lock); if(m_send_que.empty()) { - _erro("[sock " << socket_.native_handle() << "] m_send_que.size() == 0 at handle_write!"); + GULPS_ERROR("[sock ", socket_.native_handle(), "], m_send_que.size() == 0 at handle_write!"); return; } @@ -695,17 +695,16 @@ void connection::handle_write(const boost::system::error_cod //have more data to send reset_timer(get_default_time(), false); auto size_now = m_send_que.front().size(); - MDEBUG("handle_write() NOW SENDS: packet=" << size_now << " B" - << ", from queue size=" << m_send_que.size()); + GULPS_LOG_L1("handle_write NOW SENDS: packet=", size_now, " B, from queue size=", m_send_que.size()); if(speed_limit_is_enabled()) do_send_handler_write_from_queue(e, m_send_que.front().size(), m_send_que.size()); // (((H))) - CHECK_AND_ASSERT_MES(size_now == m_send_que.front().size(), void(), "Unexpected queue size"); + GULPS_CHECK_AND_ASSERT_MES(size_now == m_send_que.front().size(), void(), "Unexpected queue size"); boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), size_now), // strand_.wrap( boost::bind(&connection::handle_write, connection::shared_from_this(), _1, _2) // ) ); - //_dbg3("(normal)" << size_now); + //GULPSF_LOG_L2("(normal){}", size_now); } CRITICAL_REGION_END(); @@ -713,7 +712,7 @@ void connection::handle_write(const boost::system::error_cod { shutdown(); } - CATCH_ENTRY_L0("connection::handle_write", void()); + GULPS_CATCH_ENTRY_L0("connection::handle_write", void()); } //--------------------------------------------------------------------------------- @@ -721,7 +720,7 @@ template void connection::setRpcStation() { m_connection_type = e_connection_type_RPC; - MDEBUG("set m_connection_type = RPC "); + GULPS_LOG_L1("set m_connection_type = RPC "); } template @@ -779,7 +778,7 @@ void boosted_tcp_server::create_server_type_map() template bool boosted_tcp_server::init_server(uint32_t port, const std::string address) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); m_stop_signal_sent = false; m_port = port; m_address = address; @@ -793,7 +792,7 @@ bool boosted_tcp_server::init_server(uint32_t port, const st acceptor_.listen(); boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint(); m_port = binded_endpoint.port(); - MDEBUG("start accept"); + GULPS_LOG_L1("start accept"); new_connection_.reset(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&boosted_tcp_server::handle_accept, this, @@ -803,12 +802,12 @@ bool boosted_tcp_server::init_server(uint32_t port, const st } catch(const std::exception &e) { - MFATAL("Error starting server: " << e.what()); + GULPS_ERROR("Error starting server: ", e.what()); return false; } catch(...) { - MFATAL("Error starting server"); + GULPS_ERROR("Error starting server"); return false; } } @@ -822,7 +821,7 @@ bool boosted_tcp_server::init_server(const std::string port, if(port.size() && !string_tools::get_xtype_from_string(p, port)) { - MERROR("Failed to convert port no = " << port); + GULPSF_ERROR("Failed to convert port no = {}", port); return false; } return this->init_server(p, address); @@ -832,12 +831,12 @@ POP_WARNINGS template bool boosted_tcp_server::worker_thread() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); uint32_t local_thr_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); std::string thread_name = std::string("[") + m_thread_name_prefix; thread_name += boost::to_string(local_thr_index) + "]"; - MLOG_SET_THREAD_NAME(thread_name); - // _fact("Thread name: " << m_thread_name_prefix); + GULPS_SET_THREAD_NAME(thread_name); + // GULPS_LOG_L1("Thread name: ", m_thread_name_prefix); while(!m_stop_signal_sent) { try @@ -846,16 +845,16 @@ bool boosted_tcp_server::worker_thread() } catch(const std::exception &ex) { - _erro("Exception at server worker thread, what=" << ex.what()); + GULPS_ERROR("Exception at server worker thread, what=", ex.what()); } catch(...) { - _erro("Exception at server worker thread, unknown execption"); + GULPS_ERROR("Exception at server worker thread, unknown execption"); } } - //_info("Worker thread finished"); + //GULPS_INFO("Worker thread finished"); return true; - CATCH_ENTRY_L0("boosted_tcp_server::worker_thread", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::worker_thread", false); } //--------------------------------------------------------------------------------- template @@ -866,7 +865,7 @@ void boosted_tcp_server::set_threads_prefix(const std::strin if(it == server_type_map.end()) throw std::runtime_error("Unknown prefix/server type:" + std::string(prefix_name)); auto connection_type = it->second; // the value of type - MINFO("Set server type to: " << connection_type << " from name: " << m_thread_name_prefix << ", prefix_name = " << prefix_name); + GULPSF_INFO("Set server type to: {} from name: {}, prefix_name = {}", connection_type , m_thread_name_prefix , prefix_name); } //--------------------------------------------------------------------------------- template @@ -878,10 +877,10 @@ void boosted_tcp_server::set_connection_filter(i_connection_ template bool boosted_tcp_server::run_server(size_t threads_count, bool wait, const boost::thread::attributes &attrs) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); m_threads_count = threads_count; m_main_thread_id = boost::this_thread::get_id(); - MLOG_SET_THREAD_NAME("[SRV_MAIN]"); + GULPS_SET_THREAD_NAME("[SRV_MAIN]"); while(!m_stop_signal_sent) { @@ -891,51 +890,51 @@ bool boosted_tcp_server::run_server(size_t threads_count, bo { boost::shared_ptr thread(new boost::thread( attrs, boost::bind(&boosted_tcp_server::worker_thread, this))); - _note("Run server thread name: " << m_thread_name_prefix); + GULPS_LOG_L1("Run server thread name: ", m_thread_name_prefix); m_threads.push_back(thread); } CRITICAL_REGION_END(); // Wait for all threads in the pool to exit. if(wait) { - _fact("JOINING all threads"); + GULPS_LOG_L1("JOINING all threads"); for(std::size_t i = 0; i < m_threads.size(); ++i) { m_threads[i]->join(); } - _fact("JOINING all threads - almost"); + GULPS_LOG_L1("JOINING all threads - almost"); m_threads.clear(); - _fact("JOINING all threads - DONE"); + GULPS_LOG_L1("JOINING all threads - DONE"); } else { - _dbg1("Reiniting OK."); + GULPS_LOG_L1("Reiniting OK."); return true; } if(wait && !m_stop_signal_sent) { //some problems with the listening socket ?.. - _dbg1("Net service stopped without stop request, restarting..."); + GULPS_LOG_L1("Net service stopped without stop request, restarting..."); if(!this->init_server(m_port, m_address)) { - _dbg1("Reiniting service failed, exit."); + GULPS_LOG_L1("Reiniting service failed, exit."); return false; } else { - _dbg1("Reiniting OK."); + GULPS_LOG_L1("Reiniting OK."); } } } return true; - CATCH_ENTRY_L0("boosted_tcp_server::run_server", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::run_server", false); } //--------------------------------------------------------------------------------- template bool boosted_tcp_server::is_thread_worker() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_threads_lock); BOOST_FOREACH(boost::shared_ptr &thp, m_threads) { @@ -945,31 +944,31 @@ bool boosted_tcp_server::is_thread_worker() if(m_threads_count == 1 && boost::this_thread::get_id() == m_main_thread_id) return true; return false; - CATCH_ENTRY_L0("boosted_tcp_server::is_thread_worker", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::is_thread_worker", false); } //--------------------------------------------------------------------------------- template bool boosted_tcp_server::timed_wait_server_stop(uint64_t wait_mseconds) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); boost::chrono::milliseconds ms(wait_mseconds); for(std::size_t i = 0; i < m_threads.size(); ++i) { if(m_threads[i]->joinable() && !m_threads[i]->try_join_for(ms)) { - _dbg1("Interrupting thread " << m_threads[i]->native_handle()); + GULPS_LOG_L1("Interrupting thread ", m_threads[i]->get_id()); m_threads[i]->interrupt(); } } return true; - CATCH_ENTRY_L0("boosted_tcp_server::timed_wait_server_stop", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::timed_wait_server_stop", false); } //--------------------------------------------------------------------------------- template void boosted_tcp_server::send_stop_signal() { m_stop_signal_sent = true; - TRY_ENTRY(); + GULPS_TRY_ENTRY(); connections_mutex.lock(); for(auto &c : connections_) { @@ -978,7 +977,7 @@ void boosted_tcp_server::send_stop_signal() connections_.clear(); connections_mutex.unlock(); io_service_.stop(); - CATCH_ENTRY_L0("boosted_tcp_server::send_stop_signal()", void()); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::send_stop_signal()", void()); } //--------------------------------------------------------------------------------- template @@ -990,13 +989,13 @@ bool boosted_tcp_server::is_stop_signal_sent() template void boosted_tcp_server::handle_accept(const boost::system::error_code &e) { - MDEBUG("handle_accept"); - TRY_ENTRY(); + GULPS_LOG_L1("handle_accept"); + GULPS_TRY_ENTRY(); if(!e) { if(m_connection_type == e_connection_type_RPC) { - MDEBUG("New server for RPC connections"); + GULPS_LOG_L1("New server for RPC connections"); new_connection_->setRpcStation(); // hopefully this is not needed actually } connection_ptr conn(std::move(new_connection_)); @@ -1013,20 +1012,20 @@ void boosted_tcp_server::handle_accept(const boost::system:: } else { - _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count); + GULPSF_ERROR("Some problems at accept: {}, connections_count = {}", e.message() , m_sock_count); } - CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::handle_accept", void()); } //--------------------------------------------------------------------------------- template bool boosted_tcp_server::connect(const std::string &adr, const std::string &port, uint32_t conn_timeout, t_connection_context &conn_context, const std::string &bind_ip) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); connection_ptr new_connection_l(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); connections_mutex.lock(); connections_.insert(new_connection_l); - MDEBUG("connections_ size now " << connections_.size()); + GULPSF_LOG_L1("connections_ size now {}", connections_.size()); connections_mutex.unlock(); epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&]() { CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); }); boost::asio::ip::tcp::socket &sock_ = new_connection_l->socket(); @@ -1038,7 +1037,7 @@ bool boosted_tcp_server::connect(const std::string &adr, con boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) { - _erro("Failed to resolve " << adr); + GULPSF_ERROR("Failed to resolve {}", adr); return false; } ////////////////////////////////////////////////////////////////////////// @@ -1091,7 +1090,7 @@ bool boosted_tcp_server::connect(const std::string &adr, con { //timeout sock_.close(); - _dbg3("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")"); + GULPSF_LOG_L2("Failed to connect to {}:{}, because of timeout ({})", adr , port , conn_timeout ); return false; } } @@ -1099,13 +1098,13 @@ bool boosted_tcp_server::connect(const std::string &adr, con if(ec || !sock_.is_open()) { - _dbg3("Some problems at connect, message: " << ec.message()); + GULPSF_LOG_L2("Some problems at connect, message: {}", ec.message()); if(sock_.is_open()) sock_.close(); return false; } - _dbg3("Connected success to " << adr << ':' << port); + GULPSF_LOG_L2("Connected success to {}:{}", adr , port); // start adds the connection to the config object's list, so we don't need to have it locally anymore connections_mutex.lock(); @@ -1119,25 +1118,25 @@ bool boosted_tcp_server::connect(const std::string &adr, con } else { - _erro("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_sock_count); + GULPSF_ERROR("[sock {}] Failed to start connection, connections_count = {}", new_connection_l->socket().native_handle() , m_sock_count); } new_connection_l->save_dbg_log(); return r; - CATCH_ENTRY_L0("boosted_tcp_server::connect", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::connect", false); } //--------------------------------------------------------------------------------- template template bool boosted_tcp_server::connect_async(const std::string &adr, const std::string &port, uint32_t conn_timeout, const t_callback &cb, const std::string &bind_ip) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); connection_ptr new_connection_l(new connection(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type)); connections_mutex.lock(); connections_.insert(new_connection_l); - MDEBUG("connections_ size now " << connections_.size()); + GULPSF_LOG_L1("connections_ size now {}", connections_.size()); connections_mutex.unlock(); epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&]() { CRITICAL_REGION_LOCAL(connections_mutex); connections_.erase(new_connection_l); }); boost::asio::ip::tcp::socket &sock_ = new_connection_l->socket(); @@ -1149,7 +1148,7 @@ bool boosted_tcp_server::connect_async(const std::string &ad boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) { - _erro("Failed to resolve " << adr); + GULPSF_ERROR("Failed to resolve {}", adr); return false; } ////////////////////////////////////////////////////////////////////////// @@ -1168,7 +1167,7 @@ bool boosted_tcp_server::connect_async(const std::string &ad sh_deadline->async_wait([=](const boost::system::error_code &error) { if(error != boost::asio::error::operation_aborted) { - _dbg3("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")"); + GULPSF_LOG_L2("Failed to connect to {}:{}, because of timeout ({})", adr , port , conn_timeout ); new_connection_l->socket().close(); } }); @@ -1185,7 +1184,7 @@ bool boosted_tcp_server::connect_async(const std::string &ad } else { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port << " from " << lep.address().to_string() << ':' << lep.port()); + GULPSF_LOG_L2("[sock {}] Connected success to {}:{} from {}:{}", new_connection_l->socket().native_handle() , adr , port , lep.address().to_string() , lep.port()); // start adds the connection to the config object's list, so we don't need to have it locally anymore connections_mutex.lock(); @@ -1199,19 +1198,19 @@ bool boosted_tcp_server::connect_async(const std::string &ad } else { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection to " << adr << ':' << port); + GULPSF_LOG_L2("[sock {}] Failed to start connection to {}:{}", new_connection_l->socket().native_handle() , adr , port); cb(conn_context, boost::asio::error::fault); } } } else { - _dbg3("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port << " from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value()); + GULPSF_LOG_L2("[sock {}] Failed to connect to {}:{} from {}:{}: {}:{}", new_connection_l->socket().native_handle() , adr , port , lep.address().to_string() , lep.port() , ec_.message() , ec_.value()); cb(conn_context, ec_); } }); return true; - CATCH_ENTRY_L0("boosted_tcp_server::connect_async", false); + GULPS_CATCH_ENTRY_L0("boosted_tcp_server::connect_async", false); } } // namespace diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.h b/contrib/epee/include/net/abstract_tcp_server_cp.h index fb179abf..92ac9e0b 100644 --- a/contrib/epee/include/net/abstract_tcp_server_cp.h +++ b/contrib/epee/include/net/abstract_tcp_server_cp.h @@ -33,7 +33,6 @@ #include #include -#include "misc_log_ex.h" //#include "threads_helper.h" #include "syncobj.h" #define ENABLE_PROFILING @@ -41,8 +40,9 @@ #include "pragma_comp_defs.h" #include "profile_tools.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + #define LEVIN_DEFAULT_DATA_BUFF_SIZE 2000 @@ -54,6 +54,7 @@ namespace net_utils template class cp_server_impl //: public abstract_handler { + GULPS_CAT_MAJOR("epee_tcp_srv"); public: cp_server_impl(/*abstract_handler* phandler = NULL*/); virtual ~cp_server_impl(); @@ -161,7 +162,7 @@ class cp_server_impl //: public abstract_handler if(WSA_IO_PENDING == err) return true; } - LOG_ERROR("BIG FAIL: WSASend error code not correct, res=" << res << " last_err=" << err); + GULPSF_ERROR("BIG FAIL: WSASend error code not correct, res={} las_err={}", res, err); ::InterlockedExchange(&m_psend_data->m_is_in_use, 0); query_shutdown(); //closesocket(m_psend_data); @@ -173,7 +174,7 @@ class cp_server_impl //: public abstract_handler if(!bytes_sent || bytes_sent != cb) { int err = ::WSAGetLastError(); - LOG_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res=" << res << " last_err=" << err); + GULPSF_ERROR("BIG FAIL: WSASend immediatly complete? but bad results, res={} last_err={}", res, err); query_shutdown(); return false; } @@ -192,7 +193,7 @@ class cp_server_impl //: public abstract_handler delete m_psend_data; m_psend_data = (io_data_base *)new char[sizeof(io_data_base) + new_size - 1]; m_psend_data->TotalBuffBytes = new_size; - LOG_PRINT("Connection buffer resized up to " << new_size, LOG_LEVEL_3); + GULPS_PRINT_L3("Connection buffer resized up to ", new_size); return true; } diff --git a/contrib/epee/include/net/abstract_tcp_server_cp.inl b/contrib/epee/include/net/abstract_tcp_server_cp.inl index 9975fade..b812469f 100644 --- a/contrib/epee/include/net/abstract_tcp_server_cp.inl +++ b/contrib/epee/include/net/abstract_tcp_server_cp.inl @@ -26,8 +26,9 @@ #pragma comment(lib, "Ws2_32.lib") -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -54,7 +55,7 @@ bool cp_server_impl::init_server(int port_no) int err = ::WSAStartup(MAKEWORD(2, 2), &wsad); if(err != 0 || LOBYTE(wsad.wVersion) != 2 || HIBYTE(wsad.wVersion) != 2) { - LOG_ERROR("Could not find a usable WinSock DLL, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Could not find a usable WinSock DLL, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -64,7 +65,7 @@ bool cp_server_impl::init_server(int port_no) if(INVALID_SOCKET == m_listen_socket) { err = ::WSAGetLastError(); - LOG_ERROR("Failed to create socket, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Failed to create socket, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -73,7 +74,7 @@ bool cp_server_impl::init_server(int port_no) if(SOCKET_ERROR == err) { err = ::WSAGetLastError(); - LOG_PRINT("Failed to setsockopt(SO_REUSEADDR), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\"", LOG_LEVEL_1); + GULPSF_LOG_L1("Failed to setsockopt(SO_REUSEADDR), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -88,7 +89,7 @@ bool cp_server_impl::init_server(int port_no) if(SOCKET_ERROR == err) { err = ::WSAGetLastError(); - LOG_PRINT("Failed to Bind, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\"", LOG_LEVEL_1); + GULPSF_LOG_L1("Failed to Bind, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -97,7 +98,7 @@ bool cp_server_impl::init_server(int port_no) if(INVALID_HANDLE_VALUE == m_completion_port) { err = ::WSAGetLastError(); - LOG_PRINT("Failed to CreateIoCompletionPort, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\"", LOG_LEVEL_1); + GULPSF_LOG_L1("Failed to CreateIoCompletionPort, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -123,7 +124,7 @@ static int CALLBACK CPConditionFunc( return CF_REJECT;*/ /*if(pthis->get_active_connections_num()>=FD_SETSIZE-1) { - LOG_PRINT("Maximum connections count overfull.", LOG_LEVEL_2); + GULPS_LOG_L2("Maximum connections count overfull."); return CF_REJECT; }*/ @@ -150,7 +151,7 @@ unsigned CALLBACK cp_server_impl::worker_thread(void *param) template bool cp_server_impl::worker_thread_member() { - LOG_PRINT("Worker thread STARTED", LOG_LEVEL_1); + GULPS_LOG_L1("Worker thread STARTED"); bool stop_handling = false; while(!stop_handling) { @@ -166,7 +167,7 @@ bool cp_server_impl::worker_thread_member() { // check return code for error int err = GetLastError(); - LOG_PRINT("GetQueuedCompletionStatus failed with error " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_1); + GULPSF_LOG_L1("GetQueuedCompletionStatus failed with error {} {}", err , log_space::get_win32_err_descr(err)); if(pio_data) ::InterlockedExchange(&pio_data->m_is_in_use, 0); @@ -185,13 +186,13 @@ bool cp_server_impl::worker_thread_member() } if(!pconnection || !pio_data) { - LOG_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection=" << pconnection << " pio_data=" << pio_data, LOG_LEVEL_0); + GULPSF_PRINT("BIG FAIL: pconnection or pio_data is empty: pconnection={} pio_data={}", pconnection, pio_data); break; } if(::InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)) { - LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)"); + GULPS_LOG_ERROR("InterlockedCompareExchange(&pconnection->m_connection_shutwoned, 0, 0)"); //DebugBreak(); } @@ -199,7 +200,7 @@ bool cp_server_impl::worker_thread_member() { if(!pconnection) { - LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!"); + GULPS_LOG_ERROR("op_type=op_type_stop, but pconnection is empty!!!"); continue; } shutdown_connection(pconnection); @@ -233,7 +234,7 @@ bool cp_server_impl::worker_thread_member() int res = 0; while(true) { - LOG_PRINT("Prepearing data for WSARecv....", LOG_LEVEL_3); + GULPS_LOG_L3("Prepearing data for WSARecv...."); ZeroMemory(&pio_data->m_overlapped, sizeof(OVERLAPPED)); pio_data->DataBuf.len = pio_data->TotalBuffBytes; pio_data->DataBuf.buf = pio_data->Buffer; @@ -242,7 +243,7 @@ bool cp_server_impl::worker_thread_member() DWORD bytes_recvd = 0; DWORD flags = 0; - LOG_PRINT("Calling WSARecv....", LOG_LEVEL_3); + GULPS_LOG_L3("Calling WSARecv...."); ::InterlockedExchange(&pio_data->m_is_in_use, 1); res = WSARecv(pconnection->m_sock, &(pio_data->DataBuf), 1, &bytes_recvd, &flags, &(pio_data->m_overlapped), NULL); if(res == SOCKET_ERROR) @@ -250,10 +251,10 @@ bool cp_server_impl::worker_thread_member() int err = ::WSAGetLastError(); if(WSA_IO_PENDING == err) { //go pending, ok - LOG_PRINT("WSARecv return WSA_IO_PENDING", LOG_LEVEL_3); + GULPS_LOG_L3("WSARecv return WSA_IO_PENDING"); break; } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); + GULPS_LOG_ERRORF("BIG FAIL: WSARecv error code not correct, res={} last_err={}", res, err ); ::InterlockedExchange(&pio_data->m_is_in_use, 0); pconnection->query_shutdown(); break; @@ -264,14 +265,14 @@ bool cp_server_impl::worker_thread_member() if(!bytes_recvd) { ::InterlockedExchange(&pio_data->m_is_in_use, 0); - LOG_PRINT("WSARecv return 0, bytes_recvd=0, graceful close.", LOG_LEVEL_3); + GULPS_LOG_L3("WSARecv return 0, bytes_recvd=0, graceful close."); int err = ::WSAGetLastError(); - //LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err); + //GULPS_LOG_ERRORF("BIG FAIL: WSARecv error code not correct, res={} last_err={}", res, err ); //pconnection->query_shutdown(); break; }else { - LOG_PRINT("WSARecv return immediatily 0, bytes_recvd=" << bytes_recvd, LOG_LEVEL_3); + GULPSF_LOG_L3("WSARecv return immediatily 0, bytes_recvd={}", bytes_recvd); //pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd); } }*/ @@ -279,7 +280,7 @@ bool cp_server_impl::worker_thread_member() } } - LOG_PRINT("Worker thread STOPED", LOG_LEVEL_1); + GULPS_LOG_L1("Worker thread STOPED"); ::InterlockedDecrement(&m_worker_thread_counter); return true; } @@ -291,19 +292,19 @@ bool cp_server_impl::shutdown_connection(connection *pconn if(!pconn) { - LOG_ERROR("Attempt to remove null pptr connection!"); + GULPS_LOG_ERROR("Attempt to remove null pptr connection!"); return false; } else { - LOG_PRINT("Shutting down connection (" << pconn << ")", LOG_LEVEL_3); + GULPSF_LOG_L3("Shutting down connection ({})", pconn ); } m_connections_lock.lock(); connections_container::iterator it = m_connections.find(pconn->m_sock); m_connections_lock.unlock(); if(it == m_connections.end()) { - LOG_ERROR("Failed to find closing socket=" << pconn->m_sock); + GULPS_LOG_ERRORF("Failed to find closing socket={}", pconn->m_sock); return false; } SOCKET sock = it->second->m_sock; @@ -313,7 +314,7 @@ bool cp_server_impl::shutdown_connection(connection *pconn } size_t close_sock_wait_count = 0; { - LOG_PRINT("Entered to 'in_use wait zone'", LOG_LEVEL_3); + GULPS_LOG_L3("Entered to 'in_use wait zone'"); PROFILE_FUNC("[shutdown_connection] wait for in_use"); while(::InterlockedCompareExchange(&it->second->m_precv_data->m_is_in_use, 1, 1)) { @@ -321,14 +322,14 @@ bool cp_server_impl::shutdown_connection(connection *pconn Sleep(100); close_sock_wait_count++; } - LOG_PRINT("First step to 'in_use wait zone'", LOG_LEVEL_3); + GULPS_LOG_L3("First step to 'in_use wait zone'"); while(::InterlockedCompareExchange(&it->second->m_psend_data->m_is_in_use, 1, 1)) { Sleep(100); close_sock_wait_count++; } - LOG_PRINT("Leaved 'in_use wait zone'", LOG_LEVEL_3); + GULPS_LOG_L3("Leaved 'in_use wait zone'"); } ::closesocket(it->second->m_sock); @@ -337,7 +338,7 @@ bool cp_server_impl::shutdown_connection(connection *pconn m_connections_lock.lock(); m_connections.erase(it); m_connections_lock.unlock(); - LOG_PRINT("Socked " << sock << " closed, wait_count=" << close_sock_wait_count, LOG_LEVEL_2); + GULPSF_LOG_L2("Socked {} closed, wait_count={}", sock , close_sock_wait_count); return true; } //------------------------------------------------------------- @@ -348,7 +349,7 @@ bool cp_server_impl::run_server(int threads_count = 0) if(SOCKET_ERROR == err) { err = ::WSAGetLastError(); - LOG_ERROR("Failed to listen, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Failed to listen, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -366,7 +367,7 @@ bool cp_server_impl::run_server(int threads_count = 0) //::CloseHandle(h_thread); } - LOG_PRINT("Numbers of worker threads started: " << threads_count, LOG_LEVEL_1); + GULPSF_LOG_L1("Numbers of worker threads started: {}", threads_count); m_stop = false; while(!m_stop) @@ -387,7 +388,7 @@ bool cp_server_impl::run_server(int threads_count = 0) if(SOCKET_ERROR == select_res) { err = ::WSAGetLastError(); - LOG_ERROR("Failed to select, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Failed to select, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); return false; } if(!select_res) @@ -410,17 +411,17 @@ bool cp_server_impl::run_server(int threads_count = 0) if(m_stop) break; int err = ::WSAGetLastError(); - LOG_PRINT("Failed to WSAAccept, err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\"", LOG_LEVEL_2); + GULPSF_LOG_L2("Failed to WSAAccept, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); continue; } - LOG_PRINT("Accepted connection (new socket=" << new_sock << ")", LOG_LEVEL_2); + GULPSF_LOG_L2("Accepted connection (new socket={})", new_sock ); { PROFILE_FUNC("[run_server] Add new connection"); add_new_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); } } } - LOG_PRINT("Closing connections(" << m_connections.size() << ") and waiting...", LOG_LEVEL_2); + GULPSF_LOG_L2("Closing connections({}) and waiting...", m_connections.size() ); m_connections_lock.lock(); for(connections_container::iterator it = m_connections.begin(); it != m_connections.end(); it++) { @@ -434,9 +435,9 @@ bool cp_server_impl::run_server(int threads_count = 0) ::Sleep(100); wait_count++; } - LOG_PRINT("Connections closed OK (wait_count=" << wait_count << ")", LOG_LEVEL_2); + GULPSF_LOG_L2("Connections closed OK (wait_count={})", wait_count ); - LOG_PRINT("Stopping worker threads(" << m_worker_thread_counter << ").", LOG_LEVEL_2); + GULPSF_LOG_L2("Stopping worker threads({}).", m_worker_thread_counter ); for(int i = 0; i < m_worker_thread_counter; i++) { ::PostQueuedCompletionStatus(m_completion_port, 0, 0, 0); @@ -449,7 +450,7 @@ bool cp_server_impl::run_server(int threads_count = 0) wait_count++; } - LOG_PRINT("Net Server STOPPED, wait_count = " << wait_count, LOG_LEVEL_1); + GULPSF_LOG_L1("Net Server STOPPED, wait_count = {}", wait_count); return true; } //------------------------------------------------------------- @@ -458,7 +459,7 @@ bool cp_server_impl::add_new_connection(SOCKET new_sock, const networ { PROFILE_FUNC("[add_new_connection]"); - LOG_PRINT("Add new connection zone: entering lock", LOG_LEVEL_3); + GULPS_LOG_L3("Add new connection zone: entering lock"); m_connections_lock.lock(); boost::shared_ptr> ptr; @@ -466,7 +467,7 @@ bool cp_server_impl::add_new_connection(SOCKET new_sock, const networ connection &conn = *ptr.get(); m_connections[new_sock] = ptr; - LOG_PRINT("Add new connection zone: leaving lock", LOG_LEVEL_3); + GULPS_LOG_L3("Add new connection zone: leaving lock"); m_connections_lock.unlock(); conn.init_buffers(); conn.m_sock = new_sock; @@ -480,7 +481,7 @@ bool cp_server_impl::add_new_connection(SOCKET new_sock, const networ //if(NULL == ::CreateIoCompletionPort((HANDLE)new_sock, m_completion_port, (ULONG_PTR)&conn, 0)) //{ // int err = ::GetLastError(); - // LOG_PRINT("Failed to CreateIoCompletionPort(associate socket and completion port), err = " << err << " \"" << socket_errors::get_socket_error_text(err) <<"\"", LOG_LEVEL_2); + // GULPSF_LOG_L2("Failed to CreateIoCompletionPort(associate socket and completion port), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); // return false; //} @@ -512,7 +513,7 @@ bool cp_server_impl::add_new_connection(SOCKET new_sock, const networ { break; } - LOG_ERROR("BIG FAIL: WSARecv error code not correct, res=" << res << " last_err=" << err << " " << log_space::get_win32_err_descr(err)); + GULPS_LOG_ERRORF("BIG FAIL: WSARecv error code not correct, res={} last_err={} {}", res , err , log_space::get_win32_err_descr(err)); ::InterlockedExchange(&conn.m_precv_data->m_is_in_use, 0); conn.query_shutdown(); //shutdown_connection(&conn); @@ -553,7 +554,7 @@ bool cp_server_impl::deinit_server() if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to closesocket(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Failed to closesocket(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); } m_listen_socket = INVALID_SOCKET; } @@ -562,7 +563,7 @@ bool cp_server_impl::deinit_server() if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to WSACleanup(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOG_ERRORF("Failed to WSACleanup(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); } m_initialized = false; diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 84ed6bbc..8b8c14cd 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -83,7 +83,9 @@ enum t_connection_type std::string to_string(t_connection_type type); class connection_basic -{ // not-templated base class for rapid developmet of some code parts +{ + GULPS_CAT_MAJOR("epee_conn_basics"); + // not-templated base class for rapid developmet of some code parts public: std::unique_ptr mI; // my Implementation diff --git a/contrib/epee/include/net/http_auth.h b/contrib/epee/include/net/http_auth.h index 18a17ed0..b3531be8 100644 --- a/contrib/epee/include/net/http_auth.h +++ b/contrib/epee/include/net/http_auth.h @@ -36,8 +36,7 @@ #include #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h index 8a3fefba..8a419e10 100644 --- a/contrib/epee/include/net/http_base.h +++ b/contrib/epee/include/net/http_base.h @@ -33,8 +33,7 @@ #include "string_tools.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index b7544261..bc76ec8e 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -55,8 +55,9 @@ //#pragma comment(lib, "shlwapi.lib") -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + extern epee::critical_section gregexp_lock; @@ -65,7 +66,7 @@ namespace epee namespace net_utils { -/*struct url +/*struct url { public: void parse(const std::string& url_s) @@ -266,6 +267,9 @@ class http_simple_client_template : public i_target_handler bool m_ssl; public: + + GULPS_CAT_MAJOR("epee_http_client"); + explicit http_simple_client_template() : i_target_handler(), m_net_client(), m_host_buff(), m_port(), m_auth(), m_header_cache(), m_response_info(), m_len_in_summary(0), m_len_in_remain(0), m_pcontent_encoding_handler(nullptr), m_state(), m_chunked_state(), m_chunked_cache(), m_lock(), m_ssl(false) { @@ -278,7 +282,7 @@ class http_simple_client_template : public i_target_handler { http::url_content parsed{}; const bool r = parse_url(address, parsed); - CHECK_AND_ASSERT_MES(r && parsed.host.size() > 0 && parsed.port != 0, false, "failed to parse url: " << address); + GULPS_CHECK_AND_ASSERT_MES(r && parsed.host.size() > 0 && parsed.port != 0, false, "failed to parse url: " , address); set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), ssl); return true; } @@ -336,10 +340,10 @@ class http_simple_client_template : public i_target_handler CRITICAL_REGION_LOCAL(m_lock); if(!is_connected()) { - MDEBUG("Reconnecting..."); + GULPS_LOG_L1("Reconnecting..."); if(!connect(timeout)) { - MDEBUG("Failed to connect to " << m_host_buff << ":" << m_port); + GULPSF_LOG_L1("Failed to connect to {}:{}", m_host_buff , m_port); return false; } } @@ -365,10 +369,10 @@ class http_simple_client_template : public i_target_handler //-- bool res = m_net_client.send(req_buff, timeout); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); + GULPS_CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); if(body.size()) res = m_net_client.send(body, timeout); - CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); + GULPS_CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND"); m_response_info.clear(); m_state = reciev_machine_state_header; @@ -390,12 +394,12 @@ class http_simple_client_template : public i_target_handler break; default: case http_client_auth::kParseFailure: - LOG_ERROR("Bad server response for authentication"); + GULPS_LOG_ERROR("Bad server response for authentication"); return false; } req_buff.resize(initial_size); // rollback for new auth generation } - LOG_ERROR("Client has incorrect username/password for server requiring authentication"); + GULPS_LOG_ERROR("Client has incorrect username/password for server requiring authentication"); return false; } //--------------------------------------------------------------------------- @@ -427,7 +431,7 @@ class http_simple_client_template : public i_target_handler { if(!m_net_client.recv(recv_buffer, timeout)) { - MERROR("Unexpected recv fail"); + GULPS_ERROR("Unexpected recv fail"); m_state = reciev_machine_state_error; } if(!recv_buffer.size()) @@ -472,7 +476,7 @@ class http_simple_client_template : public i_target_handler } else { - LOG_PRINT_L3("Returning false because of wrong state machine. state: " << m_state); + GULPS_LOG_L3("Returning false because of wrong state machine. state: ", m_state); return false; } } @@ -483,7 +487,7 @@ class http_simple_client_template : public i_target_handler CRITICAL_REGION_LOCAL(m_lock); if(!recv_buff.size()) { - LOG_ERROR("Connection closed at handle_header"); + GULPS_LOG_ERROR("Connection closed at handle_header"); m_state = reciev_machine_state_error; return false; } @@ -499,7 +503,7 @@ class http_simple_client_template : public i_target_handler analize_cached_header_and_invoke_state(); if(!on_header(m_response_info)) { - MDEBUG("Connection cancelled by on_header"); + GULPS_LOG_L1("Connection cancelled by on_header"); m_state = reciev_machine_state_done; return false; } @@ -519,11 +523,11 @@ class http_simple_client_template : public i_target_handler CRITICAL_REGION_LOCAL(m_lock); if(!recv_buff.size()) { - MERROR("Warning: Content-Len mode, but connection unexpectedly closed"); + GULPS_ERROR("Warning: Content-Len mode, but connection unexpectedly closed"); m_state = reciev_machine_state_done; return true; } - CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); + GULPS_CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()"); m_len_in_remain -= recv_buff.size(); if(!m_pcontent_encoding_handler->update_in(recv_buff)) { @@ -605,7 +609,7 @@ class http_simple_client_template : public i_target_handler break; else { - LOG_ERROR("http_stream_filter: Wrong last chunk terminator"); + GULPS_LOG_ERROR("http_stream_filter: Wrong last chunk terminator"); return false; } } @@ -632,7 +636,7 @@ class http_simple_client_template : public i_target_handler CRITICAL_REGION_LOCAL(m_lock); if(!recv_buff.size()) { - MERROR("Warning: CHUNKED mode, but connection unexpectedly closed"); + GULPS_ERROR("Warning: CHUNKED mode, but connection unexpectedly closed"); m_state = reciev_machine_state_done; return true; } @@ -662,7 +666,7 @@ class http_simple_client_template : public i_target_handler } if(!get_chunk_head(m_chunked_cache, m_len_in_remain, is_matched)) { - LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head:" << m_chunked_cache); + GULPSF_LOG_ERROR("http_stream_filter::handle_chunked(*) Failed to get length from chunked head:{}", m_chunked_cache); m_state = reciev_machine_state_error; return false; } @@ -714,7 +718,7 @@ class http_simple_client_template : public i_target_handler return true; case http_chunked_state_undefined: default: - LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state" << m_chunked_state); + GULPSF_LOG_ERROR("http_stream_filter::handle_chunked(): Wrong state{}", m_chunked_state); return false; } } @@ -724,7 +728,7 @@ class http_simple_client_template : public i_target_handler //--------------------------------------------------------------------------- inline bool parse_header(http_header_info &body_info, const std::string &m_cache_to_process) { - MTRACE("http_stream_filter::parse_cached_header(*)"); + GULPS_LOG_L2("http_stream_filter::parse_cached_header(*)"); const char *ptr = m_cache_to_process.c_str(); while(ptr[0] != '\r' || ptr[1] != '\n') @@ -740,7 +744,7 @@ class http_simple_client_template : public i_target_handler // optional space (not in RFC, but in previous code) if(*ptr == ' ') ++ptr; - CHECK_AND_ASSERT_MES(*ptr == ':', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process); + GULPS_CHECK_AND_ASSERT_MES(*ptr == ':', true, "http_stream_filter::parse_cached_header() invalid header in: " , m_cache_to_process); ++ptr; // optional whitespace, but not newlines - line folding is obsolete, let's ignore it while(isblank(*ptr)) @@ -754,7 +758,7 @@ class http_simple_client_template : public i_target_handler --value_end; if(*ptr == '\r') ++ptr; - CHECK_AND_ASSERT_MES(*ptr == '\n', true, "http_stream_filter::parse_cached_header() invalid header in: " << m_cache_to_process); + GULPS_CHECK_AND_ASSERT_MES(*ptr == '\n', true, "http_stream_filter::parse_cached_header() invalid header in: " , m_cache_to_process); ++ptr; const std::string key = std::string(key_pos, key_end - key_pos); @@ -792,25 +796,25 @@ class http_simple_client_template : public i_target_handler { //First line response, look like this: "HTTP/1.1 200 OK" const char *ptr = m_header_cache.c_str(); - CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line: " + m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(!memcmp(ptr, "HTTP/", 5), false, "Invalid first response line: " + m_header_cache); ptr += 5; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); unsigned long ul; char *end; ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end == '.', false, "Invalid first response line: " + m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(ul <= INT_MAX && *end == '.', false, "Invalid first response line: " + m_header_cache); m_response_info.m_http_ver_hi = ul; ptr = end + 1; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr); + GULPS_CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache + ", ptr: " , ptr); ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " << ptr); + GULPS_CHECK_AND_ASSERT_MES(ul <= INT_MAX && isblank(*end), false, "Invalid first response line: " + m_header_cache + ", ptr: " , ptr); m_response_info.m_http_ver_lo = ul; ptr = end + 1; while(isblank(*ptr)) ++ptr; - CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(isdigit(*ptr), false, "Invalid first response line: " + m_header_cache); ul = strtoul(ptr, &end, 10); - CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(ul >= 100 && ul <= 999 && isspace(*end), false, "Invalid first response line: " + m_header_cache); m_response_info.m_response_code = ul; ptr = end; // ignore the optional text, till the end @@ -818,7 +822,7 @@ class http_simple_client_template : public i_target_handler ++ptr; if(*ptr == '\r') ++ptr; - CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line: " << m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(*ptr == '\n', false, "Invalid first response line: " , m_header_cache); ++ptr; m_header_cache.erase(0, ptr - m_header_cache.c_str()); @@ -834,7 +838,7 @@ class http_simple_client_template : public i_target_handler m_pcontent_encoding_handler.reset(new content_encoding_gzip(this, result[3].matched)); #else m_pcontent_encoding_handler.reset(new do_nothing_sub_handler(this)); - LOG_ERROR("GZIP encoding not supported in this build, please add zlib to your project and define HTTP_ENABLE_GZIP"); + GULPS_LOG_ERROR("GZIP encoding not supported in this build, please add zlib to your project and define HTTP_ENABLE_GZIP"); return false; #endif } @@ -852,7 +856,7 @@ class http_simple_client_template : public i_target_handler std::string fake_str; //gcc error workaround bool res = parse_header(m_response_info.m_header_info, m_header_cache); - CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " << m_header_cache); + GULPS_CHECK_AND_ASSERT_MES(res, false, "http_stream_filter::analize_cached_reply_header_and_invoke_state(): failed to anilize reply header: " , m_header_cache); set_reply_content_encoder(); @@ -871,7 +875,7 @@ class http_simple_client_template : public i_target_handler string_tools::trim(m_response_info.m_header_info.m_transfer_encoding); if(string_tools::compare_no_case(m_response_info.m_header_info.m_transfer_encoding, "chunked")) { - LOG_ERROR("Wrong Transfer-Encoding:" << m_response_info.m_header_info.m_transfer_encoding); + GULPSF_LOG_ERROR("Wrong Transfer-Encoding:{}", m_response_info.m_header_info.m_transfer_encoding); m_state = reciev_machine_state_error; return false; } @@ -884,7 +888,7 @@ class http_simple_client_template : public i_target_handler //In the response header the length was specified if(!content_len_valid) { - LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length=" << m_response_info.m_header_info.m_content_length); + GULPSF_LOG_ERROR("http_stream_filter::analize_cached_reply_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length={}", m_response_info.m_header_info.m_content_length); m_state = reciev_machine_state_error; return false; } @@ -907,13 +911,13 @@ class http_simple_client_template : public i_target_handler else if(is_multipart_body(m_response_info.m_header_info, fake_str)) { m_state = reciev_machine_state_error; - LOG_ERROR("Unsupported MULTIPART BODY."); + GULPS_LOG_ERROR("Unsupported MULTIPART BODY."); return false; } else { //Apparently there are no signs of the form of transfer, will receive data until the connection is closed m_state = reciev_machine_state_error; - MERROR("Undefined transfer type, consider http_body_transfer_connection_close method. header: " << m_header_cache); + GULPSF_ERROR("Undefined transfer type, consider http_body_transfer_connection_close method. header: {}", m_header_cache); return false; } return false; @@ -942,7 +946,7 @@ class http_simple_client_template : public i_target_handler boundary = result[7]; else { - LOG_ERROR("Failed to match boundary in content-type=" << head_info.m_content_type); + GULPSF_LOG_ERROR("Failed to match boundary in content-type={}", head_info.m_content_type); return false; } return true; diff --git a/contrib/epee/include/net/http_client_base.h b/contrib/epee/include/net/http_client_base.h index c206b735..5e6a8ee1 100644 --- a/contrib/epee/include/net/http_client_base.h +++ b/contrib/epee/include/net/http_client_base.h @@ -26,8 +26,7 @@ #pragma once -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { diff --git a/contrib/epee/include/net/http_client_via_api_helper.h b/contrib/epee/include/net/http_client_via_api_helper.h index ebdb8e7e..0a555604 100644 --- a/contrib/epee/include/net/http_client_via_api_helper.h +++ b/contrib/epee/include/net/http_client_via_api_helper.h @@ -29,13 +29,19 @@ #include #pragma comment(lib, "Wininet.lib") -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + namespace epee { namespace net_utils { +namespace http_client +{ + +GULPS_CAT_MAJOR("epee_http_client"); + inline bool http_ssl_invoke(const std::string &url, const std::string usr, const std::string psw, std::string &http_response_body, bool use_post = false) { bool final_res = false; @@ -47,7 +53,7 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const if(!hinet) { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenA, \nError: " << err << " " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetOpenA, \nError: {} {}", err , log_space::get_win32_err_descr(err)); return false; } @@ -83,7 +89,7 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const //ERROR_INTERNET_INVALID_CA 45 //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpSendRequestA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call HttpSendRequestA, \nError: {}", log_space::get_win32_err_descr(err)); break; } @@ -96,12 +102,12 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const //ERROR_INTERNET_INVALID_CA 45 //ERROR_INTERNET_INVALID_URL (INTERNET_ERROR_BASE + 5) int err = ::GetLastError(); - LOG_PRINT("Failed to call HttpQueryInfo, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call HttpQueryInfo, \nError: {}", log_space::get_win32_err_descr(err)); break; } if(code < 200 || code > 299) { - LOG_PRINT("Wrong server response, HttpQueryInfo returned statuse code" << code, LOG_LEVEL_0); + GULPSF_PRINT("Wrong server response, HttpQueryInfo returned statuse code{}", code); break; } @@ -113,7 +119,7 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const if(!res) { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetReadFile, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetReadFile, \nError: {}", log_space::get_win32_err_descr(err)); break; } if(readed) @@ -134,7 +140,7 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const if(!res) { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetCloseHandle, \nError: {}", log_space::get_win32_err_descr(err)); } break; @@ -144,7 +150,7 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const { //ERROR_INTERNET_INVALID_CA int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetOpenUrlA, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetOpenUrlA, \nError: {}", log_space::get_win32_err_descr(err)); return false; } @@ -152,22 +158,23 @@ inline bool http_ssl_invoke(const std::string &url, const std::string usr, const if(!res) { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetCloseHandle, \nError: {}", log_space::get_win32_err_descr(err)); } } else { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetConnectA(" << string_encoding::convert_to_ansii(url_obj.GetHostName()) << ", port " << port << " \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetConnectA({}, port {} \nError: {}", string_encoding::convert_to_ansii(url_obj.GetHostName()) , port , log_space::get_win32_err_descr(err)); } res = ::InternetCloseHandle(hinet); if(!res) { int err = ::GetLastError(); - LOG_PRINT("Failed to call InternetCloseHandle, \nError: " << log_space::get_win32_err_descr(err), LOG_LEVEL_0); + GULPSF_PRINT("Failed to call InternetCloseHandle, \nError: {}", log_space::get_win32_err_descr(err)); } return final_res; } } } +} diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h index e262b805..c5a9e27e 100644 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -34,8 +34,7 @@ #include #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { @@ -181,7 +180,7 @@ class http_custom_handler : public simple_http_connection_handler #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + #define HTTP_MAX_URI_LEN 9000 #define HTTP_MAX_HEADER_LEN 100000 @@ -46,6 +47,8 @@ namespace net_utils namespace http { +GULPS_CAT_MAJOR("epee_http_proto"); + struct multipart_entry { std::list> m_etc_header_fields; @@ -96,7 +99,7 @@ inline bool parse_header(std::string::const_iterator it_begin, std::string::cons entry.m_etc_header_fields.push_back(std::pair(result[field_etc_name], result[field_val])); else { - LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:" << std::string(it_current_bound, it_end)); + GULPSF_LOG_ERROR("simple_http_connection_handler::parse_header() not matched last entry in:{}", std::string(it_current_bound, it_end)); } it_current_bound = result[(int)result.size() - 1].first; @@ -116,7 +119,7 @@ inline bool handle_part_of_multipart(std::string::const_iterator it_begin, std:: if(!parse_header(it_begin, end_header_it + 4, entry)) { - LOG_ERROR("Failed to parse header:" << std::string(it_begin, end_header_it + 2)); + GULPSF_LOG_ERROR("Failed to parse header:{}", std::string(it_begin, end_header_it + 2)); return false; } @@ -132,7 +135,7 @@ inline bool parse_multipart_body(const std::string &content_type, const std::str std::string boundary; if(!match_boundary(content_type, boundary)) { - MERROR("Failed to match boundary in content type: " << content_type); + GULPSF_ERROR("Failed to match boundary in content type: {}", content_type); return false; } @@ -154,7 +157,7 @@ inline bool parse_multipart_body(const std::string &content_type, const std::str pos = body.find(boundary, std::distance(body.begin(), it_begin)); if(std::string::npos == pos) { - MERROR("Error: Filed to match closing multipart tag"); + GULPS_ERROR("Error: Filed to match closing multipart tag"); it_end = body.end(); } else @@ -177,7 +180,7 @@ inline bool parse_multipart_body(const std::string &content_type, const std::str out_values.push_back(multipart_entry()); if(!handle_part_of_multipart(it_begin, it_end, out_values.back())) { - MERROR("Failed to handle_part_of_multipart"); + GULPS_ERROR("Failed to handle_part_of_multipart"); return false; } @@ -217,7 +220,7 @@ template bool simple_http_connection_handler::handle_recv(const void *ptr, size_t cb) { std::string buf((const char *)ptr, cb); - //LOG_PRINT_L0("HTTP_RECV: " << ptr << "\r\n" << buf); + //GULPSF_PRINT("HTTP_RECV: {}\r\n{}", ptr , buf); //file_io_utils::save_string_to_file(string_tools::get_current_module_folder() + "/" + boost::lexical_cast(ptr), std::string((const char*)ptr, cb)); bool res = handle_buff_in(buf); @@ -257,7 +260,7 @@ bool simple_http_connection_handler::handle_buff_in(std::s m_newlines += std::string::npos == ndel ? m_cache.size() : ndel; if(m_newlines > HTTP_MAX_STARTING_NEWLINES) { - LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too many starting newlines"); + GULPS_LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too many starting newlines"); m_state = http_state_error; return false; } @@ -272,7 +275,7 @@ bool simple_http_connection_handler::handle_buff_in(std::s m_is_stop_handling = true; if(m_cache.size() > HTTP_MAX_URI_LEN) { - LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line"); + GULPS_LOG_ERROR("simple_http_connection_handler::handle_buff_out: Too long URI line"); m_state = http_state_error; return false; } @@ -286,7 +289,7 @@ bool simple_http_connection_handler::handle_buff_in(std::s m_is_stop_handling = true; if(m_cache.size() > HTTP_MAX_HEADER_LEN) { - LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area"); + GULPS_LOG_ERROR("simple_http_connection_handler::handle_buff_in: Too long header area"); m_state = http_state_error; return false; } @@ -301,10 +304,10 @@ bool simple_http_connection_handler::handle_buff_in(std::s case http_state_connection_close: return false; default: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: " << m_state); + GULPSF_LOG_ERROR("simple_http_connection_handler::handle_char_out: Wrong state: {}", m_state); return false; case http_state_error: - LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!"); + GULPS_LOG_ERROR("simple_http_connection_handler::handle_char_out: Error state!!!"); return false; } @@ -317,7 +320,7 @@ bool simple_http_connection_handler::handle_buff_in(std::s //-------------------------------------------------------------------------------------------- inline bool analize_http_method(const boost::smatch &result, http::http_method &method, int &http_ver_major, int &http_ver_minor) { - CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); + GULPS_CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); http_ver_major = boost::lexical_cast(result[11]); http_ver_minor = boost::lexical_cast(result[12]); @@ -352,7 +355,7 @@ bool simple_http_connection_handler::handle_invoke_query_l if(!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content)) { m_state = http_state_error; - MERROR("Failed to parse URI: m_query_info.m_URI"); + GULPS_ERROR("Failed to parse URI: m_query_info.m_URI"); return false; } m_query_info.m_http_method_str = result[2]; @@ -367,7 +370,7 @@ bool simple_http_connection_handler::handle_invoke_query_l else { m_state = http_state_error; - LOG_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: " << m_cache); + GULPSF_LOG_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: {}", m_cache); return false; } @@ -391,14 +394,14 @@ std::string::size_type simple_http_connection_handler::mat template bool simple_http_connection_handler::analize_cached_request_header_and_invoke_state(size_t pos) { - //LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos)); + //GULPSF_LOG_L3("HTTP HEAD:\r\n{}", m_cache.substr(0, pos)); m_query_info.m_full_request_buf_size = pos; m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin() + pos); if(!parse_cached_header(m_query_info.m_header_info, m_cache, pos)) { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): failed to anilize request header: " << m_cache); + GULPSF_LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): failed to anilize request header: {}", m_cache); m_state = http_state_error; return false; } @@ -414,7 +417,7 @@ bool simple_http_connection_handler::analize_cached_reques m_body_transfer_type = http_body_transfer_measure; if(!get_len_from_content_lenght(m_query_info.m_header_info.m_content_length, m_len_summary)) { - LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length=" << m_query_info.m_header_info.m_content_length); + GULPSF_LOG_ERROR("simple_http_connection_handler::analize_cached_request_header_and_invoke_state(): Failed to get_len_from_content_lenght();, m_query_info.m_content_length={}", m_query_info.m_header_info.m_content_length); m_state = http_state_error; return false; } @@ -448,7 +451,7 @@ bool simple_http_connection_handler::handle_retriving_quer case http_body_transfer_multipart: case http_body_transfer_undefined: default: - LOG_ERROR("simple_http_connection_handler::handle_retriving_query_body(): Unexpected m_body_query_type state:" << m_body_transfer_type); + GULPSF_LOG_ERROR("simple_http_connection_handler::handle_retriving_query_body(): Unexpected m_body_query_type state:{}", m_body_transfer_type); m_state = http_state_error; return false; } @@ -530,7 +533,7 @@ bool simple_http_connection_handler::parse_cached_header(h body_info.m_etc_fields.push_back(std::pair(result[field_etc_name], result[field_val])); else { - LOG_ERROR("simple_http_connection_handler::parse_cached_header() not matched last entry in:" << m_cache_to_process); + GULPSF_LOG_ERROR("simple_http_connection_handler::parse_cached_header() not matched last entry in:{}", m_cache_to_process); } it_current_bound = result[(int)result.size() - 1].first; @@ -555,7 +558,7 @@ template bool simple_http_connection_handler::handle_request_and_send_response(const http::http_request_info &query_info) { http_response_info response{}; - //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); + // GULPS_CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); bool res = true; if(query_info.m_http_method != http::http_method_options) @@ -569,10 +572,9 @@ bool simple_http_connection_handler::handle_request_and_se } std::string response_data = get_response_header(response); - //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body); + //GULPSF_PRINT("HTTP_SEND: << \r\n{}", response_data + response.m_body); - LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" - << response_data); + GULPSF_LOG_L3("HTTP_RESPONSE_HEAD: << \r\n{}", response_data); m_psnd_hndlr->do_send((void *)response_data.data(), response_data.size()); if((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options)) @@ -594,7 +596,7 @@ bool simple_http_connection_handler::handle_request(const m_config.m_lock.unlock(); if(!file_io_utils::load_file_to_string(destination_file_path.c_str(), response.m_body)) { - MWARNING("URI \"" << query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size() - 2) << "\" [" << destination_file_path << "] Not Found (404 )"); + GULPSF_WARN("URI '{}' [{}] Not Found (404 )", query_info.m_full_request_str.substr(0, query_info.m_full_request_str.size() - 2) , destination_file_path ); response.m_body = get_not_found_response_body(query_info.m_URI); response.m_response_code = 404; response.m_response_comment = "Not found"; @@ -602,7 +604,7 @@ bool simple_http_connection_handler::handle_request(const return true; } - MDEBUG(" -->> " << query_info.m_full_request_str << "\r\n<<--OK"); + GULPS_LOG_L1(" -->> ", query_info.m_full_request_str, "\r\n<<--OK"); response.m_response_code = 200; response.m_response_comment = "OK"; response.m_mime_tipe = get_file_mime_tipe(uri_to_path); diff --git a/contrib/epee/include/net/http_server_cp.h b/contrib/epee/include/net/http_server_cp.h index 41e2773a..1abacd2a 100644 --- a/contrib/epee/include/net/http_server_cp.h +++ b/contrib/epee/include/net/http_server_cp.h @@ -30,8 +30,7 @@ #include "abstract_tcp_server_cp.h" #include "http_server.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { diff --git a/contrib/epee/include/net/http_server_cp2.h b/contrib/epee/include/net/http_server_cp2.h index e0cc5cf0..a92545e9 100644 --- a/contrib/epee/include/net/http_server_cp2.h +++ b/contrib/epee/include/net/http_server_cp2.h @@ -30,8 +30,7 @@ #include "abstract_tcp_server2.h" #include "http_protocol_handler.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" + namespace epee { diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index a87de1cc..5ecf9493 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -30,15 +30,16 @@ #include "storages/portable_storage.h" #include "storages/portable_storage_template_helper.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + #define CHAIN_HTTP_TO_MAP2(context_type) \ bool handle_http_request(const epee::net_utils::http::http_request_info &query_info, \ epee::net_utils::http::http_response_info &response, \ context_type &m_conn_context) \ { \ - LOG_PRINT_L2("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \ + {GULPS_CAT_MAJOR("epee_http_serv"); GULPSF_LOG_L2("HTTP [{}] {}", m_conn_context.m_remote_address.host_str(), query_info.m_http_method_str, query_info.m_URI);} \ response.m_response_code = 200; \ response.m_response_comment = "Ok"; \ if(!handle_http_request_map(query_info, response, m_conn_context)) \ @@ -70,13 +71,14 @@ uint64_t ticks = misc_utils::get_tick_count(); \ boost::value_initialized req; \ bool parse_res = epee::serialization::load_t_from_json(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" \ - << query_info.m_body); \ + GULPS_CAT_MAJOR("epee_http_serv"); \ + GULPS_CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" \ + , query_info.m_body); \ uint64_t ticks1 = epee::misc_utils::get_tick_count(); \ boost::value_initialized resp; \ if(!callback_f(static_cast(req), static_cast(resp))) \ { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ + GULPSF_ERROR("Failed to {}()", #callback_f); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ @@ -86,7 +88,7 @@ uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ response_info.m_mime_tipe = "application/json"; \ response_info.m_header_info.m_content_type = " application/json"; \ - MDEBUG(s_pattern << " processed with " << ticks1 - ticks << "/" << ticks2 - ticks1 << "/" << ticks3 - ticks2 << "ms"); \ + GULPSF_LOG_L1("{} processed with {}/{}/{}ms", s_pattern, ticks1 - ticks, ticks2 - ticks1, ticks3 - ticks2); \ } #define MAP_URI_AUTO_JON2(s_pattern, callback_f, command_type) MAP_URI_AUTO_JON2_IF(s_pattern, callback_f, command_type, true) @@ -94,16 +96,17 @@ #define MAP_URI_AUTO_BIN2(s_pattern, callback_f, command_type) \ else if(query_info.m_URI == s_pattern) \ { \ + GULPS_CAT_MAJOR("epee_http_serv"); \ handled = true; \ uint64_t ticks = misc_utils::get_tick_count(); \ boost::value_initialized req; \ bool parse_res = epee::serialization::load_t_from_binary(static_cast(req), query_info.m_body); \ - CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \ + GULPS_CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" , query_info.m_body.size()); \ uint64_t ticks1 = misc_utils::get_tick_count(); \ boost::value_initialized resp; \ if(!callback_f(static_cast(req), static_cast(resp))) \ { \ - LOG_ERROR("Failed to " << #callback_f << "()"); \ + GULPSF_ERROR("Failed to {}()", #callback_f); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ @@ -113,7 +116,7 @@ uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ response_info.m_mime_tipe = " application/octet-stream"; \ response_info.m_header_info.m_content_type = " application/octet-stream"; \ - MDEBUG(s_pattern << "() processed with " << ticks1 - ticks << "/" << ticks2 - ticks1 << "/" << ticks3 - ticks2 << "ms"); \ + GULPSF_LOG_L1("{}() processed with {}/{}/{}ms", s_pattern, ticks1 - ticks, ticks2 - ticks1, ticks3 - ticks2); \ } #define CHAIN_URI_MAP2(callback) \ @@ -182,7 +185,7 @@ uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ response_info.m_mime_tipe = "application/json"; \ response_info.m_header_info.m_content_type = " application/json"; \ - MDEBUG(query_info.m_URI << "[" << method_name << "] processed with " << ticks1 - ticks << "/" << ticks2 - ticks1 << "/" << ticks3 - ticks2 << "ms"); + {GULPS_CAT_MAJOR("epee_http_serv"); GULPSF_LOG_L1("{}[{}] processed with {}/{}/{}ms", query_info.m_URI, method_name, ticks1 - ticks, ticks2 - ticks1, ticks3 - ticks2);} #define MAP_JON_RPC_WE_IF(method_name, callback_f, command_type, cond) \ else if((callback_name == method_name) && (cond)) \ diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index db640937..25cbe252 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -32,8 +32,9 @@ #include "net/http_server_cp2.h" #include "net/http_server_handlers_map2.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + namespace epee { @@ -41,7 +42,7 @@ namespace epee template class http_server_impl_base : public net_utils::http::i_http_server_handler { - + GULPS_CAT_MAJOR("epee_http_serv"); public: http_server_impl_base() : m_net_server(epee::net_utils::e_connection_type_RPC) @@ -71,11 +72,11 @@ class http_server_impl_base : public net_utils::http::i_http_server_handler 4096) { - LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request"); + GULPS_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request"); return false; } break; @@ -147,14 +151,12 @@ class jsonrpc2_connection_handler } bool handle_request_and_send_response(const std::string &request_data) { - CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); + GULPS_CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!"); std::string response_data; - LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" - << request_data); + GULPSF_LOG_L3("JSONRPC2_REQUEST: >> \r\n{}", request_data); bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context); - LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" - << response_data); + GULPSF_LOG_L3("JSONRPC2_RESPONSE: << \r\n{}", response_data); m_psnd_hndlr->do_send((void *)response_data.data(), response_data.size()); return rpc_result; diff --git a/contrib/epee/include/net/jsonrpc_server_handlers_map.h b/contrib/epee/include/net/jsonrpc_server_handlers_map.h index 5278db84..4292f04c 100644 --- a/contrib/epee/include/net/jsonrpc_server_handlers_map.h +++ b/contrib/epee/include/net/jsonrpc_server_handlers_map.h @@ -8,6 +8,8 @@ #include "storages/portable_storage_template_helper.h" #include +#include "common/gulps.hpp" + #define BEGIN_JSONRPC2_MAP(t_connection_context) \ bool handle_rpc_request(const std::string &req_data, \ std::string &resp_data, \ @@ -57,7 +59,7 @@ epee::serialization::store_t_to_json(resp, resp_data, 0, false); \ resp_data += "\n"; \ uint64_t ticks3 = epee::misc_utils::get_tick_count(); \ - LOG_PRINT("[" << method_name << "] processed with " << ticks1 - ticks << "/" << ticks2 - ticks1 << "/" << ticks3 - ticks2 << "ms", LOG_LEVEL_2); + {GULPS_CAT_MAJOR("epee_jsrpc_serv"); GULPS_LOG_L2("[{}] processed with {}/{}/{}ms", method_name, ticks1 - ticks, ticks2 - ticks1, ticks3 - ticks2);} #define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \ else if(callback_name == method_name) \ diff --git a/contrib/epee/include/net/jsonrpc_server_impl_base.h b/contrib/epee/include/net/jsonrpc_server_impl_base.h index 44d03e7f..8da1f81d 100644 --- a/contrib/epee/include/net/jsonrpc_server_impl_base.h +++ b/contrib/epee/include/net/jsonrpc_server_impl_base.h @@ -8,13 +8,15 @@ #include "net/jsonrpc_protocol_handler.h" #include "net/jsonrpc_server_handlers_map.h" +#include "common/gulps.hpp" + namespace epee { template class jsonrpc_server_impl_base : public net_utils::jsonrpc2::i_jsonrpc2_server_handler { - + GULPS_CAT_MAJOR("epee_jsrpc_serv"); public: jsonrpc_server_impl_base() : m_net_server() @@ -31,11 +33,11 @@ class jsonrpc_server_impl_base : public net_utils::jsonrpc2::i_jsonrpc2_server_h //set self as callback handler m_net_server.get_config_object().m_phandler = static_cast(this); - LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port); + GULPSF_PRINT("Binding on {}:{}", bind_ip , bind_port); bool res = m_net_server.init_server(bind_port, bind_ip); if(!res) { - LOG_ERROR("Failed to bind server"); + GULPS_ERROR("Failed to bind server"); return false; } return true; @@ -44,14 +46,14 @@ class jsonrpc_server_impl_base : public net_utils::jsonrpc2::i_jsonrpc2_server_h bool run(size_t threads_count, bool wait = true) { //go to loop - LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0); + GULPSF_PRINT("Run net_service loop( {} threads)...", threads_count ); if(!m_net_server.run_server(threads_count, wait)) { - LOG_ERROR("Failed to run net tcp server!"); + GULPS_ERROR("Failed to run net tcp server!"); } if(wait) - LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0); + GULPS_PRINT("net_service loop stopped."); return true; } diff --git a/contrib/epee/include/net/jsonrpc_structs.h b/contrib/epee/include/net/jsonrpc_structs.h index 033a189c..7bef9f1b 100644 --- a/contrib/epee/include/net/jsonrpc_structs.h +++ b/contrib/epee/include/net/jsonrpc_structs.h @@ -18,7 +18,7 @@ struct request epee::serialization::storage_entry id; t_param params; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(jsonrpc) KV_SERIALIZE(id) KV_SERIALIZE(method) @@ -30,7 +30,7 @@ struct error { int64_t code; std::string message; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(error) KV_SERIALIZE(code) KV_SERIALIZE(message) END_KV_SERIALIZE_MAP() @@ -38,13 +38,13 @@ struct error struct dummy_error { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(dummy_error) END_KV_SERIALIZE_MAP() }; struct dummy_result { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(dummy_result) END_KV_SERIALIZE_MAP() }; @@ -55,7 +55,7 @@ struct response t_param result; epee::serialization::storage_entry id; t_error error; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(jsonrpc) KV_SERIALIZE(id) KV_SERIALIZE(result) @@ -69,7 +69,7 @@ struct response std::string jsonrpc; t_param result; epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(jsonrpc) KV_SERIALIZE(id) KV_SERIALIZE(result) @@ -82,7 +82,7 @@ struct response std::string jsonrpc; t_error error; epee::serialization::storage_entry id; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(jsonrpc) KV_SERIALIZE(id) KV_SERIALIZE(error) diff --git a/contrib/epee/include/net/levin_client.h b/contrib/epee/include/net/levin_client.h index 7b3d172a..8bb06b81 100644 --- a/contrib/epee/include/net/levin_client.h +++ b/contrib/epee/include/net/levin_client.h @@ -38,11 +38,14 @@ namespace epee { namespace levin { + /************************************************************************/ /* */ /************************************************************************/ class levin_client_impl { + GULPS_CAT_MAJOR("epee_lev_cli"); + public: levin_client_impl(); virtual ~levin_client_impl(); diff --git a/contrib/epee/include/net/levin_client.inl b/contrib/epee/include/net/levin_client.inl index f5a3e3f8..0ef17990 100644 --- a/contrib/epee/include/net/levin_client.inl +++ b/contrib/epee/include/net/levin_client.inl @@ -26,10 +26,12 @@ //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ + #include "string_tools.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -88,7 +90,7 @@ inline int levin_client_impl::invoke(int command, const std::string &in_buff, st if(head.m_signature != LEVIN_SIGNATURE) { - LOG_PRINT_L1("Signature mismatch in response"); + GULPS_LOG_L1("Signature mismatch in response"); return -1; } @@ -146,7 +148,7 @@ inline int levin_client_impl2::invoke(int command, const std::string &in_buff, s if(head.m_signature != LEVIN_SIGNATURE) { - LOG_PRINT_L1("Signature mismatch in response"); + GULPS_LOG_L1("Signature mismatch in response"); return -1; } diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h index c0502e1a..ee058c23 100644 --- a/contrib/epee/include/net/levin_client_async.h +++ b/contrib/epee/include/net/levin_client_async.h @@ -30,8 +30,9 @@ #include "levin_base.h" #include "net_helper.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -39,15 +40,17 @@ namespace levin { /************************************************************************ - * levin_client_async - probably it is not really fast implementation, - * each handler thread could make up to 30 ms latency. + * levin_client_async - probably it is not really fast implementation, + * each handler thread could make up to 30 ms latency. * But, handling events in reader thread will cause dead locks in - * case of recursive call (call invoke() to the same connection + * case of recursive call (call invoke() to the same connection * on reader thread on remote invoke() handler) ***********************************************************************/ class levin_client_async { + GULPS_CAT_MAJOR("epee_lev_cli"); + levin_commands_handler *m_pcommands_handler; void (*commands_handler_destroy)(levin_commands_handler *); volatile uint32_t m_is_stop; @@ -74,8 +77,8 @@ class levin_client_async }; std::list m_recieved_packets; /* - m_current_connection_index needed when some connection was broken and reconnected - in this - case we could have some received packets in que, which shoud not be handled + m_current_connection_index needed when some connection was broken and reconnected - in this + case we could have some received packets in que, which shoud not be handled */ volatile uint32_t m_current_connection_index; ::critical_section m_invoke_lock; @@ -148,7 +151,7 @@ class levin_client_async { if(!reconnect()) { - LOG_ERROR("Reconnect Failed. Failed to invoke() because not connected!"); + GULPS_LOG_ERROR("Reconnect Failed. Failed to invoke() because not connected!"); return false; } } @@ -168,7 +171,7 @@ class levin_client_async return false; int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to recv(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); //reconnect(); return false; @@ -179,7 +182,7 @@ class levin_client_async //reconnect(); return false; } - LOG_PRINT_L4("[" << m_socket << "] RECV " << res); + GULPSF_LOG_L3("[{}] RECV {}", m_socket , res); cb -= res; pbuff += res; } @@ -245,29 +248,29 @@ class levin_client_async head.m_command = command; head.m_protocol_version = LEVIN_PROTOCOL_VER_1; head.m_flags = LEVIN_PACKET_REQUEST; - LOG_PRINT("[" << m_socket << "] Sending invoke data", LOG_LEVEL_4); + GULPSF_LOG_L3("[{}] Sending invoke data", m_socket ); CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket << "] SEND " << sizeof(head)); + GULPSF_LOG_L3("[{}] SEND {}", m_socket , sizeof(head)); int res = ::send(m_socket, (const char *)&head, sizeof(head), 0); if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to send(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); return LEVIN_ERROR_CONNECTION_DESTROYED; } - LOG_PRINT_L4("[" << m_socket << "] SEND " << (int)in_buff.size()); + GULPSF_LOG_L3("[{}] SEND {}", m_socket , (int)in_buff.size()); res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to send(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); return LEVIN_ERROR_CONNECTION_DESTROYED; } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data << ", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + GULPSF_LOG_L3("LEVIN_PACKET_SENT. [len={}, flags={}, is_cmd={}, cmd_id = {}, pr_v={}, uid={}]{}", head.m_cb , head.m_flags , head.m_have_to_return_data , head.m_command , head.m_protocol_version , string_tools::get_str_from_guid_a(head.m_id) ); //hard coded timeout in 10 minutes for maximum invoke period. if it happens, it could mean only some real troubles. boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(100); @@ -294,7 +297,7 @@ class levin_client_async } else { - LOG_PRINT("[" << m_socket << "] Timeout on waiting invoke result. ", LOG_LEVEL_0); + GULPSF_PRINT("[{}] Timeout on waiting invoke result. ", m_socket ); //disconnect(); return LEVIN_ERROR_CONNECTION_TIMEDOUT; } @@ -325,26 +328,26 @@ class levin_client_async head.m_protocol_version = LEVIN_PROTOCOL_VER_1; head.m_flags = LEVIN_PACKET_REQUEST; CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket << "] SEND " << sizeof(head)); + GULPSF_LOG_L3("[{}] SEND {}", m_socket , sizeof(head)); int res = ::send(m_socket, (const char *)&head, sizeof(head), 0); if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to send(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); return LEVIN_ERROR_CONNECTION_DESTROYED; } - LOG_PRINT_L4("[" << m_socket << "] SEND " << (int)in_buff.size()); + GULPSF_LOG_L3("[{}] SEND {}", m_socket , (int)in_buff.size()); res = ::send(m_socket, in_buff.data(), (int)in_buff.size(), 0); if(SOCKET_ERROR == res) { int err = ::WSAGetLastError(); - LOG_ERROR("Failed to send(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPSF_LOG_ERROR("Failed to send(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); return LEVIN_ERROR_CONNECTION_DESTROYED; } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data << ", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + GULPSF_LOG_L3("LEVIN_PACKET_SENT. [len={}, flags={}, is_cmd={}, cmd_id = {}, pr_v={}, uid={}]{}", head.m_cb , head.m_flags , head.m_have_to_return_data , head.m_command , head.m_protocol_version , string_tools::get_str_from_guid_a(head.m_id) ); return 1; } @@ -372,7 +375,7 @@ class levin_client_async if(m_is_stop) return false; int err_code = ::WSAGetLastError(); - LOG_ERROR("Filed to call select, err code = " << err_code); + GULPSF_LOG_ERROR("Filed to call select, err code = {}", err_code); disconnect(); } else @@ -401,7 +404,7 @@ class levin_client_async { if(m_is_stop) return false; - LOG_ERROR("Failed to recv_n"); + GULPS_LOG_ERROR("Failed to recv_n"); return false; } @@ -409,7 +412,7 @@ class levin_client_async if(head.m_signature != LEVIN_SIGNATURE) { - LOG_ERROR("Signature mismatch in response"); + GULPS_LOG_ERROR("Signature mismatch in response"); return false; } @@ -420,12 +423,12 @@ class levin_client_async { if(m_is_stop) return false; - LOG_ERROR("Filed to reciev"); + GULPS_LOG_ERROR("Filed to reciev"); return false; } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_RECIEVED. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data << ", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + GULPSF_LOG_L3("LEVIN_PACKET_RECIEVED. [len={}, flags={}, is_cmd={}, cmd_id = {}, pr_v={}, uid={}]", head.m_cb , head.m_flags , head.m_have_to_return_data , head.m_command , head.m_protocol_version , string_tools::get_str_from_guid_a(head.m_id) ); if(is_request) { @@ -454,7 +457,7 @@ class levin_client_async bool reciever_thread() { - LOG_PRINT_L3("[" << m_socket << "] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); + GULPSF_LOG_L3("[{}] Socket reciever thread started.[m_threads_count={}]", m_socket , m_threads_count ); log_space::log_singletone::set_thread_log_prefix("RECIEVER_WORKER"); boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); @@ -475,7 +478,7 @@ class levin_client_async break; //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); //return true; } - LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); + GULPS_LOG_ERROR("Failed to reciev_and_process_incoming_data. shutting down"); //boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); //disconnect_no_wait(); //break; @@ -484,7 +487,7 @@ class levin_client_async } boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket << "] Socket reciever thread stopped.[m_threads_count=" << m_threads_count << "]"); + GULPSF_LOG_L3("[{}] Socket reciever thread stopped.[m_threads_count={}]", m_socket , m_threads_count ); return true; } @@ -517,11 +520,11 @@ class levin_client_async if(res == SOCKET_ERROR) { int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); + GULPSF_LOG_ERROR("Failed to send, err = {}", err_code); return false; } CRITICAL_REGION_END(); - LOG_PRINT_L4("LEVIN_PACKET_SENT. [len=" << head.m_cb << ", flags=" << head.m_flags << ", is_cmd=" << head.m_have_to_return_data << ", cmd_id = " << head.m_command << ", pr_v=" << head.m_protocol_version << ", uid=" << string_tools::get_str_from_guid_a(head.m_id) << "]"); + GULPSF_LOG_L3("LEVIN_PACKET_SENT. [len={}, flags={}, is_cmd={}, cmd_id = {}, pr_v={}, uid={}]{}", head.m_cb , head.m_flags , head.m_have_to_return_data , head.m_command , head.m_protocol_version , string_tools::get_str_from_guid_a(head.m_id) ); } else { @@ -534,7 +537,7 @@ class levin_client_async bool handler_thread() { - LOG_PRINT_L3("[" << m_socket << "] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); + GULPSF_LOG_L3("[{}] Socket handler thread started.[m_threads_count={}]", m_socket , m_threads_count ); log_space::log_singletone::set_thread_log_prefix("HANDLER_WORKER"); boost::interprocess::ipcdetail::atomic_inc32(&m_threads_count); @@ -568,7 +571,7 @@ class levin_client_async } boost::interprocess::ipcdetail::atomic_dec32(&m_threads_count); - LOG_PRINT_L3("[" << m_socket << "] Socket handler thread stopped.[m_threads_count=" << m_threads_count << "]"); + GULPSF_LOG_L3("[{}] Socket handler thread stopped.[m_threads_count={}]", m_socket , m_threads_count ); return true; } }; diff --git a/contrib/epee/include/net/levin_helper.h b/contrib/epee/include/net/levin_helper.h index 61478e45..ddd46bbe 100644 --- a/contrib/epee/include/net/levin_helper.h +++ b/contrib/epee/include/net/levin_helper.h @@ -29,8 +29,9 @@ #include "levin_base.h" #include "serializeble_struct_helper.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -77,21 +78,22 @@ bool pack_data_to_levin_message(const std::string &data, std::string &buff, int bool load_levin_data_from_levin_message(std::string &levin_data, const std::string &buff, int &command) { + GULPS_CAT_MAJOR("epee_lev_help"); if(buff.size() < sizeof(levin::bucket_head)) { - LOG_PRINT_L3("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); + GULPS_LOG_L3("size of buff(", buff.size(), ") is too small, at load_struct_from_levin_message"); return false; } levin::bucket_head &head = *(levin::bucket_head *)(&buff[0]); if(head.m_signature != LEVIN_SIGNATURE) { - LOG_PRINT_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); + GULPS_LOG_L3("Failed to read signature in levin message, at load_struct_from_levin_message"); return false; } if(head.m_cb != buff.size() - sizeof(levin::bucket_head)) { - LOG_PRINT_L3("sizes mismatch, at load_struct_from_levin_message"); + GULPS_LOG_L3("sizes mismatch, at load_struct_from_levin_message"); return false; } @@ -104,21 +106,22 @@ bool load_levin_data_from_levin_message(std::string &levin_data, const std::stri template bool load_struct_from_levin_message(t_struct &t, const std::string &buff, int &command) { + GULPS_CAT_MAJOR("epee_lev_help"); if(buff.size() < sizeof(levin::bucket_head)) { - LOG_ERROR("size of buff(" << buff.size() << ") is too small, at load_struct_from_levin_message"); + GULPS_ERROR("size of buff(", buff.size(), ") is too small, at load_struct_from_levin_message"); return false; } levin::bucket_head &head = *(levin::bucket_head *)(&buff[0]); if(head.m_signature != LEVIN_SIGNATURE) { - LOG_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); + GULPS_ERROR("Failed to read signature in levin message, at load_struct_from_levin_message"); return false; } if(head.m_cb != buff.size() - sizeof(levin::bucket_head)) { - LOG_ERROR("sizes mismatch, at load_struct_from_levin_message"); + GULPS_ERROR("sizes mismatch, at load_struct_from_levin_message"); return false; } @@ -127,7 +130,7 @@ bool load_struct_from_levin_message(t_struct &t, const std::string &buff, int &c if(!StorageNamed::load_struct_from_storage_buff_t(t, buff_strg)) { - LOG_ERROR("Failed to read storage, at load_struct_from_levin_message"); + GULPS_ERROR("Failed to read storage, at load_struct_from_levin_message"); return false; } command = head.m_command; diff --git a/contrib/epee/include/net/levin_protocol_handler.h b/contrib/epee/include/net/levin_protocol_handler.h index 56c53b60..e6591e32 100644 --- a/contrib/epee/include/net/levin_protocol_handler.h +++ b/contrib/epee/include/net/levin_protocol_handler.h @@ -30,8 +30,9 @@ #include "levin_base.h" #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -52,6 +53,7 @@ struct protocl_handler_config template class protocol_handler { + GULPS_CAT_MAJOR("epee_lev_proto"); public: typedef t_connection_context connection_context; typedef protocl_handler_config config_type; @@ -91,7 +93,7 @@ bool protocol_handler::handle_recv(const void *ptr, size_t { if(!m_config.m_pcommands_handler) { - LOG_ERROR_CC(m_conn_context, "Command handler not set!"); + GULPS_ERROR(m_conn_context, "Command handler not set!"); return false; } m_cach_in_buffer.append((const char *)ptr, cb); @@ -106,7 +108,7 @@ bool protocol_handler::handle_recv(const void *ptr, size_t { if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t *)m_cach_in_buffer.data()) != LEVIN_SIGNATURE) { - LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); + GULPS_ERROR(m_conn_context, "Signature mismatch on accepted connection"); return false; } is_continue = false; @@ -116,7 +118,7 @@ bool protocol_handler::handle_recv(const void *ptr, size_t bucket_head *phead = (bucket_head *)m_cach_in_buffer.data(); if(LEVIN_SIGNATURE != phead->m_signature) { - LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection"); + GULPS_ERROR(m_conn_context, "Signature mismatch on accepted connection"); return false; } m_current_head = *phead; @@ -158,7 +160,7 @@ bool protocol_handler::handle_recv(const void *ptr, size_t m_state = conn_state_reading_head; break; default: - LOG_ERROR_CC(m_conn_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); + GULPS_ERROR(m_conn_context, "Undefined state in levin_server_impl::connection_handler, m_state=", m_state); return false; } } diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index e008dc89..39dc1e8b 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -41,8 +41,9 @@ #include #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + #ifndef MIN_BYTES_WANTED #define MIN_BYTES_WANTED 512 @@ -62,6 +63,7 @@ class async_protocol_handler; template class async_protocol_handler_config { + GULPS_CAT_MAJOR("epee_lev_proto"); typedef boost::unordered_map *> connections_map; critical_section m_connects_lock; connections_map m_connects; @@ -113,6 +115,7 @@ class async_protocol_handler_config template class async_protocol_handler { + GULPS_CAT_MAJOR("epee_lev_proto"); public: typedef t_connection_context connection_context; typedef async_protocol_handler_config config_type; @@ -165,12 +168,12 @@ class async_protocol_handler { if(m_con.start_outer_call()) { - MDEBUG(con.get_context_ref() << "anvoke_handler, timeout: " << timeout); + GULPS_LOG_L1(con.get_context_ref(), " invoke_handler, timeout: ", timeout); m_timer.expires_from_now(boost::posix_time::milliseconds(timeout)); m_timer.async_wait([&con, command, cb, timeout](const boost::system::error_code &ec) { if(ec == boost::asio::error::operation_aborted) return; - MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); + GULPS_INFO(con.get_context_ref(), " Timeout on invoke operation happened, command: ", command, " timeout: ", timeout); std::string fake; cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); con.close(); @@ -234,7 +237,7 @@ class async_protocol_handler m_timer.async_wait([&con, cb, command, timeout](const boost::system::error_code &ec) { if(ec == boost::asio::error::operation_aborted) return; - MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout); + GULPS_INFO(con.get_context_ref(), " Timeout on invoke operation happened, command: ", command, " timeout: ", timeout); std::string fake; cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref()); con.close(); @@ -285,17 +288,17 @@ class async_protocol_handler { misc_utils::sleep_no_w(100); } - CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " << m_wait_count); + GULPS_CHECK_AND_ASSERT_MES_NO_RET(0 == boost::interprocess::ipcdetail::atomic_read32(&m_wait_count), "Failed to wait for operation completion. m_wait_count = " , m_wait_count); - MTRACE(m_connection_context << "~async_protocol_handler()"); + GULPS_LOG_L2(m_connection_context, "~async_protocol_handler()"); } bool start_outer_call() { - MTRACE(m_connection_context << "[levin_protocol] -->> start_outer_call"); + GULPS_LOG_L2(m_connection_context, "[levin_protocol] -->> start_outer_call"); if(!m_pservice_endpoint->add_ref()) { - MERROR(m_connection_context << "[levin_protocol] -->> start_outer_call failed"); + GULPS_ERROR(m_connection_context , " [levin_protocol] -->> start_outer_call failed"); return false; } boost::interprocess::ipcdetail::atomic_inc32(&m_wait_count); @@ -303,7 +306,7 @@ class async_protocol_handler } bool finish_outer_call() { - MTRACE(m_connection_context << "[levin_protocol] <<-- finish_outer_call"); + GULPS_LOG_L2(m_connection_context , "[levin_protocol] ,-- finish_outer_call"); boost::interprocess::ipcdetail::atomic_dec32(&m_wait_count); m_pservice_endpoint->release(); return true; @@ -359,15 +362,15 @@ class async_protocol_handler if(!m_config.m_pcommands_handler) { - MERROR(m_connection_context << "Commands handler not set!"); + GULPS_ERROR(m_connection_context , "Commands handler not set!"); return false; } if(m_cache_in_buffer.size() + cb > m_config.m_max_packet_size) { - MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet received " << m_cache_in_buffer.size() + cb - << ", connection will be closed."); + GULPS_WARN(m_connection_context , "Maximum packet size exceed!, m_max_packet_size = " , m_config.m_max_packet_size + , ", packet received " , m_cache_in_buffer.size() + cb + , ", connection will be closed."); return false; } @@ -390,7 +393,7 @@ class async_protocol_handler //async call scenario boost::shared_ptr response_handler = m_invoke_response_handlers.front(); response_handler->reset_timer(); - MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb); + GULPS_LOG_L1(m_connection_context , "LEVIN_PACKET partial msg received. len=" , cb); } } break; @@ -407,11 +410,11 @@ class async_protocol_handler bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags & LEVIN_PACKET_RESPONSE); - MDEBUG(m_connection_context << "LEVIN_PACKET_RECIEVED. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - << ", cmd = " << m_current_head.m_command - << ", v=" << m_current_head.m_protocol_version); + GULPS_LOG_L1(m_connection_context , "LEVIN_PACKET_RECIEVED. [len=" , m_current_head.m_cb + , ", flags" , m_current_head.m_flags + , ", r?=" , m_current_head.m_have_to_return_data + , ", cmd = " , m_current_head.m_command + , ", v=" , m_current_head.m_protocol_version); if(is_response) { //response to some invoke @@ -435,7 +438,7 @@ class async_protocol_handler //use sync call scenario if(!boost::interprocess::ipcdetail::atomic_read32(&m_wait_count) && !boost::interprocess::ipcdetail::atomic_read32(&m_close_called)) { - MERROR(m_connection_context << "no active invoke when response came, wtf?"); + GULPS_ERROR(m_connection_context , "no active invoke when response came, wtf?"); return false; } else @@ -469,11 +472,11 @@ class async_protocol_handler if(!m_pservice_endpoint->do_send(send_buff.data(), send_buff.size())) return false; CRITICAL_REGION_END(); - MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << m_current_head.m_cb - << ", flags" << m_current_head.m_flags - << ", r?=" << m_current_head.m_have_to_return_data - << ", cmd = " << m_current_head.m_command - << ", ver=" << m_current_head.m_protocol_version); + GULPS_LOG_L1(m_connection_context , "LEVIN_PACKET_SENT. [len=" , m_current_head.m_cb + , ", flags" , m_current_head.m_flags + , ", r?=" , m_current_head.m_have_to_return_data + , ", cmd = " , m_current_head.m_command + , ", ver=" , m_current_head.m_protocol_version); } else m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context); @@ -487,7 +490,7 @@ class async_protocol_handler { if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t *)m_cache_in_buffer.data()) != LEVIN_SIGNATURE) { - MWARNING(m_connection_context << "Signature mismatch, connection will be closed"); + GULPS_WARN(m_connection_context , "Signature mismatch, connection will be closed"); return false; } is_continue = false; @@ -497,7 +500,7 @@ class async_protocol_handler bucket_head2 *phead = (bucket_head2 *)m_cache_in_buffer.data(); if(LEVIN_SIGNATURE != phead->m_signature) { - LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed"); + GULPS_LOG_ERROR(m_connection_context, "Signature mismatch, connection will be closed"); return false; } m_current_head = *phead; @@ -507,15 +510,15 @@ class async_protocol_handler m_oponent_protocol_ver = m_current_head.m_protocol_version; if(m_current_head.m_cb > m_config.m_max_packet_size) { - LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet header received " << m_current_head.m_cb - << ", connection will be closed."); + GULPS_LOG_ERROR(m_connection_context , "Maximum packet size exceed!, m_max_packet_size = " , m_config.m_max_packet_size + , ", packet header received " , m_current_head.m_cb + , ", connection will be closed."); return false; } } break; default: - LOG_ERROR_CC(m_connection_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state); + GULPS_LOG_ERROR(m_connection_context, "Undefined state in levin_server_impl::connection_handler, m_state=", m_state); return false; } } @@ -573,14 +576,14 @@ class async_protocol_handler CRITICAL_REGION_LOCAL1(m_invoke_response_handlers_lock); if(!m_pservice_endpoint->do_send(&head, sizeof(head))) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send"); err_code = LEVIN_ERROR_CONNECTION; break; } if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send"); err_code = LEVIN_ERROR_CONNECTION; break; } @@ -630,22 +633,22 @@ class async_protocol_handler CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(&head, sizeof(head))) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send"); return LEVIN_ERROR_CONNECTION; } if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send"); return LEVIN_ERROR_CONNECTION; } CRITICAL_REGION_END(); - MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb - << ", f=" << head.m_flags - << ", r?=" << head.m_have_to_return_data - << ", cmd = " << head.m_command - << ", ver=" << head.m_protocol_version); + GULPS_LOG_L1(m_connection_context , "LEVIN_PACKET_SENT. [len=" , head.m_cb + , ", f=" , head.m_flags + , ", r?=" , head.m_have_to_return_data + , ", cmd = " , head.m_command + , ", ver=" , head.m_protocol_version); uint64_t ticks_start = misc_utils::get_tick_count(); size_t prev_size = 0; @@ -659,7 +662,7 @@ class async_protocol_handler } if(misc_utils::get_tick_count() - ticks_start > m_config.m_invoke_timeout) { - MWARNING(m_connection_context << "invoke timeout (" << m_config.m_invoke_timeout << "), closing connection "); + GULPS_WARN(m_connection_context , "invoke timeout (" , m_config.m_invoke_timeout , "), closing connection "); close(); return LEVIN_ERROR_CONNECTION_TIMEDOUT; } @@ -702,17 +705,17 @@ class async_protocol_handler CRITICAL_REGION_BEGIN(m_send_lock); if(!m_pservice_endpoint->do_send(&head, sizeof(head))) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send()"); return -1; } if(!m_pservice_endpoint->do_send(in_buff.data(), (int)in_buff.size())) { - LOG_ERROR_CC(m_connection_context, "Failed to do_send()"); + GULPS_LOG_ERROR(m_connection_context, "Failed to do_send()"); return -1; } CRITICAL_REGION_END(); - LOG_DEBUG_CC(m_connection_context, "LEVIN_PACKET_SENT. [len=" << head.m_cb << ", f=" << head.m_flags << ", r?=" << head.m_have_to_return_data << ", cmd = " << head.m_command << ", ver=" << head.m_protocol_version); + GULPS_LOG_L1(m_connection_context , "LEVIN_PACKET_SENT. [len=" , head.m_cb , ", f=" , head.m_flags , ", r?=" , head.m_have_to_return_data , ", cmd = " , head.m_command , ", ver=" , head.m_protocol_version); return 1; } @@ -758,7 +761,7 @@ void async_protocol_handler_config::delete_connections(siz } catch(const std::out_of_range &e) { - MWARNING("Connection not found in m_connects, continuing"); + GULPS_WARN("Connection not found in m_connects, continuing"); } --count; } diff --git a/contrib/epee/include/net/munin_connection_handler.h b/contrib/epee/include/net/munin_connection_handler.h index 2dd88f09..5187f378 100644 --- a/contrib/epee/include/net/munin_connection_handler.h +++ b/contrib/epee/include/net/munin_connection_handler.h @@ -47,6 +47,8 @@ #define END_MUNIN_SERVICE() } #define MUNIN_SERVICE_PARAM(munin_var_name_str, variable) paramters_text += std::string() + munin_var_name_str ".value " + boost::lexical_cast(variable) + "\n" +#include "common/gulps.hpp" + namespace epee { namespace net_utils @@ -94,6 +96,8 @@ struct fake_send_handler : public i_service_endpoint /************************************************************************/ class munin_node_server_connection_handler { + GULPS_CAT_MAJOR("epee_mun_conn"); + public: typedef node_server_config config_type; typedef connection_context_base connection_context; @@ -139,9 +143,7 @@ class munin_node_server_connection_handler const char *pbuff = (const char *)ptr; std::string recvd_buff(pbuff, cb); - LOG_PRINT("munin_recv: \n" - << recvd_buff, - LOG_LEVEL_3); + GULPS_PRINT_L3("munin_recv: \n{}", recvd_buff); m_cache += recvd_buff; @@ -169,7 +171,7 @@ class munin_node_server_connection_handler stop_handling = true; return false; default: - LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state); + GULPS_LOG_ERROR("Error in munin state machine! Unknown state=" , m_machine_state); stop_handling = true; m_machine_state = http_state_error; return false; @@ -287,9 +289,7 @@ class munin_node_server_connection_handler bool send_hook(const std::string &buff) { - LOG_PRINT("munin_send: \n" - << buff, - LOG_LEVEL_3); + GULPS_PRINT_L3("munin_send: \n{}", buff); if(m_psnd_hndlr) return m_psnd_hndlr->do_send(buff.data(), buff.size()); @@ -332,8 +332,8 @@ inline bool test_self() node_server_config sc; sc.m_services.push_back(munin_service()); sc.m_services.back().m_service_name = "test_service"; - - sc.m_services.back().m_service_config_string = + + sc.m_services.back().m_service_config_string = "graph_args --base 1000 -l 0 --vertical-label N --upper-limit 329342976\n" "graph_title REPORTS STATICTICS\n" "graph_category bind\n" @@ -358,10 +358,10 @@ inline bool test_self() sc.m_services.back().m_service_name = "test_service1"; fake_send_handler fh; munin_node_server_connection_handler mh(&fh, sc); - + std::string buff = "list\n"; mh.handle_recv(buff.data(), buff.size()); - + buff = "nodes\n"; mh.handle_recv(buff.data(), buff.size()); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index c42cdd32..b899e942 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -39,8 +39,9 @@ #include #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + #ifndef MAKE_IP #define MAKE_IP(a1, a2, a3, a4) (a1 | (a2 << 8) | (a3 << 16) | (a4 << 24)) @@ -129,7 +130,7 @@ class blocked_mode_client boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) { - LOG_ERROR("Failed to resolve " << addr); + GULPSF_LOG_ERROR("Failed to resolve {}", addr); return false; } @@ -172,18 +173,18 @@ class blocked_mode_client } else { - MWARNING("Some problems at connect, message: " << ec.message()); + GULPSF_LOG_L1("Some problems at connect, message: {}", ec.message()); return false; } } catch(const boost::system::system_error &er) { - MDEBUG("Some problems at connect, message: " << er.what()); + GULPSF_LOG_L1("Some problems at connect, message: {}", er.what()); return false; } catch(...) { - MDEBUG("Some fatal problems."); + GULPS_LOG_L1("Some fatal problems."); return false; } @@ -205,12 +206,12 @@ class blocked_mode_client catch(const boost::system::system_error & /*er*/) { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); + //GULPSF_LOG_ERROR("Some problems at disconnect, message: {}", er.what()); return false; } catch(...) { - //LOG_ERROR("Some fatal problems."); + //GULPS_LOG_ERROR("Some fatal problems."); return false; } return true; @@ -244,7 +245,7 @@ class blocked_mode_client if(ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPSF_LOG_L3("Problems at write: {}", ec.message()); m_connected = false; return false; } @@ -256,12 +257,12 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at connect, message: " << er.what()); + GULPSF_LOG_ERROR("Some problems at connect, message: {}", er.what()); return false; } catch(...) { - LOG_ERROR("Some fatal problems."); + GULPS_LOG_ERROR("Some fatal problems."); return false; } @@ -300,7 +301,7 @@ class blocked_mode_client if(!writen || ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPSF_LOG_L3("Problems at write: {}", ec.message()); m_connected = false; return false; } @@ -312,13 +313,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at send, message: " << er.what()); + GULPSF_LOG_ERROR("Some problems at send, message: {}", er.what()); m_connected = false; return false; } catch(...) { - LOG_ERROR("Some fatal problems."); + GULPS_LOG_ERROR("Some fatal problems."); return false; } @@ -369,21 +370,21 @@ class blocked_mode_client if(ec) { - MTRACE("READ ENDS: Connection err_code " << ec.value()); + GULPSF_LOG_L2("READ ENDS: Connection err_code {}", ec.value()); if(ec == boost::asio::error::eof) { - MTRACE("Connection err_code eof."); + GULPS_LOG_L2("Connection err_code eof."); //connection closed there, empty return true; } - MDEBUG("Problems at read: " << ec.message()); + GULPSF_LOG_L1("Problems at read: {}", ec.message()); m_connected = false; return false; } else { - MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered); + GULPSF_LOG_L2("READ ENDS: Success. bytes_tr: {}", bytes_transfered); m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } @@ -396,13 +397,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at read, message: " << er.what()); + GULPSF_LOG_ERROR("Some problems at read, message: {}", er.what()); m_connected = false; return false; } catch(...) { - LOG_ERROR("Some fatal problems at read."); + GULPS_LOG_ERROR("Some fatal problems at read."); return false; } @@ -446,7 +447,7 @@ class blocked_mode_client if(ec) { - LOG_PRINT_L3("Problems at read: " << ec.message()); + GULPSF_LOG_L3("Problems at read: {}", ec.message()); m_connected = false; return false; } @@ -457,7 +458,7 @@ class blocked_mode_client if(bytes_transfered != buff.size()) { - LOG_ERROR("Transferred mismatch with transfer_at_least value: m_bytes_transferred=" << bytes_transfered << " at_least value=" << buff.size()); + GULPSF_LOG_ERROR("Transferred mismatch with transfer_at_least value: m_bytes_transferred={} at_least value={}", bytes_transfered , buff.size()); return false; } @@ -466,13 +467,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at read, message: " << er.what()); + GULPSF_LOG_ERROR("Some problems at read, message: {}", er.what()); m_connected = false; return false; } catch(...) { - LOG_ERROR("Some fatal problems at read."); + GULPS_LOG_ERROR("Some fatal problems at read."); return false; } @@ -487,13 +488,13 @@ class blocked_mode_client shutdown_ssl(); m_ssl_socket.next_layer().cancel(ec); if(ec) - MDEBUG("Problems at cancel: " << ec.message()); + GULPSF_LOG_L1("Problems at cancel: {}", ec.message()); m_ssl_socket.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); if(ec) - MDEBUG("Problems at shutdown: " << ec.message()); + GULPSF_LOG_L1("Problems at shutdown: {}", ec.message()); m_ssl_socket.next_layer().close(ec); if(ec) - MDEBUG("Problems at close: " << ec.message()); + GULPSF_LOG_L1("Problems at close: {}", ec.message()); boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); m_connected = false; return true; @@ -524,7 +525,7 @@ class blocked_mode_client // The deadline has passed. The socket is closed so that any outstanding // asynchronous operations are cancelled. This allows the blocked // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); + GULPS_LOG_L3("Timed out socket"); m_connected = false; m_ssl_socket.next_layer().close(); @@ -556,7 +557,7 @@ class blocked_mode_client ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) #endif ) - MDEBUG("Problems at ssl shutdown: " << ec.message()); + GULPSF_LOG_L1("Problems at ssl shutdown: {}", ec.message()); } protected: @@ -658,7 +659,7 @@ class async_blocked_mode_client : public blocked_mode_client if(!writen || ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPSF_LOG_L3("Problems at write: {}", ec.message()); return false; } else @@ -669,12 +670,12 @@ class async_blocked_mode_client : public blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at connect, message: " << er.what()); + GULPSF_LOG_ERROR("Some problems at connect, message: {}", er.what()); return false; } catch(...) { - LOG_ERROR("Some fatal problems."); + GULPS_LOG_ERROR("Some fatal problems."); return false; } @@ -694,7 +695,7 @@ class async_blocked_mode_client : public blocked_mode_client // The deadline has passed. The socket is closed so that any outstanding // asynchronous operations are cancelled. This allows the blocked // connect(), read_line() or write_line() functions to return. - LOG_PRINT_L3("Timed out socket"); + GULPS_LOG_L3("Timed out socket"); m_ssl_socket.next_layer().close(); // There is no longer an active deadline. The expiry is set to positive diff --git a/contrib/epee/include/net/net_parse_helpers.h b/contrib/epee/include/net/net_parse_helpers.h index 70a1c7b2..7045e38f 100644 --- a/contrib/epee/include/net/net_parse_helpers.h +++ b/contrib/epee/include/net/net_parse_helpers.h @@ -28,8 +28,9 @@ #include "http_base.h" #include "reg_exp_definer.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -72,7 +73,8 @@ inline bool parse_uri_query(const std::string &query, std::list #include #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" #ifndef MAKE_IP #define MAKE_IP(a1, a2, a3, a4) (a1 | (a2 << 8) | (a3 << 16) | (a4 << 24)) @@ -45,6 +43,9 @@ namespace epee { namespace net_utils { + +GULPS_CAT_MAJOR("epee_net"); + class ipv4_network_address { uint32_t m_ip; @@ -71,7 +72,7 @@ class ipv4_network_address static constexpr uint8_t get_type_id() noexcept { return ID; } static const uint8_t ID = 1; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(ipv4_network_address) KV_SERIALIZE(m_ip) KV_SERIALIZE(m_port) END_KV_SERIALIZE_MAP() @@ -155,7 +156,7 @@ class network_address virtual uint8_t get_type_id() const override { return value.get_type_id(); } }; - std::shared_ptr self; + std::shared_ptr self = nullptr; template Type &as_mutable() const @@ -169,7 +170,6 @@ class network_address } public: - network_address() : self(nullptr) {} template network_address(const T &src) : self(std::make_shared>(src)) {} @@ -184,7 +184,7 @@ class network_address template const Type &as() const { return as_mutable(); } - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(network_address) uint8_t type = is_store ? this_ref.get_type_id() : 0; if(!epee::serialization::selector::serialize(type, stg, hparent_section, "type")) return false; @@ -197,14 +197,14 @@ class network_address const_cast(this_ref) = ipv4_network_address{0, 0}; auto &addr = this_ref.template as_mutable(); if(epee::serialization::selector::serialize(addr, stg, hparent_section, "addr")) - MDEBUG("Found as addr: " << this_ref.str()); + GULPSF_LOG_L1("Found as addr: {}", this_ref.str()); else if(epee::serialization::selector::serialize(addr, stg, hparent_section, "template as()")) - MDEBUG("Found as template as(): " << this_ref.str()); + GULPSF_LOG_L1("Found as template as(): {}", this_ref.str()); else if(epee::serialization::selector::serialize(addr, stg, hparent_section, "template as_mutable()")) - MDEBUG("Found as template as_mutable(): " << this_ref.str()); + GULPSF_LOG_L1("Found as template as_mutable(): {}", this_ref.str()); else { - MWARNING("Address not found"); + GULPS_WARN("Address not found"); return false; } } @@ -217,7 +217,7 @@ class network_address break; } default: - MERROR("Unsupported network address type: " << (unsigned)type); + GULPS_ERROR("Unsupported network address type: ", (unsigned)type); return false; } END_KV_SERIALIZE_MAP() @@ -334,33 +334,18 @@ struct i_service_endpoint std::string print_connection_context(const connection_context_base &ctx); std::string print_connection_context_short(const connection_context_base &ctx); -inline MAKE_LOGGABLE(connection_context_base, ct, os) +inline std::ostream &operator<<(std::ostream &os, const connection_context_base &ct) { - os << "[" << epee::net_utils::print_connection_context_short(ct) << "] "; + os << "[" << epee::net_utils::print_connection_context_short(ct).c_str() << "] "; return os; } -#define LOG_ERROR_CC(ct, message) MERROR(ct << message) -#define LOG_WARNING_CC(ct, message) MWARNING(ct << message) -#define LOG_INFO_CC(ct, message) MINFO(ct << message) -#define LOG_DEBUG_CC(ct, message) MDEBUG(ct << message) -#define LOG_TRACE_CC(ct, message) MTRACE(ct << message) -#define LOG_CC(level, ct, message) MLOG(level, ct << message) - -#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(ct << message) -#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(ct << message) -#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(ct << message) -#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(ct << message) -#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(ct << message) - -#define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message) -#define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message) -#define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message) -#define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message) -#define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message) - -#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message) } } +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif #endif //_NET_UTILS_BASE_H_ diff --git a/contrib/epee/include/net/network_throttle-detail.hpp b/contrib/epee/include/net/network_throttle-detail.hpp index 10b8bf11..5731e0c2 100644 --- a/contrib/epee/include/net/network_throttle-detail.hpp +++ b/contrib/epee/include/net/network_throttle-detail.hpp @@ -44,6 +44,7 @@ namespace net_utils class network_throttle : public i_network_throttle { + GULPS_CAT_MAJOR("epee_net_tht_det"); private: struct packet_info { diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp index 71dfbea4..299e8e0e 100644 --- a/contrib/epee/include/net/network_throttle.hpp +++ b/contrib/epee/include/net/network_throttle.hpp @@ -54,7 +54,7 @@ #include "syncobj.h" #include "misc_language.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include "net/net_utils_base.h" #include "pragma_comp_defs.h" #include diff --git a/contrib/epee/include/net/protocol_switcher.h b/contrib/epee/include/net/protocol_switcher.h index f8a46d24..65cf3279 100644 --- a/contrib/epee/include/net/protocol_switcher.h +++ b/contrib/epee/include/net/protocol_switcher.h @@ -109,7 +109,7 @@ bool protocol_switcher::handle_recv(const void *ptr, size_t cb) } else { - LOG_ERROR("Wrong protocol accepted on port..."); + GULPS_ERROR("Wrong protocol accepted on port..."); return false; } } diff --git a/contrib/epee/include/net/smtp.h b/contrib/epee/include/net/smtp.h index 7f396a31..995557bd 100644 --- a/contrib/epee/include/net/smtp.h +++ b/contrib/epee/include/net/smtp.h @@ -43,6 +43,8 @@ namespace net_utils namespace smtp { +GULPS_CAT_MAJOR("epee_smtp"); + using boost::asio::ip::tcp; using namespace boost::archive::iterators; typedef base64_from_binary> base64_text; diff --git a/contrib/epee/include/net/smtp_helper.h b/contrib/epee/include/net/smtp_helper.h index 58c52140..45f8da2c 100644 --- a/contrib/epee/include/net/smtp_helper.h +++ b/contrib/epee/include/net/smtp_helper.h @@ -24,6 +24,8 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include "common/gulps.hpp" + #pragma once #include "smtp.h" @@ -40,7 +42,7 @@ inline bool send_mail(const std::string &server, int port, const std::string &lo if(!smtp.ServerConnect(server.c_str(), port)) { - LOG_PRINT("Reporting: Failed to connect to server " << server << ":" << port, LOG_LEVEL_0); + GULPSF_PRINT("Reporting: Failed to connect to server {}:{}", server , port); return false; } @@ -48,7 +50,7 @@ inline bool send_mail(const std::string &server, int port, const std::string &lo { if(!smtp.ServerLogin(login.c_str(), pass.c_str())) { - LOG_PRINT("Reporting: Failed to auth on server " << server << ":" << port, LOG_LEVEL_0); + GULPSF_PRINT("Reporting: Failed to auth on server {}:", server ); return false; } } @@ -64,11 +66,11 @@ inline bool send_mail(const std::string &server, int port, const std::string &lo char *szErrorText = smtp.GetLastErrorText(); if(szErrorText) { - LOG_PRINT("Failed to send message, error text: " << szErrorText, LOG_LEVEL_0); + GULPSF_PRINT("Failed to send message, error text: {}", szErrorText); } else { - LOG_PRINT("Failed to send message, error text: null", LOG_LEVEL_0); + GULPS_PRINT("Failed to send message, error text: null"); } return false; } diff --git a/contrib/epee/include/profile_tools.h b/contrib/epee/include/profile_tools.h index 4a41755b..22b1076a 100644 --- a/contrib/epee/include/profile_tools.h +++ b/contrib/epee/include/profile_tools.h @@ -29,6 +29,8 @@ #include "misc_os_dependent.h" +#include "common/gulps.hpp" + namespace epee { @@ -57,15 +59,17 @@ namespace epee #define START_WAY_POINTS() uint64_t _____way_point_time = epee::misc_utils::get_tick_count(); #define WAY_POINT(name) \ { \ + GULPS_CAT_MAJOR("epee_prof_tools"); \ uint64_t delta = epee::misc_utils::get_tick_count() - _____way_point_time; \ - MDEBUG("Way point " << name << ": " << delta); \ + GULPSF_LOG_L1("Way point {}: {}", name, delta); \ _____way_point_time = misc_utils::get_tick_count(); \ } #define WAY_POINT2(name, avrg_obj) \ { \ uint64_t delta = epee::misc_utils::get_tick_count() - _____way_point_time; \ avrg_obj.push(delta); \ - MDEBUG("Way point " << name << ": " << delta); \ + GULPS_CAT_MAJOR("epee_prof_tools"); \ + GULPSF_LOG_L1("Way point {}: {}", name, delta); \ _____way_point_time = misc_utils::get_tick_count(); \ } @@ -88,7 +92,8 @@ struct local_call_account } ~local_call_account() { - MINFO("PROFILE " << m_pname << ":av_time:\t" << (m_count_of_call ? (m_summary_time_used / m_count_of_call) : 0) << " sum_time:\t" << m_summary_time_used << " call_count:\t" << m_count_of_call); + GULPS_CAT_MAJOR("epee_prof_tools"); + GULPSF_INFO("PROFILE {}:av_time:\t{} sum_time:\t{} call_count:\t{}", m_pname , (m_count_of_call ? (m_summary_time_used / m_count_of_call) : 0) , m_summary_time_used , m_count_of_call); } size_t m_count_of_call; diff --git a/contrib/epee/include/readline_buffer.h b/contrib/epee/include/readline_buffer.h index 93e4d6d2..e935881b 100644 --- a/contrib/epee/include/readline_buffer.h +++ b/contrib/epee/include/readline_buffer.h @@ -1,5 +1,7 @@ #pragma once +#ifdef HAVE_READLINE + #include #include #include @@ -43,3 +45,11 @@ class suspend_readline bool m_restart; }; } + +#define PAUSE_READLINE() rdln::suspend_readline pause_readline; + +#else + +#define PAUSE_READLINE() + +#endif diff --git a/contrib/epee/include/reg_utils.h b/contrib/epee/include/reg_utils.h index a41487e1..08070d72 100644 --- a/contrib/epee/include/reg_utils.h +++ b/contrib/epee/include/reg_utils.h @@ -227,13 +227,13 @@ inline bool RegGetRAWValue(HKEY hParentKey, const char *pSubKey, const char *pVa //----------------------------------------------------------------------------------------------------------------------------------- inline bool RegRemoveValue(HKEY hParentKey, const char *pValName) { - //CHECK_AND_ASSERT(hParentKey&&pValName, false); + //GULPS_CHECK_AND_ASSERT(hParentKey&&pValName, false); return ::RegDeleteValueA(hParentKey, pValName) == ERROR_SUCCESS ? true : false; } //----------------------------------------------------------------------------------------------------------------------------------- inline bool RegRemoveKey(HKEY hParentKey, const char *pKeyName) { - //CHECK_AND_ASSERT(hParentKey&&pKeyName, false); + //GULPS_CHECK_AND_ASSERT(hParentKey&&pKeyName, false); return ::RegDeleteKeyA(hParentKey, pKeyName) == ERROR_SUCCESS ? true : false; } } diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index 9c93722b..04f0e6cb 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -28,17 +28,26 @@ #include "enableable.h" #include "keyvalue_serialization_overloads.h" -#include "misc_log_ex.h" #include #include +#include "common/gulps.hpp" + namespace epee { /************************************************************************/ /* Serialize map declarations */ /************************************************************************/ -#define BEGIN_KV_SERIALIZE_MAP() \ +#define BEGIN_KV_SERIALIZE_MAP(class_name) \ + private: \ + class epee_zero{}; \ + class_name(const epee_zero){} \ public: \ + class_name() \ + { \ + static typename std::remove_pointer::type set_zero(epee_zero{}); \ + *this = set_zero; \ + } \ template \ bool store(t_storage &st, typename t_storage::hsection hparent_section = nullptr) const \ { \ @@ -59,7 +68,7 @@ namespace epee catch(const std::exception &err) \ { \ (void)(err); \ - LOG_ERROR("Exception on unserializing: " << err.what()); \ + GULPS_CAT2_ERROR("kv_ser","","Exception on unserializing: {}", err.what()); \ return false; \ } \ } \ diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 8e367f97..c9f1ea01 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -32,12 +32,13 @@ #include #include #include -#include "misc_log_ex.h" +#include "common/gulps.hpp" namespace epee { namespace serialization { +GULPS_CAT_MAJOR("epee_kv_ser"); //------------------------------------------------------------------------------------------------------------------- template @@ -65,7 +66,7 @@ static bool unserialize_t_val_as_blob(t_type &d, t_storage &stg, typename t_stor std::string blob; if(!stg.get_value(pname, blob, hparent_section)) return false; - CHECK_AND_ASSERT_MES(blob.size() == sizeof(d), false, "unserialize_t_val_as_blob: size of " << typeid(t_type).name() << " = " << sizeof(t_type) << ", but stored blod size = " << blob.size() << ", value name = " << pname); + GULPS_CHECK_AND_ASSERT_MES(blob.size() == sizeof(d), false, "unserialize_t_val_as_blob: size of " , typeid(t_type).name() , " = " , sizeof(t_type) , ", but stored blod size = " , blob.size() , ", value name = " , pname); d = *(const t_type *)blob.data(); return true; } @@ -74,7 +75,7 @@ template static bool serialize_t_obj(const serializible_type &obj, t_storage &stg, typename t_storage::hsection hparent_section, const char *pname) { typename t_storage::hsection hchild_section = stg.open_section(pname, hparent_section, true); - CHECK_AND_ASSERT_MES(hchild_section, false, "serialize_t_obj: failed to open/create section " << pname); + GULPS_CHECK_AND_ASSERT_MES(hchild_section, false, "serialize_t_obj: failed to open/create section " , pname); return obj.store(stg, hchild_section); } //------------------------------------------------------------------------------------------------------------------- @@ -113,7 +114,7 @@ static bool serialize_stl_container_t_val(const stl_container &container, t_stor return true; typename stl_container::const_iterator it = container.begin(); typename t_storage::harray hval_array = stg.insert_first_value(pname, *it, hparent_section); - CHECK_AND_ASSERT_MES(hval_array, false, "failed to insert first value to storage"); + GULPS_CHECK_AND_ASSERT_MES(hval_array, false, "failed to insert first value to storage"); it++; for(; it != container.end(); it++) stg.insert_next_value(hval_array, *it); @@ -160,9 +161,9 @@ static bool unserialize_stl_container_pod_val_as_blob(stl_container &container, { size_t loaded_size = buff.size(); typename stl_container::value_type *pelem = (typename stl_container::value_type *)buff.data(); - CHECK_AND_ASSERT_MES(!(loaded_size % sizeof(typename stl_container::value_type)), + GULPS_CHECK_AND_ASSERT_MES(!(loaded_size % sizeof(typename stl_container::value_type)), false, - "size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type)); + "size in blob " , loaded_size , " not have not zero modulo for sizeof(value_type) = " , sizeof(typename stl_container::value_type)); size_t count = (loaded_size / sizeof(typename stl_container::value_type)); for(size_t i = 0; i < count; i++) container.insert(container.end(), *(pelem++)); @@ -179,7 +180,7 @@ static bool serialize_stl_container_t_obj(const stl_container &container, t_stor typename stl_container::const_iterator it = container.begin(); typename t_storage::hsection hchild_section = nullptr; typename t_storage::harray hsec_array = stg.insert_first_section(pname, hchild_section, hparent_section); - CHECK_AND_ASSERT_MES(hsec_array && hchild_section, false, "failed to insert first section with section name " << pname); + GULPS_CHECK_AND_ASSERT_MES(hsec_array && hchild_section, false, "failed to insert first section with section name " , pname); res = it->store(stg, hchild_section); it++; for(; it != container.end(); it++) diff --git a/contrib/epee/include/service_impl_base.h b/contrib/epee/include/service_impl_base.h index a21da6a9..1cd117c2 100644 --- a/contrib/epee/include/service_impl_base.h +++ b/contrib/epee/include/service_impl_base.h @@ -29,10 +29,13 @@ #pragma comment(lib, "advapi32.lib") +#include "common/gulps.hpp" + namespace epee { class service_impl_base { + GULPS_CAT_MAJOR("epee_srv_imp_base"); public: service_impl_base(); virtual ~service_impl_base(); @@ -101,7 +104,7 @@ inline service_impl_base *&service_impl_base::instance() //----------------------------------------------------------------------------- inline bool service_impl_base::install() { - CHECK_AND_ASSERT(!m_service, false); + GULPS_CHECK_AND_ASSERT(!m_service, false); const char *psz_descr = get_description(); SERVICE_FAILURE_ACTIONSA *fail_acts = get_failure_actions(); @@ -117,9 +120,7 @@ inline bool service_impl_base::install() if(!m_manager) { int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to OpenSCManager(), last err={}", log_space::get_win32_err_descr(err)); break; } } @@ -129,9 +130,7 @@ inline bool service_impl_base::install() if(!m_service) { int err = GetLastError(); - LOG_ERROR( - "Failed to CreateService(), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to CreateService(), last err={}", log_space::get_win32_err_descr(err)); break; } @@ -142,9 +141,7 @@ inline bool service_impl_base::install() &sd)) { int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err={}", log_space::get_win32_err_descr(err)); break; } } @@ -155,22 +152,20 @@ inline bool service_impl_base::install() fail_acts)) { int err = GetLastError(); - LOG_ERROR( - "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err={}", log_space::get_win32_err_descr(err)); break; } } - LOG_PRINT("Installed succesfully.", LOG_LEVEL_0); + GULPS_PRINT("Installed succesfully."); return true; } - LOG_PRINT("Failed to install.", LOG_LEVEL_0); + GULPS_PRINT("Failed to install."); return false; } //----------------------------------------------------------------------------- inline bool service_impl_base::remove() { - CHECK_AND_ASSERT(!m_service, false); + GULPS_CHECK_AND_ASSERT(!m_service, false); while(TRUE) { @@ -180,9 +175,7 @@ inline bool service_impl_base::remove() if(!m_manager) { int err = GetLastError(); - LOG_ERROR( - "Failed to OpenSCManager(), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to OpenSCManager(), last err={}", log_space::get_win32_err_descr(err)); break; } } @@ -193,9 +186,7 @@ inline bool service_impl_base::remove() if(!m_service) { int err = GetLastError(); - LOG_ERROR( - "Failed to OpenService(), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to OpenService(), last err={}", log_space::get_win32_err_descr(err)); break; } } @@ -208,9 +199,7 @@ inline bool service_impl_base::remove() continue; else if(err != ERROR_SERVICE_NOT_ACTIVE) { - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to ControlService(SERVICE_CONTROL_STOP), last err={}", log_space::get_win32_err_descr(err)); break; } } @@ -218,13 +207,11 @@ inline bool service_impl_base::remove() if(!::DeleteService(m_service)) { int err = ::GetLastError(); - LOG_ERROR( - "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" - << log_space::get_win32_err_descr(err)); + GULPSF_LOG_ERROR("Failed to ControlService(SERVICE_CONTROL_STOP), last err={}", log_space::get_win32_err_descr(err)); break; } - LOG_PRINT("Removed successfully.", LOG_LEVEL_0); + GULPS_PRINT("Removed successfully."); break; } @@ -238,7 +225,7 @@ inline bool service_impl_base::init() //----------------------------------------------------------------------------- inline bool service_impl_base::run_service() { - CHECK_AND_ASSERT(!m_service, false); + GULPS_CHECK_AND_ASSERT(!m_service, false); long error_code = 0; @@ -248,24 +235,19 @@ inline bool service_impl_base::run_service() service_table->lpServiceName = (char *)get_name(); service_table->lpServiceProc = service_entry; - LOG_PRINT("[+] Start service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); + GULPS_LOG_L1("[+] Start service control dispatcher for \"{}\"", get_name()); error_code = 1; BOOL res = ::StartServiceCtrlDispatcherA(service_table); if(!res) { int err = GetLastError(); - LOG_PRINT( - "[+] Error starting service control dispatcher, err=" - << log_space::get_win32_err_descr(err), - LOG_LEVEL_1); + GULPS_LOG_L1("[+] Error starting service control dispatcher, err={}", log_space::get_win32_err_descr(err)); return false; } else { - LOG_PRINT("[+] End service control dispatcher for \"" << get_name() << "\"", - LOG_LEVEL_1); + GULPS_LOG_L1("[+] End service control dispatcher for \"{}\"", get_name()); } return true; } @@ -273,7 +255,7 @@ inline bool service_impl_base::run_service() inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, DWORD event, void *pdata, void *pcontext) { - CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); + GULPS_CHECK_AND_ASSERT(pcontext, ERROR_CALL_NOT_IMPLEMENTED); service_impl_base *pservice = (service_impl_base *)pcontext; return pservice->service_handler(control, event, pdata); @@ -282,10 +264,10 @@ inline DWORD __stdcall service_impl_base::_service_handler(DWORD control, inline void __stdcall service_impl_base::service_entry(DWORD argc, char **pargs) { service_impl_base *pme = instance(); - LOG_PRINT("instance: " << pme, LOG_LEVEL_4); + GULPS_LOG_L3("instance: "); if(!pme) { - LOG_ERROR("Error: at service_entry() pme = NULL"); + GULPS_LOG_ERROR("Error: at service_entry() pme = NULL"); return; } pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(), diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h index 1bd85c43..1593a436 100644 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -33,6 +33,8 @@ #include #include +#include "common/gulps.hpp" + namespace epee { namespace net_utils @@ -40,6 +42,7 @@ namespace net_utils template bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "GET") { + GULPS_CAT_MAJOR("epee_h_abs_inv"); std::string req_param; if(!serialization::store_t_to_json(out_struct, req_param)) return false; @@ -50,19 +53,20 @@ bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, const http::http_response_info *pri = NULL; if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri), std::move(additional_params))) { - LOG_PRINT_L1("Failed to invoke http request to " << uri); + GULPS_LOG_L1("Failed to invoke http request to ", uri); return false; } if(!pri) { - LOG_PRINT_L1("Failed to invoke http request to " << uri << ", internal error (null response ptr)"); + GULPS_LOG_L1("Failed to invoke http request to ", uri, " internal error (null response ptr)"); return false; } if(pri->m_response_code != 200) { - LOG_PRINT_L1("Failed to invoke http request to " << uri << ", wrong response code: " << pri->m_response_code); + //GULPSF_LOG_L1("Failed to invoke http request to {}, wrong response code: {}", uri , pri->m_response_code); + GULPS_LOG_L1("Failed to invoke http request to ", uri, " wrong response code: ", pri->m_response_code); return false; } @@ -72,6 +76,7 @@ bool invoke_http_json(const boost::string_ref uri, const t_request &out_struct, template bool invoke_http_bin(const boost::string_ref uri, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "GET") { + GULPS_CAT_MAJOR("epee_h_abs_inv"); std::string req_param; if(!serialization::store_t_to_binary(out_struct, req_param)) return false; @@ -79,19 +84,19 @@ bool invoke_http_bin(const boost::string_ref uri, const t_request &out_struct, t const http::http_response_info *pri = NULL; if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri))) { - LOG_PRINT_L1("Failed to invoke http request to " << uri); + GULPS_LOG_L1("Failed to invoke http request to ", uri); return false; } if(!pri) { - LOG_PRINT_L1("Failed to invoke http request to " << uri << ", internal error (null response ptr)"); + GULPS_LOG_L1("Failed to invoke http request to ", uri, " internal error (null response ptr)"); return false; } if(pri->m_response_code != 200) { - LOG_PRINT_L1("Failed to invoke http request to " << uri << ", wrong response code: " << pri->m_response_code); + GULPS_LOG_L1("Failed to invoke http request to ", uri, " wrong response code: ", pri->m_response_code); return false; } @@ -101,6 +106,7 @@ bool invoke_http_bin(const boost::string_ref uri, const t_request &out_struct, t template bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request &out_struct, t_response &result_struct, t_transport &transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "GET", const std::string &req_id = "0") { + GULPS_CAT_MAJOR("epee_h_abs_inv"); epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); req_t.jsonrpc = "2.0"; req_t.id = req_id; @@ -113,7 +119,7 @@ bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, } if(resp_t.error.code || resp_t.error.message.size()) { - LOG_ERROR("RPC call of \"" << req_t.method << "\" returned error: " << resp_t.error.code << ", message: " << resp_t.error.message); + GULPSF_LOG_ERROR("RPC call of \"{}\" returned error: {}, message: {}", req_t.method, resp_t.error.code, resp_t.error.message); return false; } result_struct = resp_t.result; diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h index abee8913..9ae6f49f 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -30,8 +30,9 @@ #include "portable_storage_template_helper.h" #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -49,15 +50,16 @@ bool invoke_remote_command2(int command, const t_arg &out_struct, t_result &resu stg.store_to_binary(buff_to_send); int res = transport.invoke(command, buff_to_send, buff_to_recv); + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); if(res <= 0) { - MERROR("Failed to invoke command " << command << " return code " << res); + GULPSF_LOG_ERROR("Failed to invoke command {} return code {}", command , res); return false; } serialization::portable_storage stg_ret; if(!stg_ret.load_from_binary(buff_to_recv)) { - LOG_ERROR("Failed to load_from_binary on command " << command); + GULPSF_LOG_ERROR("Failed to load_from_binary on command {}", command); return false; } return result_struct.load(stg_ret); @@ -77,7 +79,8 @@ bool notify_remote_command2(int command, const t_arg &out_struct, t_transport &t int res = transport.notify(command, buff_to_send); if(res <= 0) { - LOG_ERROR("Failed to notify command " << command << " return code " << res); + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); + GULPSF_LOG_ERROR("Failed to notify command {} return code {}", command , res); return false; } return true; @@ -86,7 +89,7 @@ bool notify_remote_command2(int command, const t_arg &out_struct, t_transport &t template bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg &out_struct, t_result &result_struct, t_transport &transport) { - + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); typename serialization::portable_storage stg; out_struct.store(stg); std::string buff_to_send, buff_to_recv; @@ -95,13 +98,13 @@ bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id); if(res <= 0) { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + GULPSF_LOG_L1("Failed to invoke command {} return code {}", command , res); return false; } typename serialization::portable_storage stg_ret; if(!stg_ret.load_from_binary(buff_to_recv)) { - LOG_ERROR("Failed to load_from_binary on command " << command); + GULPSF_LOG_ERROR("Failed to load_from_binary on command {}", command); return false; } return result_struct.load(stg_ret); @@ -110,6 +113,7 @@ bool invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg template bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg &out_struct, t_transport &transport, const callback_t &cb, size_t inv_timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) { + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); typename serialization::portable_storage stg; const_cast(out_struct).store(stg); //TODO: add true const support to searilzation std::string buff_to_send; @@ -118,20 +122,20 @@ bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const t_result result_struct = AUTO_VAL_INIT(result_struct); if(code <= 0) { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code); + GULPSF_LOG_L1("Failed to invoke command {} return code {}", command , code); cb(code, result_struct, context); return false; } serialization::portable_storage stg_ret; if(!stg_ret.load_from_binary(buff)) { - LOG_ERROR("Failed to load_from_binary on command " << command); + GULPSF_LOG_ERROR("Failed to load_from_binary on command {}", command); cb(LEVIN_ERROR_FORMAT, result_struct, context); return false; } if(!result_struct.load(stg_ret)) { - LOG_ERROR("Failed to load result struct on command " << command); + GULPSF_LOG_ERROR("Failed to load result struct on command {}", command); cb(LEVIN_ERROR_FORMAT, result_struct, context); return false; } @@ -141,7 +145,7 @@ bool async_invoke_remote_command2(boost::uuids::uuid conn_id, int command, const inv_timeout); if(res <= 0) { - LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res); + GULPSF_LOG_L1("Failed to invoke command {} return code {}", command , res); return false; } return true; @@ -159,7 +163,8 @@ bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg int res = transport.notify(command, buff_to_send, conn_id); if(res <= 0) { - MERROR("Failed to notify command " << command << " return code " << res); + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); + GULPSF_LOG_ERROR("Failed to notify command {} return code {}", command , res); return false; } return true; @@ -169,10 +174,11 @@ bool notify_remote_command2(boost::uuids::uuid conn_id, int command, const t_arg template int buff_to_t_adapter(int command, const std::string &in_buff, std::string &buff_out, callback_t cb, t_context &context) { + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) { - LOG_ERROR("Failed to load_from_binary in command " << command); + GULPSF_LOG_ERROR("Failed to load_from_binary in command {}", command); return -1; } boost::value_initialized in_struct; @@ -180,7 +186,7 @@ int buff_to_t_adapter(int command, const std::string &in_buff, std::string &buff if(!static_cast(in_struct).load(strg)) { - LOG_ERROR("Failed to load in_struct in command " << command); + GULPSF_LOG_ERROR("Failed to load in_struct in command {}", command); return -1; } int res = cb(command, static_cast(in_struct), static_cast(out_struct), context); @@ -189,7 +195,7 @@ int buff_to_t_adapter(int command, const std::string &in_buff, std::string &buff if(!strg_out.store_to_binary(buff_out)) { - LOG_ERROR("Failed to store_to_binary in command" << command); + GULPSF_LOG_ERROR("Failed to store_to_binary in command{}", command); return -1; } @@ -199,16 +205,17 @@ int buff_to_t_adapter(int command, const std::string &in_buff, std::string &buff template int buff_to_t_adapter(t_owner *powner, int command, const std::string &in_buff, callback_t cb, t_context &context) { + GULPS_CAT_MAJOR("epee_lev_abs_inv2"); serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) { - LOG_ERROR("Failed to load_from_binary in notify " << command); + GULPSF_LOG_ERROR("Failed to load_from_binary in notify {}", command); return -1; } boost::value_initialized in_struct; if(!static_cast(in_struct).load(strg)) { - LOG_ERROR("Failed to load in_struct in notify " << command); + GULPSF_LOG_ERROR("Failed to load in_struct in notify {}", command); return -1; } return cb(command, in_struct, context); @@ -306,7 +313,7 @@ int buff_to_t_adapter(t_owner *powner, int command, const std::string &in_buff, } #define END_INVOKE_MAP2() \ - LOG_ERROR("Unknown command:" << command); \ + {GULPS_CAT_MAJOR("epee_lev_abs_inv2"); GULPSF_LOG_ERROR("Unknown command:{}", command);} \ return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \ } } diff --git a/contrib/epee/include/storages/parserse_base_utils.h b/contrib/epee/include/storages/parserse_base_utils.h index f1f6cfef..cdb3515c 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -26,6 +26,9 @@ #pragma once +#include "common/gulps.hpp" + + namespace epee { namespace misc_utils @@ -76,7 +79,7 @@ inline std::string transform_to_escape_sequence(const std::string &src) return res; } /* - + \b Backspace (ascii code 08) \f Form feed (ascii code 0C) \n New line @@ -94,6 +97,7 @@ inline void match_string2(std::string::const_iterator &star_end_string, std::str bool escape_mode = false; std::string::const_iterator it = star_end_string; ++it; + GULPS_CAT_MAJOR("epee_pars_bs_utls"); for(; it != buf_end; it++) { if(escape_mode /*prev_ch == '\\'*/) @@ -132,7 +136,7 @@ inline void match_string2(std::string::const_iterator &star_end_string, std::str break; default: val.push_back(*it); - LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\""); + GULPSF_PRINT("Unknown escape sequence :\"\\{}\"", *it); } escape_mode = false; } @@ -150,7 +154,7 @@ inline void match_string2(std::string::const_iterator &star_end_string, std::str val.push_back(*it); } } - ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end)); + GULPS_ASSERT_MES_AND_THROW("Failed to match string in json entry: ", std::string(star_end_string, buf_end)); } inline bool match_string(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val) { @@ -169,6 +173,7 @@ inline void match_number2(std::string::const_iterator &star_end_string, std::str { val.clear(); is_float_val = false; + GULPS_CAT_MAJOR("epee_pars_bs_utls"); for(std::string::const_iterator it = star_end_string; it != buf_end; it++) { if(isdigit(*it) || (it == star_end_string && *it == '-') || (val.size() && *it == '.') || (is_float_val && (*it == 'e' || *it == 'E' || *it == '-' || *it == '+'))) @@ -187,10 +192,10 @@ inline void match_number2(std::string::const_iterator &star_end_string, std::str return; } else - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + GULPS_ASSERT_MES_AND_THROW("wrong number in json entry: ", std::string(star_end_string, buf_end)); } } - ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end)); + GULPS_ASSERT_MES_AND_THROW("wrong number in json entry: ", std::string(star_end_string, buf_end)); } inline bool match_number(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val) { @@ -209,7 +214,7 @@ inline bool match_number(std::string::const_iterator &star_end_string, std::stri inline void match_word2(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val) { val.clear(); - + GULPS_CAT_MAJOR("epee_pars_bs_utls"); for(std::string::const_iterator it = star_end_string; it != buf_end; it++) { if(!isalpha(*it)) @@ -221,10 +226,10 @@ inline void match_word2(std::string::const_iterator &star_end_string, std::strin return; } else - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + GULPS_ASSERT_MES_AND_THROW("failed to match word number in json entry: ", std::string(star_end_string, buf_end)); } } - ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end)); + GULPS_ASSERT_MES_AND_THROW("failed to match word number in json entry: ", std::string(star_end_string, buf_end)); } inline bool match_word(std::string::const_iterator &star_end_string, std::string::const_iterator buf_end, std::string &val) { diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index 445adaf8..5abcd279 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -34,6 +34,8 @@ #include "portable_storage_to_json.h" #include "portable_storage_val_converters.h" +#include "common/gulps.hpp" + namespace epee { namespace serialization @@ -43,6 +45,7 @@ namespace serialization /************************************************************************/ class portable_storage { + GULPS_CAT_MAJOR("epee_prt_strg"); public: typedef epee::serialization::hsection hsection; typedef epee::serialization::harray harray; @@ -105,18 +108,18 @@ class portable_storage }; inline bool portable_storage::dump_as_json(std::string &buff, size_t indent, bool insert_newlines) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); std::stringstream ss; epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines); buff = ss.str(); return true; - CATCH_ENTRY("portable_storage::dump_as_json", false) + GULPS_CATCH_ENTRY("portable_storage::dump_as_json", false) } inline bool portable_storage::load_from_json(const std::string &source) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); return json::load_from_json(source, *this); - CATCH_ENTRY("portable_storage::load_from_json", false) + GULPS_CATCH_ENTRY("portable_storage::load_from_json", false) } template @@ -127,7 +130,7 @@ bool portable_storage::dump_as_xml(std::string &targetObj, const std::string &ro inline bool portable_storage::store_to_binary(binarybuffer &target) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); std::stringstream ss; storage_block_header sbh = AUTO_VAL_INIT(sbh); sbh.m_signature_a = PORTABLE_STORAGE_SIGNATUREA; @@ -137,38 +140,38 @@ inline bool portable_storage::store_to_binary(binarybuffer &target) pack_entry_to_buff(ss, m_root); target = ss.str(); return true; - CATCH_ENTRY("portable_storage::store_to_binary", false) + GULPS_CATCH_ENTRY("portable_storage::store_to_binary", false) } inline bool portable_storage::load_from_binary(const binarybuffer &source) { m_root.m_entries.clear(); if(source.size() < sizeof(storage_block_header)) { - LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header)); + GULPSF_ERROR("portable_storage: wrong binary format, packet size = {} less than expected sizeof(storage_block_header)={}", source.size() , sizeof(storage_block_header)); return false; } storage_block_header *pbuff = (storage_block_header *)source.data(); if(pbuff->m_signature_a != PORTABLE_STORAGE_SIGNATUREA || pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB) { - LOG_ERROR("portable_storage: wrong binary format - signature mismatch"); + GULPS_ERROR("portable_storage: wrong binary format - signature mismatch"); return false; } if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER) { - LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver); + GULPSF_ERROR("portable_storage: wrong binary format - unknown format ver = {}", pbuff->m_ver); return false; } - TRY_ENTRY(); + GULPS_TRY_ENTRY(); throwable_buffer_reader buf_reader(source.data() + sizeof(storage_block_header), source.size() - sizeof(storage_block_header)); buf_reader.read(m_root); return true; //TODO: - CATCH_ENTRY("portable_storage::load_from_binary", false); + GULPS_CATCH_ENTRY("portable_storage::load_from_binary", false); } //--------------------------------------------------------------------------------------------------------------- inline hsection portable_storage::open_section(const std::string §ion_name, hsection hparent_section, bool create_if_notexist) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); hparent_section = hparent_section ? hparent_section : &m_root; storage_entry *pentry = find_storage_entry(section_name, hparent_section); if(!pentry) @@ -177,7 +180,7 @@ inline hsection portable_storage::open_section(const std::string §ion_name, return nullptr; return insert_new_section(section_name, hparent_section); } - CHECK_AND_ASSERT(pentry, nullptr); + GULPS_CHECK_AND_ASSERT(pentry, nullptr); //check that section_entry we find is real "CSSection" if(pentry->type() != typeid(section)) { @@ -187,7 +190,7 @@ inline hsection portable_storage::open_section(const std::string §ion_name, return nullptr; } return &boost::get
(*pentry); - CATCH_ENTRY("portable_storage::open_section", nullptr); + GULPS_CATCH_ENTRY("portable_storage::open_section", nullptr); } //--------------------------------------------------------------------------------------------------------------- template @@ -203,7 +206,7 @@ template bool portable_storage::get_value(const std::string &value_name, t_value &val, hsection hparent_section) { BOOST_MPL_ASSERT((boost::mpl::contains)); - //TRY_ENTRY(); + //GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(value_name, hparent_section); @@ -213,12 +216,12 @@ bool portable_storage::get_value(const std::string &value_name, t_value &val, hs get_value_visitor gvv(val); boost::apply_visitor(gvv, *pentry); return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); + // GULPS_CATCH_ENTRY("portable_storage::template<>get_value", false); } //--------------------------------------------------------------------------------------------------------------- inline bool portable_storage::get_value(const std::string &value_name, storage_entry &val, hsection hparent_section) { - //TRY_ENTRY(); + //GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(value_name, hparent_section); @@ -227,14 +230,14 @@ inline bool portable_storage::get_value(const std::string &value_name, storage_e val = *pentry; return true; - //CATCH_ENTRY("portable_storage::template<>get_value", false); + //GULPS_CATCH_ENTRY("portable_storage::template<>get_value", false); } //--------------------------------------------------------------------------------------------------------------- template bool portable_storage::set_value(const std::string &value_name, const t_value &v, hsection hparent_section) { BOOST_MPL_ASSERT((boost::mpl::contains::type, t_value>)); - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(value_name, hparent_section); @@ -247,39 +250,39 @@ bool portable_storage::set_value(const std::string &value_name, const t_value &v } *pentry = storage_entry(v); return true; - CATCH_ENTRY("portable_storage::template<>set_value", false); + GULPS_CATCH_ENTRY("portable_storage::template<>set_value", false); } //--------------------------------------------------------------------------------------------------------------- inline storage_entry *portable_storage::find_storage_entry(const std::string &pentry_name, hsection psection) { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); + GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(psection, nullptr); auto it = psection->m_entries.find(pentry_name); if(it == psection->m_entries.end()) return nullptr; return &it->second; - CATCH_ENTRY("portable_storage::find_storage_entry", nullptr); + GULPS_CATCH_ENTRY("portable_storage::find_storage_entry", nullptr); } //--------------------------------------------------------------------------------------------------------------- template storage_entry *portable_storage::insert_new_entry_get_storage_entry(const std::string &pentry_name, hsection psection, const entry_type &entry) { - TRY_ENTRY(); - CHECK_AND_ASSERT(psection, nullptr); + GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(psection, nullptr); auto ins_res = psection->m_entries.insert(std::pair(pentry_name, entry)); return &ins_res.first->second; - CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); + GULPS_CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); } //--------------------------------------------------------------------------------------------------------------- inline hsection portable_storage::insert_new_section(const std::string &pentry_name, hsection psection) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); storage_entry *pse = insert_new_entry_get_storage_entry(pentry_name, psection, section()); if(!pse) return nullptr; return &boost::get
(*pse); - CATCH_ENTRY("portable_storage::insert_new_section", nullptr); + GULPS_CATCH_ENTRY("portable_storage::insert_new_section", nullptr); } //--------------------------------------------------------------------------------------------------------------- template @@ -302,7 +305,7 @@ template harray portable_storage::get_first_value(const std::string &value_name, t_value &target, hsection hparent_section) { BOOST_MPL_ASSERT((boost::mpl::contains)); - //TRY_ENTRY(); + //GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(value_name, hparent_section); @@ -316,7 +319,7 @@ harray portable_storage::get_first_value(const std::string &value_name, t_value if(!boost::apply_visitor(gfv, ar_entry)) return nullptr; return &ar_entry; - //CATCH_ENTRY("portable_storage::get_first_value", nullptr); + // GULPS_CATCH_ENTRY("portable_storage::get_first_value", nullptr); } //--------------------------------------------------------------------------------------------------------------- template @@ -340,20 +343,20 @@ template bool portable_storage::get_next_value(harray hval_array, t_value &target) { BOOST_MPL_ASSERT((boost::mpl::contains)); - //TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); + //GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(hval_array, false); array_entry &ar_entry = *hval_array; get_next_value_visitor gnv(target); if(!boost::apply_visitor(gnv, ar_entry)) return false; return true; - //CATCH_ENTRY("portable_storage::get_next_value", false); + // GULPS_CATCH_ENTRY("portable_storage::get_next_value", false); } //--------------------------------------------------------------------------------------------------------------- template harray portable_storage::insert_first_value(const std::string &value_name, const t_value &target, hsection hparent_section) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(value_name, hparent_section); @@ -373,28 +376,28 @@ harray portable_storage::insert_first_value(const std::string &value_name, const array_entry_t &arr_typed = boost::get>(arr); arr_typed.insert_first_val(target); return &arr; - CATCH_ENTRY("portable_storage::insert_first_value", nullptr); + GULPS_CATCH_ENTRY("portable_storage::insert_first_value", nullptr); } //--------------------------------------------------------------------------------------------------------------- template bool portable_storage::insert_next_value(harray hval_array, const t_value &target) { - TRY_ENTRY(); - CHECK_AND_ASSERT(hval_array, false); + GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(hval_array, false); - CHECK_AND_ASSERT_MES(hval_array->type() == typeid(array_entry_t), - false, "unexpected type in insert_next_value: " << typeid(array_entry_t).name()); + GULPS_CHECK_AND_ASSERT_MES(hval_array->type() == typeid(array_entry_t), + false, "unexpected type in insert_next_value: " , typeid(array_entry_t).name()); array_entry_t &arr_typed = boost::get>(*hval_array); arr_typed.insert_next_value(target); return true; - CATCH_ENTRY("portable_storage::insert_next_value", false); + GULPS_CATCH_ENTRY("portable_storage::insert_next_value", false); } //--------------------------------------------------------------------------------------------------------------- //sections inline harray portable_storage::get_first_section(const std::string &sec_name, hsection &h_child_section, hsection hparent_section) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(sec_name, hparent_section); @@ -411,13 +414,13 @@ inline harray portable_storage::get_first_section(const std::string &sec_name, h return nullptr; h_child_section = psec; return &ar_entry; - CATCH_ENTRY("portable_storage::get_first_section", nullptr); + GULPS_CATCH_ENTRY("portable_storage::get_first_section", nullptr); } //--------------------------------------------------------------------------------------------------------------- inline bool portable_storage::get_next_section(harray hsec_array, hsection &h_child_section) { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); + GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(hsec_array, false); if(hsec_array->type() != typeid(array_entry_t
)) return false; array_entry_t
&sec_array = boost::get>(*hsec_array); @@ -425,12 +428,12 @@ inline bool portable_storage::get_next_section(harray hsec_array, hsection &h_ch if(!h_child_section) return false; return true; - CATCH_ENTRY("portable_storage::get_next_section", false); + GULPS_CATCH_ENTRY("portable_storage::get_next_section", false); } //--------------------------------------------------------------------------------------------------------------- inline harray portable_storage::insert_first_section(const std::string &sec_name, hsection &hinserted_childsection, hsection hparent_section) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!hparent_section) hparent_section = &m_root; storage_entry *pentry = find_storage_entry(sec_name, hparent_section); @@ -450,20 +453,20 @@ inline harray portable_storage::insert_first_section(const std::string &sec_name array_entry_t
&sec_array = boost::get>(ar_entry); hinserted_childsection = &sec_array.insert_first_val(section()); return &ar_entry; - CATCH_ENTRY("portable_storage::insert_first_section", nullptr); + GULPS_CATCH_ENTRY("portable_storage::insert_first_section", nullptr); } //--------------------------------------------------------------------------------------------------------------- inline bool portable_storage::insert_next_section(harray hsec_array, hsection &hinserted_childsection) { - TRY_ENTRY(); - CHECK_AND_ASSERT(hsec_array, false); - CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t
), - false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name()); + GULPS_TRY_ENTRY(); + GULPS_CHECK_AND_ASSERT(hsec_array, false); + GULPS_CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t
), + false, "unexpected type(not 'section') in insert_next_section, type: " , hsec_array->type().name()); array_entry_t
&sec_array = boost::get>(*hsec_array); hinserted_childsection = &sec_array.insert_next_value(section()); return true; - CATCH_ENTRY("portable_storage::insert_next_section", false); + GULPS_CATCH_ENTRY("portable_storage::insert_next_section", false); } //--------------------------------------------------------------------------------------------------------------- } diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h index 34882884..f79dbe96 100644 --- a/contrib/epee/include/storages/portable_storage_from_bin.h +++ b/contrib/epee/include/storages/portable_storage_from_bin.h @@ -66,11 +66,11 @@ struct throwable_buffer_reader recursuion_limitation_guard(size_t &counter) : m_counter_ref(counter) { ++m_counter_ref; - CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded"); + GULPS_CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (", EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, ") exceeded"); } ~recursuion_limitation_guard() noexcept(false) { - CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()"); + GULPS_CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()"); --m_counter_ref; } }; @@ -94,7 +94,7 @@ inline throwable_buffer_reader::throwable_buffer_reader(const void *ptr, size_t inline void throwable_buffer_reader::read(void *target, size_t count) { RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained"); + GULPS_CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read ", count, " bytes from buffer with ", m_count, " bytes remained"); memcpy(target, m_ptr, count); m_ptr += count; m_count -= count; @@ -171,14 +171,14 @@ inline storage_entry throwable_buffer_reader::load_storage_array_entry(uint8_t t case SERIALIZE_TYPE_ARRAY: return read_ae(); default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = ", type); } } inline size_t throwable_buffer_reader::read_varint() { RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint"); + GULPS_CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint"); size_t v = 0; uint8_t size_mask = (*(uint8_t *)m_ptr) & PORTABLE_RAW_SIZE_MARK_MASK; switch(size_mask) @@ -196,7 +196,7 @@ inline size_t throwable_buffer_reader::read_varint() v = read(); break; default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = ", size_mask); } v >>= 2; return v; @@ -235,7 +235,7 @@ inline storage_entry throwable_buffer_reader::read_se() RECURSION_LIMITATION(); uint8_t ent_type = 0; read(ent_type); - CHECK_AND_ASSERT_THROW_MES(ent_type & SERIALIZE_FLAG_ARRAY, "wrong type sequenses"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ent_type & SERIALIZE_FLAG_ARRAY, "wrong type sequenses"); return load_storage_array_entry(ent_type); } @@ -276,7 +276,7 @@ inline storage_entry throwable_buffer_reader::load_storage_entry() case SERIALIZE_TYPE_ARRAY: return read_se(); default: - CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = ", ent_type); } } inline void throwable_buffer_reader::read(section &sec) @@ -296,8 +296,8 @@ inline void throwable_buffer_reader::read(std::string &str) { RECURSION_LIMITATION(); size_t len = read_varint(); - CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len); - CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count); + GULPS_CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: ", len); + GULPS_CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value ", len, " goes out of remain storage len ", m_count); //do this manually to avoid double memory write in huge strings (first time at resize, second at read) str.assign((const char *)m_ptr, len); m_ptr += len; @@ -307,7 +307,7 @@ inline void throwable_buffer_reader::read(std::string &str) inline void throwable_buffer_reader::read(array_entry &ae) { RECURSION_LIMITATION(); - CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported"); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported"); } } } diff --git a/contrib/epee/include/storages/portable_storage_from_json.h b/contrib/epee/include/storages/portable_storage_from_json.h index 3451b6c6..9aef13e5 100644 --- a/contrib/epee/include/storages/portable_storage_from_json.h +++ b/contrib/epee/include/storages/portable_storage_from_json.h @@ -32,6 +32,8 @@ #define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100 +#include "common/gulps.hpp" + namespace epee { using namespace misc_utils::parse; @@ -39,21 +41,22 @@ namespace serialization { namespace json { +GULPS_CAT_MAJOR("epee_ptb_stg_jsn"); #define CHECK_ISSPACE() \ if(!isspace(*it)) \ { \ - ASSERT_MES_AND_THROW("Wrong JSON character at: " << std::string(it, buf_end)); \ + GULPS_ASSERT_MES_AND_THROW("Wrong JSON character at: ", std::string(it, buf_end)); \ } /*inline void parse_error() { - ASSERT_MES_AND_THROW("json parse error"); + GULPS_ASSERT_MES_AND_THROW("json parse error"); }*/ template inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg, unsigned int recursion) { - CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL, "Wrong JSON data: recursion limitation (" << EPEE_JSON_RECURSION_LIMIT_INTERNAL << ") exceeded"); + GULPS_CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL, "Wrong JSON data: recursion limitation (", EPEE_JSON_RECURSION_LIMIT_INTERNAL, ") exceeded"); std::string::const_iterator sub_element_start; std::string name; typename t_storage::harray h_array = nullptr; @@ -169,13 +172,13 @@ inline void run_handler(typename t_storage::hsection current_section, state = match_state_wonder_after_value; } else - ASSERT_MES_AND_THROW("Unknown value keyword " << word); + GULPS_ASSERT_MES_AND_THROW("Unknown value keyword ", word); } else if(*it == '{') { //sub section here typename t_storage::hsection new_sec = stg.open_section(name, current_section, true); - CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end)); + GULPS_CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: ", std::string(it, buf_end)); run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_wonder_after_value; } @@ -201,7 +204,7 @@ inline void run_handler(typename t_storage::hsection current_section, case match_state_wonder_array: if(*it == '[') { - ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry"); + GULPS_ASSERT_MES_AND_THROW("array of array not suppoerted yet :( sorry"); //mean array of array } if(*it == '{') @@ -209,7 +212,7 @@ inline void run_handler(typename t_storage::hsection current_section, //mean array of sections typename t_storage::hsection new_sec = nullptr; h_array = stg.insert_first_section(name, new_sec, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array && new_sec, "failed to create new section"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array && new_sec, "failed to create new section"); run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_array_after_value; array_md = array_mode_sections; @@ -220,7 +223,7 @@ inline void run_handler(typename t_storage::hsection current_section, std::string val; match_string2(it, buf_end, val); h_array = stg.insert_first_value(name, val, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values entry"); state = match_state_array_after_value; array_md = array_mode_string; } @@ -234,13 +237,13 @@ inline void run_handler(typename t_storage::hsection current_section, { int64_t nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); } else { double nval = boost::lexical_cast(val); //bool res = string_tools::string_to_num_fast(val, nval); h_array = stg.insert_first_value(name, nval, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); } state = match_state_array_after_value; @@ -258,19 +261,19 @@ inline void run_handler(typename t_storage::hsection current_section, if(boost::iequals(word, "true")) { h_array = stg.insert_first_value(name, true, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); state = match_state_array_after_value; array_md = array_mode_booleans; } else if(boost::iequals(word, "false")) { h_array = stg.insert_first_value(name, false, current_section); - CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(h_array, " failed to insert values section entry"); state = match_state_array_after_value; array_md = array_mode_booleans; } else - ASSERT_MES_AND_THROW("Unknown value keyword " << word) + GULPS_ASSERT_MES_AND_THROW("Unknown value keyword ", word) } else CHECK_ISSPACE(); @@ -295,7 +298,7 @@ inline void run_handler(typename t_storage::hsection current_section, { typename t_storage::hsection new_sec = NULL; bool res = stg.insert_next_section(h_array, new_sec); - CHECK_AND_ASSERT_THROW_MES(res && new_sec, "failed to insert next section"); + GULPS_CHECK_AND_ASSERT_THROW_MES(res && new_sec, "failed to insert next section"); run_handler(new_sec, it, buf_end, stg, recursion + 1); state = match_state_array_after_value; } @@ -308,7 +311,7 @@ inline void run_handler(typename t_storage::hsection current_section, std::string val; match_string2(it, buf_end, val); bool res = stg.insert_next_value(h_array, val); - CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); + GULPS_CHECK_AND_ASSERT_THROW_MES(res, "failed to insert values"); state = match_state_array_after_value; } else @@ -333,7 +336,7 @@ inline void run_handler(typename t_storage::hsection current_section, double nval = boost::lexical_cast(val); //string_tools::string_to_num_fast(val, nval); insert_res = stg.insert_next_value(h_array, nval); } - CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); + GULPS_CHECK_AND_ASSERT_THROW_MES(insert_res, "Failed to insert next value"); state = match_state_array_after_value; array_md = array_mode_numbers; } @@ -348,29 +351,29 @@ inline void run_handler(typename t_storage::hsection current_section, if(boost::iequals(word, "true")) { bool r = stg.insert_next_value(h_array, true); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); state = match_state_array_after_value; } else if(boost::iequals(word, "false")) { bool r = stg.insert_next_value(h_array, false); - CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); + GULPS_CHECK_AND_ASSERT_THROW_MES(r, " failed to insert values section entry"); state = match_state_array_after_value; } else - ASSERT_MES_AND_THROW("Unknown value keyword " << word); + GULPS_ASSERT_MES_AND_THROW("Unknown value keyword ", word); } else CHECK_ISSPACE(); break; case array_mode_undifined: default: - ASSERT_MES_AND_THROW("Bad array state"); + GULPS_ASSERT_MES_AND_THROW("Bad array state"); } break; case match_state_error: default: - ASSERT_MES_AND_THROW("WRONG JSON STATE"); + GULPS_ASSERT_MES_AND_THROW("WRONG JSON STATE"); } } } @@ -383,9 +386,9 @@ inline void run_handler(typename t_storage::hsection current_section, "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", - "postalCode": -10021, - "have_boobs": true, - "have_balls": false + "postalCode": -10021, + "have_boobs": true, + "have_balls": false }, "phoneNumber": [ { @@ -396,7 +399,7 @@ inline void run_handler(typename t_storage::hsection current_section, "type": "fax", "number": "646 555-4567" } - ], + ], "phoneNumbers": [ "812 123-1234", "916 123-4567" @@ -414,12 +417,12 @@ inline bool load_from_json(const std::string &buff_json, t_storage &stg) } catch(const std::exception &ex) { - MERROR("Failed to parse json, what: " << ex.what()); + GULPSF_ERROR("Failed to parse json, what: {}", ex.what()); return false; } catch(...) { - MERROR("Failed to parse json"); + GULPS_ERROR("Failed to parse json"); return false; } } diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h index c336ff96..0a4c8dbb 100644 --- a/contrib/epee/include/storages/portable_storage_to_bin.h +++ b/contrib/epee/include/storages/portable_storage_to_bin.h @@ -67,7 +67,7 @@ size_t pack_varint(t_stream &strm, size_t val) } else { - CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = " << val); + GULPS_CHECK_AND_ASSERT_THROW_MES(val <= 4611686018427387903, "failed to pack varint - too big amount = ", val); return pack_varint_t(strm, PORTABLE_RAW_SIZE_MARK_INT64, val); } } @@ -204,7 +204,7 @@ bool pack_entry_to_buff(t_stream &strm, const section &sec) pack_varint(strm, sec.m_entries.size()); for(const section_pair &se : sec.m_entries) { - CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first); + GULPS_CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits::max(), "storage_entry_name is too long: ", se.first.size(),", val: ", se.first); uint8_t len = static_cast(se.first.size()); strm.write((const char *)&len, sizeof(len)); strm.write(se.first.data(), size_t(len)); diff --git a/contrib/epee/include/storages/portable_storage_val_converters.h b/contrib/epee/include/storages/portable_storage_val_converters.h index 283a5e38..3285842e 100644 --- a/contrib/epee/include/storages/portable_storage_val_converters.h +++ b/contrib/epee/include/storages/portable_storage_val_converters.h @@ -33,40 +33,45 @@ #include "portable_storage_base.h" #include "warnings.h" +#include "common/gulps.hpp" + namespace epee { namespace serialization { -#define ASSERT_AND_THROW_WRONG_CONVERSION() ASSERT_MES_AND_THROW("WRONG DATA CONVERSION: from type=" << typeid(from).name() << " to type " << typeid(to).name()) +#define ASSERT_AND_THROW_WRONG_CONVERSION() GULPS_ASSERT_MES_AND_THROW("WRONG DATA CONVERSION: from type=", typeid(from).name(), " to type ", typeid(to).name()) template void convert_int_to_uint(const from_type &from, to_type &to) { + GULPS_CAT_MAJOR("epee_val_conv"); PUSH_WARNINGS DISABLE_VS_WARNINGS(4018) - CHECK_AND_ASSERT_THROW_MES(from >= 0, "unexpected int value with signed storage value less than 0, and unsigned receiver value"); + GULPS_CHECK_AND_ASSERT_THROW_MES(from >= 0, "unexpected int value with signed storage value less than 0, and unsigned receiver value"); DISABLE_GCC_AND_CLANG_WARNING(sign-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); + GULPS_CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value ", from, " to type ", typeid(to_type).name(), " with max possible value = ", std::numeric_limits::max()); to = static_cast(from); POP_WARNINGS } template void convert_int_to_int(const from_type &from, to_type &to) { - CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds::lowest(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with lowest possible value = " << boost::numeric::bounds::lowest()); + GULPS_CAT_MAJOR("epee_val_conv"); + GULPS_CHECK_AND_ASSERT_THROW_MES(from >= boost::numeric::bounds::lowest(), "int value overhead: try to set value ", from, " to type ", typeid(to_type).name(), " with lowest possible value = ", boost::numeric::bounds::lowest()); PUSH_WARNINGS DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); + GULPS_CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "int value overhead: try to set value ", from, " to type ", typeid(to_type).name(), " with max possible value = ", std::numeric_limits::max()); POP_WARNINGS to = static_cast(from); } template void convert_uint_to_any_int(const from_type &from, to_type &to) { + GULPS_CAT_MAJOR("epee_val_conv"); PUSH_WARNINGS DISABLE_VS_WARNINGS(4018) DISABLE_CLANG_WARNING(tautological-constant-out-of-range-compare) - CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "uint value overhead: try to set value " << from << " to type " << typeid(to_type).name() << " with max possible value = " << std::numeric_limits::max()); + GULPS_CHECK_AND_ASSERT_THROW_MES(from <= std::numeric_limits::max(), "uint value overhead: try to set value ", from, " to type ", typeid(to_type).name(), " with max possible value = ", std::numeric_limits::max()); to = static_cast(from); POP_WARNINGS } @@ -128,6 +133,7 @@ struct convert_to_integral { static void convert(const from_type &from, to_type &to) { + GULPS_CAT_MAJOR("epee_val_conv"); ASSERT_AND_THROW_WRONG_CONVERSION(); } }; @@ -140,7 +146,8 @@ struct convert_to_integral { static void convert(const std::string &from, uint64_t &to) { - MTRACE("Converting std::string to uint64_t. Source: " << from); + GULPS_CAT_MAJOR("epee_val_conv"); + GULPSF_LOG_L2("Converting std::string to uint64_t. Source: {}", from); // String only contains digits if(std::all_of(from.begin(), from.end(), ::isdigit)) to = boost::lexical_cast(from); diff --git a/contrib/epee/include/zlib_helper.h b/contrib/epee/include/zlib_helper.h index bb1fda73..73b40e26 100644 --- a/contrib/epee/include/zlib_helper.h +++ b/contrib/epee/include/zlib_helper.h @@ -51,7 +51,7 @@ inline bool pack(std::string &target) zstream.avail_out = (uInt)result_packed_buff.size(); ret = deflate(&zstream, Z_FINISH); - CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate. err = " << ret); + GULPS_CHECK_AND_ASSERT_MES(ret >= 0, false, "Failed to deflate. err = ", ret); if(result_packed_buff.size() != zstream.avail_out) result_packed_buff.resize(result_packed_buff.size() - zstream.avail_out); @@ -91,7 +91,7 @@ inline bool unpack(std::string &target) ret = inflate(&zstream, Z_NO_FLUSH); if(ret != Z_OK) { - LOCAL_ASSERT(0); + GULPS_LOCAL_ASSERT(0); return false; } @@ -101,7 +101,7 @@ inline bool unpack(std::string &target) ret = inflate(&zstream, Z_SYNC_FLUSH); if(ret != Z_OK && ret != Z_STREAM_END) { - LOCAL_ASSERT(0); + GULPS_LOCAL_ASSERT(0); return false; } diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index c4750cea..8b2f0e4e 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -26,9 +26,9 @@ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c +add_library(epee STATIC hex.cpp http_auth.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp) -if (USE_READLINE AND GNU_READLINE_FOUND) +if (USE_READLINE AND GNU_READLINE_FOUND AND READLINE_FOUND) add_library(epee_readline STATIC readline_buffer.cpp) endif() @@ -45,7 +45,7 @@ if (BUILD_GUI_DEPS) endif() install(TARGETS epee ARCHIVE DESTINATION ${lib_folder}) - if (USE_READLINE AND GNU_READLINE_FOUND) + if (USE_READLINE AND GNU_READLINE_FOUND AND READLINE_FOUND) install(TARGETS epee_readline ARCHIVE DESTINATION ${lib_folder}) endif() @@ -53,16 +53,16 @@ endif() target_link_libraries(epee PUBLIC - easylogging ${Boost_FILESYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) -if (USE_READLINE AND GNU_READLINE_FOUND) +if (USE_READLINE AND GNU_READLINE_FOUND AND READLINE_FOUND) target_link_libraries(epee_readline PUBLIC - easylogging + fmt::fmt-header-only PRIVATE ${GNU_READLINE_LIBRARY}) endif() diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index d2801d64..5524d1d5 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -54,7 +54,6 @@ #include "syncobj.h" #include "misc_language.h" -#include "misc_log_ex.h" #include "net/net_utils_base.h" #include "pragma_comp_defs.h" #include @@ -79,8 +78,9 @@ // TODO: #include "net/network_throttle-detail.hpp" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.p2p" +#include "common/gulps.hpp" + + // ################################################################################################ // local (TU local) headers @@ -165,7 +165,7 @@ connection_basic::connection_basic(boost::asio::io_service &io_service, std::ato { }; - _note("Spawned connection p2p#" << mI->m_peer_number << " to " << remote_addr_str << " currently we have sockets count:" << m_ref_sock_count); + GULPSF_LOG_L1("Spawned connection p2p#{} to {} currently we have sockets count:{}", mI->m_peer_number, remote_addr_str, m_ref_sock_count); } connection_basic::~connection_basic() noexcept(false) @@ -180,7 +180,7 @@ connection_basic::~connection_basic() noexcept(false) catch(...) { }; - _note("Destructing connection p2p#" << mI->m_peer_number << " to " << remote_addr_str); + GULPSF_LOG_L1("Destructing connection p2p#{} to {}", mI->m_peer_number, remote_addr_str); } void connection_basic::set_rate_up_limit(uint64_t limit) @@ -247,7 +247,7 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q_ { // rate limiting if(m_was_shutdown) { - _dbg2("m_was_shutdown - so abort sleep"); + GULPS_LOG_L1("m_was_shutdown - so abort sleep"); return; } @@ -260,7 +260,7 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q_ if(delay > 0) { long int ms = (long int)(delay * 1000); - MTRACE("Sleeping in " << __FUNCTION__ << " for " << ms << " ms before packet_size=" << packet_size); // debug sleep + GULPSF_LOG_L2("Sleeping in {} for {} ms before packet_size={}", __FUNCTION__, ms, packet_size); // debug sleep boost::this_thread::sleep(boost::posix_time::milliseconds(ms)); } } while(delay > 0); @@ -280,14 +280,14 @@ void connection_basic::set_start_time() void connection_basic::do_send_handler_write(const void *ptr, size_t cb) { // No sleeping here; sleeping is done once and for all in connection::handle_write - MTRACE("handler_write (direct) - before ASIO write, for packet=" << cb << " B (after sleep)"); + GULPSF_LOG_L2("handler_write (direct) - before ASIO write, for packet={}" , cb); set_start_time(); } void connection_basic::do_send_handler_write_from_queue(const boost::system::error_code &e, size_t cb, int q_len) { // No sleeping here; sleeping is done once and for all in connection::handle_write - MTRACE("handler_write (after write, from queue=" << q_len << ") - before ASIO write, for packet=" << cb << " B (after sleep)"); + GULPSF_LOG_L2("handler_write (after write, from queue={}) - before ASIO write, for packet={} B (after sleep)", q_len, cb); set_start_time(); } diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp deleted file mode 100644 index 8f0c8c86..00000000 --- a/contrib/epee/src/mlog.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net -// 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. -// * Neither the name of the Andrey N. Sabelnikov 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 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 _MLOG_H_ -#define _MLOG_H_ - -#include "misc_log_ex.h" -#include "string_tools.h" -#include -#include -#include -#include - -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "logging" - -#define MLOG_BASE_FORMAT "%datetime{%Y-%M-%d %H:%m:%s.%g}\t%thread\t%level\t%logger\t%loc\t%msg" - -#define MLOG_LOG(x) CINFO(el::base::Writer, el::base::DispatchAction::FileOnlyLog, RYO_DEFAULT_LOG_CATEGORY) << x - -using namespace epee; - -static std::string generate_log_filename(const char *base) -{ - std::string filename(base); - char tmp[200]; - struct tm tm; - time_t now = time(NULL); - if -#ifdef WIN32 - (!gmtime_s(&tm, &now)) -#else - (!gmtime_r(&now, &tm)) -#endif - strcpy(tmp, "unknown"); - else - strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm); - tmp[sizeof(tmp) - 1] = 0; - filename += "-"; - filename += tmp; - return filename; -} - -std::string mlog_get_default_log_path(const char *default_filename) -{ - std::string process_name = epee::string_tools::get_current_module_name(); - std::string default_log_folder = epee::string_tools::get_current_module_folder(); - std::string default_log_file = process_name; - std::string::size_type a = default_log_file.rfind('.'); - if(a != std::string::npos) - default_log_file.erase(a, default_log_file.size()); - if(!default_log_file.empty()) - default_log_file += ".log"; - else - default_log_file = default_filename; - - return (boost::filesystem::path(default_log_folder) / boost::filesystem::path(default_log_file)).string(); -} - -static void mlog_set_common_prefix() -{ - static const char *const expected_filename = "contrib/epee/src/mlog.cpp"; - const char *path = __FILE__, *expected_ptr = strstr(path, expected_filename); - if(!expected_ptr) - return; - el::Loggers::setFilenameCommonPrefix(std::string(path, expected_ptr - path)); -} - -static const char *get_default_categories(int level) -{ - const char *categories = ""; - switch(level) - { - case 0: - categories = "*:WARNING,net:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; - break; - case 1: - categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO"; - break; - case 2: - categories = "*:DEBUG"; - break; - case 3: - categories = "*:TRACE"; - break; - case 4: - categories = "*:TRACE"; - break; - default: - break; - } - return categories; -} - -void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size) -{ - el::Configurations c; - c.setGlobally(el::ConfigurationType::Filename, filename_base); - c.setGlobally(el::ConfigurationType::ToFile, "true"); - const char *log_format = getenv("RYO_LOG_FORMAT"); - if(!log_format) - log_format = MLOG_BASE_FORMAT; - c.setGlobally(el::ConfigurationType::Format, log_format); - c.setGlobally(el::ConfigurationType::ToStandardOutput, console ? "true" : "false"); - c.setGlobally(el::ConfigurationType::MaxLogFileSize, std::to_string(max_log_file_size)); - el::Loggers::setDefaultConfigurations(c, true); - - el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging); - el::Loggers::addFlag(el::LoggingFlag::CreateLoggerAutomatically); - el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog); - el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput); - el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck); - el::Helpers::installPreRollOutCallback([filename_base](const char *name, size_t) { - std::string rname = generate_log_filename(filename_base.c_str()); - rename(name, rname.c_str()); - }); - mlog_set_common_prefix(); - const char *monero_log = getenv("RYO_LOGS"); - if(!monero_log) - { - monero_log = get_default_categories(0); - } - mlog_set_log(monero_log); -} - -void mlog_set_categories(const char *categories) -{ - std::string new_categories; - if(*categories) - { - if(*categories == '+') - { - ++categories; - new_categories = mlog_get_categories(); - if(*categories) - { - if(!new_categories.empty()) - new_categories += ","; - new_categories += categories; - } - } - else if(*categories == '-') - { - ++categories; - new_categories = mlog_get_categories(); - std::vector single_categories; - boost::split(single_categories, categories, boost::is_any_of(","), boost::token_compress_on); - for(const std::string &s : single_categories) - { - size_t pos = new_categories.find(s); - if(pos != std::string::npos) - new_categories = new_categories.erase(pos, s.size()); - } - } - else - { - new_categories = categories; - } - } - el::Loggers::setCategories(new_categories.c_str(), true); - MLOG_LOG("New log categories: " << el::Loggers::getCategories()); -} - -std::string mlog_get_categories() -{ - return el::Loggers::getCategories(); -} - -// maps epee style log level to new logging system -void mlog_set_log_level(int level) -{ - const char *categories = get_default_categories(level); - mlog_set_categories(categories); -} - -void mlog_set_log(const char *log) -{ - long level; - char *ptr = NULL; - - if(!*log) - { - mlog_set_categories(log); - return; - } - level = strtol(log, &ptr, 10); - if(ptr && *ptr) - { - // we can have a default level, eg, 2,foo:ERROR - if(*ptr == ',') - { - std::string new_categories = std::string(get_default_categories(level)) + ptr; - mlog_set_categories(new_categories.c_str()); - } - else - { - mlog_set_categories(log); - } - } - else if(level >= 0 && level <= 4) - { - mlog_set_log_level(level); - } - else - { - MERROR("Invalid numerical log level: " << log); - } -} - -namespace epee -{ - -bool is_stdout_a_tty() -{ - static std::atomic initialized(false); - static std::atomic is_a_tty(false); - - if(!initialized.load(std::memory_order_acquire)) - { -#if defined(WIN32) - is_a_tty.store(0 != _isatty(_fileno(stdout)), std::memory_order_relaxed); -#else - is_a_tty.store(0 != isatty(fileno(stdout)), std::memory_order_relaxed); -#endif - initialized.store(true, std::memory_order_release); - } - - return is_a_tty.load(std::memory_order_relaxed); -} - -void set_console_color(int color, bool bright) -{ - if(!is_stdout_a_tty()) - return; - - switch(color) - { - case console_color_default: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;37m"; - else - std::cout << "\033[0m"; -#endif - } - break; - case console_color_white: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;37m"; - else - std::cout << "\033[0;37m"; -#endif - } - break; - case console_color_red: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;31m"; - else - std::cout << "\033[0;31m"; -#endif - } - break; - case console_color_green: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;32m"; - else - std::cout << "\033[0;32m"; -#endif - } - break; - - case console_color_blue: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_INTENSITY); //(bright ? FOREGROUND_INTENSITY:0)); -#else - if(bright) - std::cout << "\033[1;34m"; - else - std::cout << "\033[0;34m"; -#endif - } - break; - - case console_color_cyan: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;36m"; - else - std::cout << "\033[0;36m"; -#endif - } - break; - - case console_color_magenta: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;35m"; - else - std::cout << "\033[0;35m"; -#endif - } - break; - - case console_color_yellow: - { -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY : 0)); -#else - if(bright) - std::cout << "\033[1;33m"; - else - std::cout << "\033[0;33m"; -#endif - } - break; - } -} - -void reset_console_color() -{ - if(!is_stdout_a_tty()) - return; - -#ifdef WIN32 - HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); -#else - std::cout << "\033[0m"; - std::cout.flush(); -#endif -} -} - -#endif //_MLOG_H_ diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index d199c991..4aca63c0 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -52,7 +52,6 @@ #include "syncobj.h" #include "misc_language.h" -#include "misc_log_ex.h" #include "net/net_utils_base.h" #include "pragma_comp_defs.h" #include @@ -74,8 +73,9 @@ // TODO: #include "net/network_throttle-detail.hpp" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.throttle" +#include "common/gulps.hpp" + + // ################################################################################################ // ################################################################################################ @@ -151,7 +151,7 @@ void network_throttle::set_name(const std::string &name) void network_throttle::set_target_speed(network_speed_kbps target) { m_target_speed = target * 1024; - MINFO("Setting LIMIT: " << target << " kbps"); + GULPSF_INFO("Setting LIMIT: {} kbps", target); } network_speed_kbps network_throttle::get_target_speed() @@ -173,7 +173,7 @@ void network_throttle::tick() // TODO optimize when moving few slots at once while((!m_any_packet_yet) || (last_sample_time_slot < current_sample_time_slot)) { - _dbg3("Moving counter buffer by 1 second " << last_sample_time_slot << " < " << current_sample_time_slot << " (last time " << m_last_sample_time << ")"); + GULPSF_LOG_L1("Moving counter buffer by 1 second {} < {} (last time {})", last_sample_time_slot, current_sample_time_slot, m_last_sample_time); // rotate buffer for(size_t i = m_history.size() - 1; i >= 1; --i) m_history[i] = m_history[i - 1]; @@ -211,13 +211,11 @@ void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_s oss << "]" << std::ends; std::string history_str = oss.str(); - MTRACE("Throttle " << m_name << ": packet of ~" << packet_size << "b " - << " (from " << orginal_size << " b)" - << " Speed AVG=" << std::setw(4) << ((long int)(cts.average / 1024)) << "[w=" << cts.window << "]" - << " " << std::setw(4) << ((long int)(cts2.average / 1024)) << "[w=" << cts2.window << "]" - << " / " - << " Limit=" << ((long int)(m_target_speed / 1024)) << " KiB/sec " - << " " << history_str); + GULPSF_LOG_L2("Throttle {}: packet of ~{}b (from {} b) Speed AVG={:>4}[w={}] {:>4}[w={}] / Limit={} KiB/sec {}", m_name, packet_size, + orginal_size, + ((long int)(cts.average / 1024)), cts.window, + ((long int)(cts2.average / 1024)), cts2.window, + ((long int)(m_target_speed / 1024)), history_str); } void network_throttle::handle_trafic_tcp(size_t packet_size) @@ -243,7 +241,7 @@ void network_throttle::logger_handle_net(const std::string &filename, double tim file.open(filename.c_str(), std::ios::app | std::ios::out); file.precision(6); if(!file.is_open()) - _warn("Can't open file " << filename); + GULPS_WARN("Can't open file ", filename); file << static_cast(time) << " " << static_cast(size / 1024) << "\n"; file.close(); } @@ -317,17 +315,20 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc oss << sample.m_size << " "; oss << "]" << std::ends; std::string history_str = oss.str(); - MTRACE((cts.delay > 0 ? "SLEEP" : "") - << "dbg " << m_name << ": " - << "speed is A=" << std::setw(8) << cts.average << " vs " - << "Max=" << std::setw(8) << M << " " - << " so sleep: " - << "D=" << std::setw(8) << cts.delay << " sec " - << "E=" << std::setw(8) << E << " (Enow=" << std::setw(8) << Enow << ") " - << "M=" << std::setw(8) << M << " W=" << std::setw(8) << cts.window << " " - << "R=" << std::setw(8) << cts.recomendetDataSize << " Wgood" << std::setw(8) << Wgood << " " - << "History: " << std::setw(8) << history_str << " " - << "m_last_sample_time=" << std::setw(8) << m_last_sample_time); + GULPSF_LOG_L2("{} dbg {}: speed is A={:>8} vs Max={:>8} so sleep: D={:>8} sec E={:>8} (Enow={:>8}) M={:>8} W={:>8} R={:>8} Wgood {:>8} History: {:>8} m_last_sample_time={:>8}", + (cts.delay > 0 ? "SLEEP" : ""), + m_name, + cts.average, + M, + cts.delay, + E, + Enow, + M, + cts.window, + cts.recomendetDataSize, + Wgood, + history_str, + m_last_sample_time); } } diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index ae4430b8..b22c994c 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -28,7 +28,7 @@ #include "wipeable_string.h" #include "memwipe.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include namespace epee diff --git a/contrib/epee/tests/src/misc/test_math.h b/contrib/epee/tests/src/misc/test_math.h index 4baf4da7..bf0d9a72 100644 --- a/contrib/epee/tests/src/misc/test_math.h +++ b/contrib/epee/tests/src/misc/test_math.h @@ -37,13 +37,13 @@ bool test_median() LOG_PRINT_L0("Testing median"); std::vector sz; size_t m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 0, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 0, false, "test failed"); sz.push_back(1); m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 1, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 1, false, "test failed"); sz.push_back(10); m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 5, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 5, false, "test failed"); sz.clear(); sz.resize(3); @@ -51,7 +51,7 @@ bool test_median() sz[1] = 9; sz[2] = 3; m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 3, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 3, false, "test failed"); sz.clear(); sz.resize(4); @@ -60,7 +60,7 @@ bool test_median() sz[2] = 22; sz[3] = 60; m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 41, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 41, false, "test failed"); sz.clear(); sz.resize(5); @@ -70,7 +70,7 @@ bool test_median() sz[3] = 60; sz[4] = 11; m = misc_utils::median(sz); - CHECK_AND_ASSERT_MES(m == 22, false, "test failed"); + GULPS_CHECK_AND_ASSERT_MES(m == 22, false, "test failed"); return true; } } diff --git a/contrib/epee/tests/src/net/test_net.h b/contrib/epee/tests/src/net/test_net.h index a1ba7b63..4f55d5e9 100644 --- a/contrib/epee/tests/src/net/test_net.h +++ b/contrib/epee/tests/src/net/test_net.h @@ -270,11 +270,11 @@ inline bool do_run_test_server() net_utils::connection_context_base cntxt_1; bool r = srv1.connect("127.0.0.1", string_tools::num_to_string_fast(port2), 5000, cntxt_1); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); net_utils::connection_context_base cntxt_2; r = srv2.connect("127.0.0.1", string_tools::num_to_string_fast(port1), 5000, cntxt_2); - CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "connect to server failed"); while(true) { @@ -311,7 +311,7 @@ inline bool do_test2_work_with_srv(test_levin_server &srv, int port) { net_utils::connection_context_base cntxt_local = AUTO_VAL_INIT(cntxt_local); bool r = srv.connect_async("127.0.0.1", string_tools::num_to_string_fast(port), 5000, [&srv, &port, &wait_event, &i, &cntxt_local](const net_utils::connection_context_base &cntxt, const boost::system::error_code &ec) { - CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " << ec.message()); + GULPS_CHECK_AND_ASSERT_MES(!ec, void(), "Some problems at connect, message: " , ec.message()); cntxt_local = cntxt; LOG_PRINT_L0("Invoking command 1 to " << port); COMMAND_EXAMPLE_1::request arg = AUTO_VAL_INIT(arg); @@ -320,7 +320,7 @@ inline bool do_test2_work_with_srv(test_levin_server &srv, int port) int port_ = port; boost::mutex &wait_event_ = wait_event; int r = srv.invoke_async(cntxt.m_connection_id, COMMAND_EXAMPLE_1::ID, arg, [port_, &wait_event_](int code, const COMMAND_EXAMPLE_1::request &rsp, const net_utils::connection_context_base &cntxt) { - CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke"); + GULPS_CHECK_AND_ASSERT_MES(code > 0, void(), "Failed to invoke"); LOG_PRINT_L0("command 1 invoke to " << port_ << " OK."); wait_event_.unlock(); }); diff --git a/contrib/epee/tests/src/storages/portable_storages_test.h b/contrib/epee/tests/src/storages/portable_storages_test.h index 87a7a92f..28a5c68e 100644 --- a/contrib/epee/tests/src/storages/portable_storages_test.h +++ b/contrib/epee/tests/src/storages/portable_storages_test.h @@ -42,7 +42,7 @@ struct port_test_struct_sub { std::string m_str; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(port_test_struct_sub) KV_SERIALIZE_VAL(m_str) END_KV_SERIALIZE_MAP() }; @@ -83,7 +83,7 @@ struct port_test_struct port_test_struct_sub m_subobj; std::list m_list_of_self; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(port_test_struct) KV_SERIALIZE_VAL(m_str) KV_SERIALIZE_VAL(m_uint64) KV_SERIALIZE_VAL(m_uint32) diff --git a/contrib/epee/tests/src/storages/storage_tests.h b/contrib/epee/tests/src/storages/storage_tests.h index da4d1412..19579fd5 100644 --- a/contrib/epee/tests/src/storages/storage_tests.h +++ b/contrib/epee/tests/src/storages/storage_tests.h @@ -97,7 +97,7 @@ bool test_storages(const std::string &tests_folder) LOG_PRINT_L0("Loading test struct from storage..."); test_struct t2; bool res = epee::StorageNamed::load_struct_from_storage_file(t2, (storage_folder / +"valid_storage.bin").string()); - CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin"); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to load valid_storage.bin"); LOG_PRINT_L0("Comparing generated and loaded test struct..."); if(!(t == t2)) @@ -106,19 +106,19 @@ bool test_storages(const std::string &tests_folder) LOG_PRINT_L0("Loading broken archive 1..."); test_struct t3; res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder / +"invalid_storage_1.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not "); + GULPS_CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_1.bin loaded, but should not "); LOG_PRINT_L0("Loading broken archive 2..."); res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder / +"invalid_storage_2.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not "); + GULPS_CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_2.bin loaded, but should not "); LOG_PRINT_L0("Loading broken archive 3..."); res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder / +"invalid_storage_3.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); + GULPS_CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); LOG_PRINT_L0("Loading broken archive 4..."); res = epee::StorageNamed::load_struct_from_storage_file(t3, (storage_folder / +"invalid_storage_4.bin").string()); - CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); + GULPS_CHECK_AND_ASSERT_MES(!res, false, "invalid_storage_3.bin loaded, but should not "); return true; } diff --git a/doc/burned_premine_keyimages/key_images.7z b/doc/burned_premine_keyimages/key_images.7z new file mode 100644 index 00000000..086125bf Binary files /dev/null and b/doc/burned_premine_keyimages/key_images.7z differ diff --git a/doc/compiling.md b/doc/compiling.md new file mode 100644 index 00000000..9f1b9bd7 --- /dev/null +++ b/doc/compiling.md @@ -0,0 +1,399 @@ +## Compiling Ryo from source + +### Dependencies + +The following table summarizes the tools and libraries required to build. A +few of the libraries are also included in this repository (marked as +"Vendored"). By default, the build uses the library installed on the system, +and ignores the vendored sources. However, if no library is found installed on +the system, then the vendored source will be built and used. The vendored +sources are also used for statically-linked builds because distribution +packages often include only shared library binaries (`.so`) but not static +library archives (`.a`). + +| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Fedora | Optional | Purpose | +| ------------ | ------------- | -------- | ------------------ | ------------ | ----------------- | -------- | -------------- | +| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | `gcc` | NO | | +| CMake | 3.0.0 | NO | `cmake` | `cmake` | `cmake` | NO | | +| pkg-config | any | NO | `pkg-config` | `base-devel` | `pkgconf` | NO | | +| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | NO | C++ libraries | +| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `openssl-devel` | NO | sha256 sum | +| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `cppzmq-devel` | NO | ZeroMQ library | +| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver | +| nasm | ? | NO | `nasm` | `nasm` | `nasm` | YES | 64bit elliptic curve | +| libsodium | ? | NO | `libsodium-dev` | ? | `libsodium-devel` | NO | libsodium | +| libminiupnpc | 2.0 | YES | `libminiupnpc-dev` | `miniupnpc` | `miniupnpc-devel` | YES | NAT punching | +| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces | +| liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind | +| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | YES | Input editing | +| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `ldns-devel` | YES | SSL toolkit | +| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | YES | XML parsing | +| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite | +| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation | +| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation | + + +[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must +build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ``` + +Debian / Ubuntu one liner for all dependencies +``` sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev``` + +### Cloning the repository + +This repo does not use submodules, so simply clone this repo: + +`$ git clone https://github.com/ryo-currency/ryo-currency.git` + +If you already have a repo cloned, initialize and update: + +`$ cd ryo-currency` + +### Build instructions + +Ryo uses the CMake build system and a top-level [Makefile](Makefile) that +invokes cmake commands as needed. + +#### On Linux and OS X + +* Install the dependencies +* Change to the root of the source code directory, change to the most recent release branch, and build: + + cd ryo-currency + git checkout tags/0.4.0.0 + make + + *Optional*: If your machine has several cores and enough memory, enable + parallel build by running `make -j` instead of `make`. For + this to be worthwhile, the machine should have one core and about 2GB of RAM + available per thread. + + *Note*: If cmake can not find zmq.hpp file on OS X, installing `zmq.hpp` from + https://github.com/zeromq/cppzmq to `/usr/local/include` should fix that error. + + *Note*: The instructions above will compile the most stable release of the + Ryo software. If you would like to use and test the most recent software, + use ```git checkout master```. The master branch may contain updates that are + both unstable and incompatible with release software, though testing is always + encouraged. + +* The resulting executables can be found in `build/release/bin` + +* Add `PATH="$PATH:$HOME/ryo/build/release/bin"` to `.profile` + +* Run Ryo with `ryod --detach` + +* **Optional**: build and run the test suite to verify the binaries: + + make release-test + + *NOTE*: `core_tests` test may take a few hours to complete. + +* **Optional**: to build binaries suitable for debugging: + + make debug + +* **Optional**: to build statically-linked binaries: + + make release-static + +Dependencies need to be built with -fPIC. Static libraries usually aren't, so you may have to build them yourself with -fPIC. Refer to their documentation for how to build them. + +* **Optional**: build documentation in `doc/html` (omit `HAVE_DOT=YES` if `graphviz` is not installed): + + HAVE_DOT=YES doxygen Doxyfile + +#### On the Raspberry Pi + +Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (2017-09-07 or later) from https://www.raspberrypi.org/downloads/raspbian/. If you are using Raspian Jessie, [please see note in the following section](#note-for-raspbian-jessie-users). + +* `apt-get update && apt-get upgrade` to install all of the latest software + +* Install the dependencies for Ryo from the 'Debian' column in the table above. + +* Enable zram: +``` + sudo zramctl --find --size=1024M # Note the device name + sudo mkswap + sudo swapon +``` +* Clone ryo and checkout most recent release version: +``` + git clone https://github.com/ryo-currency/ryo-currency.git + cd ryo-currency + git checkout tags/0.2.0 +``` +* Build: +``` + make release +``` +* Wait 4-6 hours + +* The resulting executables can be found in `build/release/bin` + +* Add `PATH="$PATH:$HOME/ryo/build/release/bin"` to `.profile` + +* Run Ryo with `ryod --detach` + +* You may wish to reduce the size of the swap file after the build has finished, and delete the boost directory from your home directory + +#### *Note for Raspbian Jessie users:* + +If you are using the older Raspbian Jessie image, compiling Ryo is a bit more complicated. The version of Boost available in the Debian Jessie repositories is too old to use with Ryo, and thus you must compile a newer version yourself. The following explains the extra steps, and has been tested on a Raspberry Pi 2 with a clean install of minimal Raspbian Jessie. + +* As before, `apt-get update && apt-get upgrade` to install all of the latest software, and enable zram + +``` + sudo zramctl --find --size=1024M # Note the device name + sudo mkswap + sudo swapon +``` + +* Then, install the dependencies for Ryo except `libunwind` and `libboost-all-dev` + +* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*` to remove a previous version if you're not using a clean install): +``` + cd + wget https://sourceforge.net/projects/boost/files/boost/1.64.0/boost_1_64_0.tar.bz2 + tar xvfo boost_1_64_0.tar.bz2 + cd boost_1_64_0 + ./bootstrap.sh + sudo ./b2 +``` +* Wait ~8 hours +``` + sudo ./bjam install +``` +* Wait ~4 hours + +* From here, follow the [general Raspberry Pi instructions](#on-the-raspberry-pi) from the "Clone ryo and checkout most recent release version" step. + +#### On Windows: + +Binaries for Windows are built on Windows using the MinGW toolchain within +[MSYS2 environment](http://msys2.github.io). The MSYS2 environment emulates a +POSIX system. The toolchain runs within the environment and *cross-compiles* +binaries that can run outside of the environment as a regular Windows +application. + +**Preparing the Build Environment** + +* Download and install the [MSYS2 installer](http://msys2.github.io), either the 64-bit or the 32-bit package, depending on your system. +* Open the MSYS shell via the `MSYS2 Shell` shortcut +* Update packages using pacman: + + pacman -Syuu + +* Exit the MSYS shell using Alt+F4 +* Edit the properties for the `MSYS2 Shell` shortcut changing "msys2_shell.bat" to "msys2_shell.cmd -mingw64" for 64-bit builds or "msys2_shell.cmd -mingw32" for 32-bit builds +* Restart MSYS shell via modified shortcut and update packages again using pacman: + + pacman -Syuu + + +* Install dependencies: + + To build for 64-bit Windows: + + pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium + + To build for 32-bit Windows: + + pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium + +* Open the MingW shell via `MinGW-w64-Win64 Shell` shortcut on 64-bit Windows + or `MinGW-w64-Win64 Shell` shortcut on 32-bit Windows. Note that if you are + running 64-bit Windows, you will have both 64-bit and 32-bit MinGW shells. + +**Cloning** + +* To git clone, run: + + git clone https://github.com/ryo-currency/ryo-currency.git + +**Building** + +* Change to the cloned directory, run: + + cd ryo-currency + +* If you would like a specific [version/tag](https://github.com/ryo-currency/ryo-currency/tags), do a git checkout for that version. eg. '0.2.0'. If you dont care about the version and just want binaries from master, skip this step: + + git checkout 0.2.0 + +* If you are on a 64-bit system, run: + + make release-static-win64 + +* If you are on a 32-bit system, run: + + make release-static-win32 + +* The resulting executables can be found in `build/release/bin` + +* **Optional**: to build Windows binaries suitable for debugging on a 64-bit system, run: + + make debug-static-win64 + +* **Optional**: to build Windows binaries suitable for debugging on a 32-bit system, run: + + make debug-static-win32 + +* The resulting executables can be found in `build/debug/bin` + +### On FreeBSD: + +The project can be built from scratch by following instructions for Linux above. If you are running ryo in a jail you need to add the flag: `allow.sysvipc=1` to your jail configuration, otherwise lmdb will throw the error message: `Failed to open lmdb environment: Function not implemented`. + +We expect to add Ryo into the ports tree in the near future, which will aid in managing installations using ports or packages. + +### On OpenBSD: + +#### OpenBSD < 6.2 + +This has been tested on OpenBSD 5.8. + +You will need to add a few packages to your system. `pkg_add db cmake gcc gcc-libs g++ miniupnpc gtest`. + +The doxygen and graphviz packages are optional and require the xbase set. + +The Boost package has a bug that will prevent librpc.a from building correctly. In order to fix this, you will have to Build boost yourself from scratch. Follow the directions here (under "Building Boost"): +https://github.com/bitcoin/bitcoin/blob/master/doc/build-openbsd.md + +You will have to add the serialization, date_time, and regex modules to Boost when building as they are needed by Ryo. + +To build: `env CC=egcc CXX=eg++ CPP=ecpp DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/path/to/the/boost/you/built make release-static-64` + +#### OpenBSD >= 6.2 + +You will need to add a few packages to your system. `pkg_add cmake miniupnpc zeromq libiconv`. + +The doxygen and graphviz packages are optional and require the xbase set. + + +Build the Boost library using clang. This guide is derived from: https://github.com/bitcoin/bitcoin/blob/master/doc/build-openbsd.md + +We assume you are compiling with a non-root user and you have `doas` enabled. + +Note: do not use the boost package provided by OpenBSD, as we are installing boost to `/usr/local`. + +``` +# Create boost building directory +mkdir ~/boost +cd ~/boost + +# Fetch boost source +ftp -o boost_1_64_0.tar.bz2 https://netcologne.dl.sourceforge.net/project/boost/boost/1.64.0/boost_1_64_0.tar.bz2 + +# MUST output: (SHA256) boost_1_64_0.tar.bz2: OK +echo "7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332 boost_1_64_0.tar.bz2" | sha256 -c +tar xfj boost_1_64_0.tar.bz2 + +# Fetch and apply boost patches, required for OpenBSD +ftp -o boost_test_impl_execution_monitor_ipp.patch https://raw.githubusercontent.com/openbsd/ports/bee9e6df517077a7269ff0dfd57995f5c6a10379/devel/boost/patches/patch-boost_test_impl_execution_monitor_ipp +ftp -o boost_config_platform_bsd_hpp.patch https://raw.githubusercontent.com/openbsd/ports/90658284fb786f5a60dd9d6e8d14500c167bdaa0/devel/boost/patches/patch-boost_config_platform_bsd_hpp + +# MUST output: (SHA256) boost_config_platform_bsd_hpp.patch: OK +echo "1f5e59d1154f16ee1e0cc169395f30d5e7d22a5bd9f86358f738b0ccaea5e51d boost_config_platform_bsd_hpp.patch" | sha256 -c +# MUST output: (SHA256) boost_test_impl_execution_monitor_ipp.patch: OK +echo "30cec182a1437d40c3e0bd9a866ab5ddc1400a56185b7e671bb3782634ed0206 boost_test_impl_execution_monitor_ipp.patch" | sha256 -c + +cd boost_1_64_0 +patch -p0 < ../boost_test_impl_execution_monitor_ipp.patch +patch -p0 < ../boost_config_platform_bsd_hpp.patch + +# Start building boost +echo 'using clang : : c++ : "-fvisibility=hidden -fPIC" "" "ar" "strip" "ranlib" "" : ;' > user-config.jam +./bootstrap.sh --without-icu --with-libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale --with-toolset=clang +./b2 toolset=clang cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" -sICONV_PATH=/usr/local +doas ./b2 -d0 runtime-link=shared threadapi=pthread threading=multi link=static variant=release --layout=tagged --build-type=complete --user-config=user-config.jam -sNO_BZIP2=1 -sICONV_PATH=/usr/local --prefix=/usr/local install +``` + +Build cppzmq + +Build the cppzmq bindings. + +We assume you are compiling with a non-root user and you have `doas` enabled. + +``` +# Create cppzmq building directory +mkdir ~/cppzmq +cd ~/cppzmq + +# Fetch cppzmq source +ftp -o cppzmq-4.2.3.tar.gz https://github.com/zeromq/cppzmq/archive/v4.2.3.tar.gz + +# MUST output: (SHA256) cppzmq-4.2.3.tar.gz: OK +echo "3e6b57bf49115f4ae893b1ff7848ead7267013087dc7be1ab27636a97144d373 cppzmq-4.2.3.tar.gz" | sha256 -c +tar xfz cppzmq-4.2.3.tar.gz + +# Start building cppzmq +cd cppzmq-4.2.3 +mkdir build +cd build +cmake .. +doas make install +``` + +Build Ryo: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local make release-static` + +### On Solaris: + +The default Solaris linker can't be used, you have to install GNU ld, then run cmake manually with the path to your copy of GNU ld: + + mkdir -p build/release + cd build/release + cmake -DCMAKE_LINKER=/path/to/ld -D CMAKE_BUILD_TYPE=Release ../.. + cd ../.. + +Then you can run make as usual. + +### On Linux for Android (using docker): + + # Build image (select android64.Dockerfile for aarch64) + cd utils/build_scripts/ && docker build -f android32.Dockerfile -t ryo-android . + # Create container + docker create -it --name ryo-android ryo-android bash + # Get binaries + docker cp ryo-android:/opt/android/ryo/build/release/bin . + +### Building portable statically linked binaries + +By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets: + +* ```make release-static-linux-x86_64``` builds binaries on Linux on x86_64 portable across POSIX systems on x86_64 processors +* ```make release-static-linux-i686``` builds binaries on Linux on x86_64 or i686 portable across POSIX systems on i686 processors +* ```make release-static-linux-armv8``` builds binaries on Linux portable across POSIX systems on armv8 processors +* ```make release-static-linux-armv7``` builds binaries on Linux portable across POSIX systems on armv7 processors +* ```make release-static-linux-armv6``` builds binaries on Linux portable across POSIX systems on armv6 processors +* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems +* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems + + +## Running ryod + +The build places the binary in `bin/` sub-directory within the build directory +from which cmake was invoked (repository root by default). To run in +foreground: + + ./bin/ryod + +To list all available options, run `./bin/ryod --help`. Options can be +specified either on the command line or in a configuration file passed by the +`--config-file` argument. To specify an option in the configuration file, add +a line with the syntax `argumentname=value`, where `argumentname` is the name +of the argument without the leading dashes, for example `log-level=1`. + +To run in background: + + ./bin/ryod --log-file ryod.log --detach + +To run as a systemd service, copy +[ryod.service](utils/systemd/ryod.service) to `/etc/systemd/system/` and +[ryod.conf](utils/conf/ryod.conf) to `/etc/`. The [example +service](utils/systemd/ryod.service) assumes that the user `ryo` exists +and its home is the data directory specified in the [example +config](utils/conf/ryod.conf). + +If you're on Mac, you may need to add the `--max-concurrency 1` option to +ryo-wallet-cli, and possibly ryod, if you get crashes refreshing. diff --git a/doc/debugging.md b/doc/debugging.md new file mode 100644 index 00000000..d92a2d5d --- /dev/null +++ b/doc/debugging.md @@ -0,0 +1,49 @@ +# Debugging + +This section contains general instructions for debugging failed installs or problems encountered with Ryo. First ensure you are running the latest version built from the github repo. + +### Obtaining stack traces and core dumps on Unix systems + +We generally use the tool `gdb` (GNU debugger) to provide stack trace functionality, and `ulimit` to provide core dumps in builds which crash or segfault. + +* To use gdb in order to obtain a stack trace for a build that has stalled: + +Run the build. + +Once it stalls, enter the following command: + +``` +gdb /path/to/ryod `pidof ryod` +``` + +Type `thread apply all bt` within gdb in order to obtain the stack trace + +* If however the core dumps or segfaults: + +Enter `ulimit -c unlimited` on the command line to enable unlimited filesizes for core dumps + +Enter `echo core | sudo tee /proc/sys/kernel/core_pattern` to stop cores from being hijacked by other tools + +Run the build. + +When it terminates with an output along the lines of "Segmentation fault (core dumped)", there should be a core dump file in the same directory as ryod. It may be named just `core`, or `core.xxxx` with numbers appended. + +You can now analyse this core dump with `gdb` as follows: + +`gdb /path/to/ryod /path/to/dumpfile` + +Print the stack trace with `bt` + +* To run ryo within gdb: + +Type `gdb /path/to/ryod` + +Pass command-line options with `--args` followed by the relevant arguments + +Type `run` to run ryod + +### Analysing memory corruption + +We use the tool `valgrind` for this. + +Run with `valgrind /path/to/ryod`. It will be slow. \ No newline at end of file diff --git a/doc/img/RM.png b/doc/img/RM.png new file mode 100644 index 00000000..39054077 Binary files /dev/null and b/doc/img/RM.png differ diff --git a/doc/img/ecc-banner.png b/doc/img/ecc-banner.png new file mode 100644 index 00000000..571976b5 Binary files /dev/null and b/doc/img/ecc-banner.png differ diff --git a/doc/img/emission-block.png b/doc/img/emission-block.png new file mode 100644 index 00000000..0d1f7041 Binary files /dev/null and b/doc/img/emission-block.png differ diff --git a/doc/img/emission-curve.png b/doc/img/emission-curve.png new file mode 100644 index 00000000..42a54b81 Binary files /dev/null and b/doc/img/emission-curve.png differ diff --git a/doc/img/github.png b/doc/img/github.png new file mode 100644 index 00000000..011a5a0f Binary files /dev/null and b/doc/img/github.png differ diff --git a/doc/img/main_banner.png b/doc/img/main_banner.png new file mode 100644 index 00000000..e5306f75 Binary files /dev/null and b/doc/img/main_banner.png differ diff --git a/doc/lmdb.md b/doc/lmdb.md new file mode 100644 index 00000000..ac91d1cc --- /dev/null +++ b/doc/lmdb.md @@ -0,0 +1,11 @@ +# LMDB + +There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command: + +`cd ~/ryo/external/db_drivers/liblmdb && make` + +The output of `mdb_stat -ea ` will indicate inconsistencies in the blocks, block_heights and block_info table. + +The output of `mdb_dump -s blocks ` and `mdb_dump -s block_info ` is useful for indicating whether blocks and block_info contain the same keys. + +These records are dumped as hex data, where the first line is the key and the second line is the data. \ No newline at end of file diff --git a/doc/pgp_keys.md b/doc/pgp_keys.md index 69ab41ae..19354417 100644 --- a/doc/pgp_keys.md +++ b/doc/pgp_keys.md @@ -67,3 +67,37 @@ Nla4ixBctXWPewAyobNaN+EGJj99TMuz/3EMtxSzh//u2czenic3IUzoG1jSWwi1 =JTYP -----END PGP PUBLIC KEY BLOCK----- ``` + +## Key @mosu-forge +``` +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQENBFsQeDEBCAC6FipGNqhvlplhjoFvqUqAxreOb4/qi5eSTnzoeGlb3XEBlifV +z5d6aSQqZXjDSkrZqjh57Lkv1DugZpz/FLTVuy+b7stqxwvlQDyRxZg7871sTDh5 +ZG1CMN6rHU4wYq081+/gRDOz96TCl40geT/EKBXTPoXbVh6h1UWC5t47JqHYMFe1 +aqdqQDF+1pn5e5b1Dxe3U9B/rlTb1darb04ENNqGaaX2rrDn5d2DEv7a0/XLB2Nc +VrzbUH+3LyxgO1smzDOJHn5dia7z4LUsE10KQijwOEZtxYuMWC+KTyVubGkOVYVp +EQ4CAvHPHXWb0lyaJnP9jBlWvR1Mvznkdwi1ABEBAAG0Jm1vc3VfZm9yZ2UgPG1v +c3UuZm9yZ2VAcHJvdG9ubWFpbC5jb20+iQFOBBMBCAA4FiEEx8qIjI7MgV9v9hnk +g6LJxzvxIGMFAlsQeDECGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQg6LJ +xzvxIGNNVgf/SdwxQegQEPKo7j2vj8UhtfFX3sAxpY4ko3YX88taEZlGSSBFtW1U +0WyfBi3kdeYs8zhN3ZjnjVtFJvnjDETLu4EPAuSrDyrz3rVaMqFha8mqFvHJUC26 +phoJC3bM1/9pgmvgUJfVj4i3hoAPNSBnB7OkefFnea/OGow4NHtcvOTRDNTbZ675 +3kvmCMxv/iSfMm1oQmO4rlnBkBF5Hh7rF0hQyG3d+8iuzckaxy/zjXWRKzSX2LsZ +KXHM6BTBNq6SXnXyJ5D8meT+0sMUsxN4yblwKtFosQpVOtoQc4YMq17NWifnBedZ +qs50iIawUaBD/BBXXVOEfObxU1Ct1lGCErkBDQRbEHgxAQgArKfVkyltydCvCB11 +JERzpkvKOWEyyAA8Qrbb+6mbYlqT3Uf/+ypnj1/lJu5xfNhT9GIGR5vEDr2ERYlJ +uQ8kqnKY41oaLXr2p1U0Wp42AJX4m9XUXsiGocZpDmAluOKtXJocUoMrT4zdkviS +n2j3Vr1MPj8MOYmAg6Nl4/3nwYrHe1PN75kDjk49tf95VvnCIolilRAMXcgtKl/o +WxXFUXndOBgV2ywY7v7IGBvqKGKCz95ItJ4EKhDWs1EiCHtrGnd+OHNBjecj95vh +SRDdUFRpWIUpwjoGFKE5C0he4MS4+CDy5p8jAKUQgfWVhFmM3st8po0uTbLB5Za4 +0wv6wwARAQABiQE2BBgBCAAgFiEEx8qIjI7MgV9v9hnkg6LJxzvxIGMFAlsQeDEC +GwwACgkQg6LJxzvxIGPZ9wgAmYRdNADoPO4uxC4gP+0XjDd5W+vy1qDSXDCAqaAD +aU+B22NOwx48XlcHSg5rvzoUqoXxtdiYMR9tQS2RF1OfzNIRnJy5Jqrv7ulOV63B +n74gOGa2ypFiFj50i1Zvu/80CPDpc4Cg5csqtzslDMxiuNz+Wh+qQyYlVrV9r2N8 +ejaKFk9znjGw3fo/SxXMOncZb7yCaxeqT82/A+N9WMiUIJIhYyenYQ1uFK3lkzTK +hl0wDD1Qnrwz49v1z60+7ARUltjog6TqcXPsxFarLLo1f0kx/YPBM2jcKQ1uBFtR +8xJ0CkjYof4QDMRI9/Dft+FOzNy92o3m1s6fXcISWJ1YNw== +=ts23 +-----END PGP PUBLIC KEY BLOCK----- +``` diff --git a/doc/sumokoin.md b/doc/sumokoin.md new file mode 100644 index 00000000..b933a9ee --- /dev/null +++ b/doc/sumokoin.md @@ -0,0 +1,12 @@ +## What's your history with Sumokoin? +You can read [one-page](https://www.reddit.com/r/CryptoCurrency/comments/9eqa1x/blowing_the_lid_off_sumokoin_scam) list of sumokoin scam, that lead to partition. In short: we parted ways after one of the Sumo devs failed to disclose with the public a 400 000 coins premine unlocking years earlier [1](https://np.reddit.com/r/ryocurrency/comments/8ms1fx/on_an_epic_fail_hidden_premines_doctored/). Then two other team members resigned for a week [2](http://archive.is/obWug), one of which came back declaring "the "_i am getting out" was a mislead to earn time_" [3](http://archive.is/NdOKU). + +## I have Sumokoin, how can I claim my Ryo? +- You can claim your Ryo, **if you had Sumokoin before they forked at block #137500**. Ryo Currency as a chain fork kept all the transactions -and thus coins you had in your wallet- up and until Sumokoin forked at block #137500. To further secure your Ryo, we're going to tie the coins to a block after the fork. +- First, install the latest Ryo [wallet](https://ryo-currency.com/wallet/). Run it and generate a new wallet. Write down the seed words. Copy the PRIMARY ADDRESS under the RECEIVE tab. Then from the Ryo wallet Atom, click MENU - SWITCH WALLET » RESTORE WALLET FROM SEED and restore your Ryo from the same seeds used for your old Sumokoin wallet. +- Send all your coins to the new Ryo PRIMARY ADDRESS you copied before. +After this, you can safely transact Sumokoin, it's important to first move your Ryo, before you move your Sumokoin. +- If you are comfortable using the CLI, you can just SWEEP ALL Ryo to yourself instead of all the above. + +## How can I verify that premine was burnt on fork? +Use [these](/doc/verify_premine_burn_instructions.md) instructions. \ No newline at end of file diff --git a/doc/tor_readline.md b/doc/tor_readline.md new file mode 100644 index 00000000..adc19e7d --- /dev/null +++ b/doc/tor_readline.md @@ -0,0 +1,45 @@ +## Using Tor + +While Ryo isn't made to integrate with Tor, it can be used wrapped with torsocks, by +setting the following configuration parameters and environment variables: + +* `--p2p-bind-ip 127.0.0.1` on the command line or `p2p-bind-ip=127.0.0.1` in + ryod.conf to disable listening for connections on external interfaces. +* `--no-igd` on the command line or `no-igd=1` in ryod.conf to disable IGD + (UPnP port forwarding negotiation), which is pointless with Tor. +* `DNS_PUBLIC=tcp` or `DNS_PUBLIC=tcp://x.x.x.x` where x.x.x.x is the IP of the + desired DNS server, for DNS requests to go over TCP, so that they are routed + through Tor. When IP is not specified, ryod uses the default list of + servers defined in [src/common/dns_utils.cpp](src/common/dns_utils.cpp). +* `TORSOCKS_ALLOW_INBOUND=1` to tell torsocks to allow ryod to bind to interfaces + to accept connections from the wallet. On some Linux systems, torsocks + allows binding to localhost by default, so setting this variable is only + necessary to allow binding to local LAN/VPN interfaces to allow wallets to + connect from remote hosts. On other systems, it may be needed for local wallets + as well. +* Do NOT pass `--detach` when running through torsocks with systemd, (see + [utils/systemd/ryod.service](utils/systemd/ryod.service) for details). +* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050), + then use `--untrusted-daemon` unless it is your own hidden service. + +Example command line to start ryod through Tor: + + DNS_PUBLIC=tcp torsocks ryod --p2p-bind-ip 127.0.0.1 --no-igd + +### Using Tor on Tails + +TAILS ships with a very restrictive set of firewall rules. Therefore, you need +to add a rule to allow this connection too, in addition to telling torsocks to +allow inbound connections. Full example: + + sudo iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 18081 -j ACCEPT + DNS_PUBLIC=tcp torsocks ./ryod --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip 127.0.0.1 \ + --data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain + +## Using readline + +While `ryod` and `ryo-wallet-cli` do not use readline directly, most of the functionality can be obtained by running them via `rlwrap`. This allows command recall, edit capabilities, etc. It does not give autocompletion without an extra completion file, however. To use rlwrap, simply prepend `rlwrap` to the command line, eg: + +`rlwrap bin/ryo-wallet-cli --wallet-file /path/to/wallet` + +Note: rlwrap will save things like your seed and private keys, if you supply them on prompt. You may want to not use rlwrap when you use simplewallet to restore from seed, etc. \ No newline at end of file diff --git a/doc/verify_premine_burn_instructions.md b/doc/verify_premine_burn_instructions.md new file mode 100644 index 00000000..35fb028f --- /dev/null +++ b/doc/verify_premine_burn_instructions.md @@ -0,0 +1,32 @@ +You can verify premine burn, using Ryo Wallet Atom and its view-only wallet features. + +1. Download and install the latest verison or Ryo Wallet Atom: https://ryo-currency.com/wallet/#download +2. Download premine key image sets: https://github.com/ryo-currency/ryo-currency/blob/master/utils/burned_premine_keyimages/key_images.7z +3. Run Atom, choose "Restore view-only wallet". +4. When restoring view-only wallet, you will need wallet address + viewkey. Give any desired name for wallet, and set password if you wish (or hit "Enter" to set blank password). Use these addresses and viewkeys: + +> Wallet 1: Address: +> SumonzyoAnidrp3B6WhbntJLRJsPRD7LiSd2e5HjRV9h6qWj6ia2ihgRXn8ZwmwfQgZ1mL9EkcsBcELL4h84v1yhMF9opLgjM1j +> Viewkey: +> e6e58faa93dba88315f67f53cba9413ebf0f423badb62696aa28ce6c0db2df00 +> +> Wallet 2: Address: +> SumonzyopdC7egt7MWhJcNfR3ktmfWqPNcu3Sb9aejAZ48W4a1ZW95vjXyQDuLLg2gSN8GkP3474R2wRr1h9ggy2BUHhbrLJJ51 +> Viewkey: +> 25ba5fa5abb5f99962754001ff631e01684f9a59871d798a20a1658ba31c950c +> +> Wallet 3: Address: +> SumonzyoK3hCffFQ8djaKZhokmPZsiuEaeLfEtnJfTXVQV3ce3mNHKHQ5kYLPVfNMsS7dhmyHihvhfKU6xXCrmaL4RVDo8eR3gB +> Viewkey: +> 1a8c55e52f7f80da3dfd2eadf71a74afb3242c20168ad888b57f483dbc38b00e +> +> Dev Wallet: Address: +> Sumoo4aMxWbLgqVazxbiNNFSDyhBEonRf99KmceTEnYUCWUQR2gXF1617P8xQxaMcGi5BAU7juzThSTboV6e1gitSjkfjq2zgY2 +> Viewkey: +> e12497b6dc6c2cbaf7b311e54b93e4e5f6367acda69a49f9ef20c51d9c689f00 + +5. After clicking "open wallet" you will have to wait for sync to finish (watch bottom bar statistics). When finished - you will see incoming transactions. Since viewkey we used to restore wallet, doesn't show outgoing transactions or burn - we need to import key images. Navigate to "Wallet actions" dropdown and select "Manage key images" (It will become active when the sync process finishes), choose "import" option and press "browse" to navigate appropriate key in step [1]. +6. After import you will see the actual balance of wallet. In our case, since they are premine + dev wallets they will be close to 0 (barring some small donations). +![restore view-only wallet](https://i.imgur.com/tRlelTF.jpg) +![see incoming transfers](https://i.imgur.com/GolNK88.jpg) +![import key images to see final balance](https://i.imgur.com/kGlm4uq.jpg) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index ff8bf24c..28cabfee 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -78,8 +78,5 @@ else() endif() add_subdirectory(db_drivers) -add_subdirectory(easylogging++) # fmt is shipped as subtree add_subdirectory(fmt) -# activate extended color output for fmt -add_definitions(-DFMT_EXTENDED_COLORS) diff --git a/external/boost/archive/portable_binary_archive.hpp b/external/boost/archive/portable_binary_archive.hpp index a1f00b34..f29d83d1 100644 --- a/external/boost/archive/portable_binary_archive.hpp +++ b/external/boost/archive/portable_binary_archive.hpp @@ -22,7 +22,7 @@ #endif #include -#include +#include #include diff --git a/external/boost/archive/portable_binary_iarchive.hpp b/external/boost/archive/portable_binary_iarchive.hpp index 9c642e79..88bbaf29 100644 --- a/external/boost/archive/portable_binary_iarchive.hpp +++ b/external/boost/archive/portable_binary_iarchive.hpp @@ -234,7 +234,7 @@ BOOST_SERIALIZATION_REGISTER_ARCHIVE(portable_binary_iarchive) #include #include -#include +#include #include namespace boost @@ -263,12 +263,12 @@ portable_binary_iarchive::load_impl(boost::intmax_t &l, char maxsize) portable_binary_iarchive_exception()); char *cptr = reinterpret_cast(&l); -#ifdef BOOST_BIG_ENDIAN +#if BOOST_ENDIAN_BIG_BYTE cptr += (sizeof(boost::intmax_t) - size); #endif this->primitive_base_t::load_binary(cptr, size); -#ifdef BOOST_BIG_ENDIAN +#if BOOST_ENDIAN_BIG_BYTE if(m_flags & endian_little) #else if(m_flags & endian_big) diff --git a/external/boost/archive/portable_binary_oarchive.hpp b/external/boost/archive/portable_binary_oarchive.hpp index 3f7fa32e..79d1e19c 100644 --- a/external/boost/archive/portable_binary_oarchive.hpp +++ b/external/boost/archive/portable_binary_oarchive.hpp @@ -226,8 +226,7 @@ BOOST_SERIALIZATION_REGISTER_ARCHIVE(portable_binary_oarchive) // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org for updates, documentation, and revision history. - -#include +#include #include namespace boost @@ -269,7 +268,7 @@ portable_binary_oarchive::save_impl( else ll = l; char *cptr = reinterpret_cast(&ll); -#ifdef BOOST_BIG_ENDIAN +#if BOOST_ENDIAN_BIG_BYTE cptr += (sizeof(boost::intmax_t) - size); if(m_flags & endian_little) reverse_bytes(size, cptr); diff --git a/external/easylogging++/CMakeLists.txt b/external/easylogging++/CMakeLists.txt deleted file mode 100644 index 78795d54..00000000 --- a/external/easylogging++/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2014-2018, The Monero Project -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without modification, are -# permitted provided that the following conditions are met: -# -# 1. Redistributions of source code must retain the above copyright notice, this list of -# conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright notice, this list -# of conditions and the following disclaimer in the documentation and/or other -# materials provided with the distribution. -# -# 3. Neither the name of the 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 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. - -cmake_minimum_required(VERSION 2.8.7) - -project(easylogging CXX) - -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - -find_package(Threads) - -add_library(easylogging - easylogging++.cc) - -include_directories("${CMAKE_CURRENT_SOURCE_DIR}") -include_directories("${CMAKE_CURRENT_BINARY_DIR}") -target_link_libraries(easylogging - PRIVATE - ${CMAKE_THREAD_LIBS_INIT}) - -# GUI/libwallet install target -if (BUILD_GUI_DEPS) - if(IOS) - set(lib_folder lib-${ARCH}) - else() - set(lib_folder lib) - endif() - install(TARGETS easylogging - ARCHIVE DESTINATION ${lib_folder} - LIBRARY DESTINATION ${lib_folder}) -endif() -set_property(TARGET easylogging APPEND PROPERTY COMPILE_FLAGS "-fPIC") - diff --git a/external/easylogging++/ea_config.h b/external/easylogging++/ea_config.h deleted file mode 100644 index 4c74925d..00000000 --- a/external/easylogging++/ea_config.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#define ELPP_THREAD_SAFE -#define ELPP_DEFAULT_LOG_FILE "" -#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING -#define ELPP_NO_CHECK_MACROS -#define ELPP_WINSOCK2 -#define ELPP_NO_DEBUG_MACROS - -#ifdef EASYLOGGING_CC -#if !(!defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__) -#define ELPP_FEATURE_CRASH_LOG -#endif -#endif diff --git a/external/easylogging++/easylogging++.cc b/external/easylogging++/easylogging++.cc deleted file mode 100644 index 2143d973..00000000 --- a/external/easylogging++/easylogging++.cc +++ /dev/null @@ -1,3723 +0,0 @@ -// -// Bismillah ar-Rahmaan ar-Raheem -// -// Easylogging++ v9.94.1 -// Cross-platform logging library for C++ applications -// -// Copyright (c) 2017 muflihun.com -// -// This library is released under the MIT Licence. -// http://labs.muflihun.com/easyloggingpp/licence.php -// -// https://github.com/muflihun/easyloggingpp -// https://muflihun.github.io/easyloggingpp -// http://muflihun.com -// - -#define EASYLOGGING_CC -#include "easylogging++.h" - -#include - -#if defined(AUTO_INITIALIZE_EASYLOGGINGPP) -INITIALIZE_EASYLOGGINGPP -#endif - -namespace el -{ - -// el::base::utils -namespace base -{ -namespace utils -{ - -/// @brief Aborts application due with user-defined status -static void abort(int status, const std::string &reason) -{ - // Both status and reason params are there for debugging with tools like gdb etc - ELPP_UNUSED(status); - ELPP_UNUSED(reason); -#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) - // Ignore msvc critical error dialog - break instead (on debug mode) - _asm int 3 -#else -#ifdef NDEBUG - ::_exit(1); -#else - ::abort(); -#endif -#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) -} - -} // namespace utils -} // namespace base - -// el - -// LevelHelper - -const char *LevelHelper::convertToString(Level level) -{ - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if(level == Level::Global) - return "GLOBAL"; - if(level == Level::Debug) - return "DEBUG"; - if(level == Level::Info) - return "INFO"; - if(level == Level::Warning) - return "WARNING"; - if(level == Level::Error) - return "ERROR"; - if(level == Level::Fatal) - return "FATAL"; - if(level == Level::Verbose) - return "VERBOSE"; - if(level == Level::Trace) - return "TRACE"; - return "UNKNOWN"; -} - -struct StringToLevelItem -{ - const char *levelString; - Level level; -}; - -static struct StringToLevelItem stringToLevelMap[] = { - {"global", Level::Global}, - {"debug", Level::Debug}, - {"info", Level::Info}, - {"warning", Level::Warning}, - {"error", Level::Error}, - {"fatal", Level::Fatal}, - {"verbose", Level::Verbose}, - {"trace", Level::Trace}}; - -Level LevelHelper::convertFromString(const char *levelStr) -{ - for(auto &item : stringToLevelMap) - { - if(base::utils::Str::cStringCaseEq(levelStr, item.levelString)) - { - return item.level; - } - } - return Level::Unknown; -} - -Level LevelHelper::convertFromStringPrefix(const char *levelStr) -{ - if((strncmp(levelStr, "GLOBAL", 6) == 0) || (strncmp(levelStr, "global", 6) == 0)) - return Level::Global; - if((strncmp(levelStr, "DEBUG", 5) == 0) || (strncmp(levelStr, "debug", 5) == 0)) - return Level::Debug; - if((strncmp(levelStr, "INFO", 4) == 0) || (strncmp(levelStr, "info", 4) == 0)) - return Level::Info; - if((strncmp(levelStr, "WARNING", 7) == 0) || (strncmp(levelStr, "warning", 7) == 0)) - return Level::Warning; - if((strncmp(levelStr, "ERROR", 5) == 0) || (strncmp(levelStr, "error", 5) == 0)) - return Level::Error; - if((strncmp(levelStr, "FATAL", 5) == 0) || (strncmp(levelStr, "fatal", 5) == 0)) - return Level::Fatal; - if((strncmp(levelStr, "VERBOSE", 7) == 0) || (strncmp(levelStr, "verbose", 7) == 0)) - return Level::Verbose; - if((strncmp(levelStr, "TRACE", 5) == 0) || (strncmp(levelStr, "trace", 5) == 0)) - return Level::Trace; - return Level::Unknown; -} - -void LevelHelper::forEachLevel(base::type::EnumType *startIndex, const std::function &fn) -{ - base::type::EnumType lIndexMax = LevelHelper::kMaxValid; - do - { - if(fn()) - { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while(*startIndex <= lIndexMax); -} - -// ConfigurationTypeHelper - -const char *ConfigurationTypeHelper::convertToString(ConfigurationType configurationType) -{ - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if(configurationType == ConfigurationType::Enabled) - return "ENABLED"; - if(configurationType == ConfigurationType::Filename) - return "FILENAME"; - if(configurationType == ConfigurationType::Format) - return "FORMAT"; - if(configurationType == ConfigurationType::ToFile) - return "TO_FILE"; - if(configurationType == ConfigurationType::ToStandardOutput) - return "TO_STANDARD_OUTPUT"; - if(configurationType == ConfigurationType::SubsecondPrecision) - return "SUBSECOND_PRECISION"; - if(configurationType == ConfigurationType::PerformanceTracking) - return "PERFORMANCE_TRACKING"; - if(configurationType == ConfigurationType::MaxLogFileSize) - return "MAX_LOG_FILE_SIZE"; - if(configurationType == ConfigurationType::LogFlushThreshold) - return "LOG_FLUSH_THRESHOLD"; - return "UNKNOWN"; -} - -struct ConfigurationStringToTypeItem -{ - const char *configString; - ConfigurationType configType; -}; - -static struct ConfigurationStringToTypeItem configStringToTypeMap[] = { - {"enabled", ConfigurationType::Enabled}, - {"to_file", ConfigurationType::ToFile}, - {"to_standard_output", ConfigurationType::ToStandardOutput}, - {"format", ConfigurationType::Format}, - {"filename", ConfigurationType::Filename}, - {"subsecond_precision", ConfigurationType::SubsecondPrecision}, - {"milliseconds_width", ConfigurationType::MillisecondsWidth}, - {"performance_tracking", ConfigurationType::PerformanceTracking}, - {"max_log_file_size", ConfigurationType::MaxLogFileSize}, - {"log_flush_threshold", ConfigurationType::LogFlushThreshold}, -}; - -ConfigurationType ConfigurationTypeHelper::convertFromString(const char *configStr) -{ - for(auto &item : configStringToTypeMap) - { - if(base::utils::Str::cStringCaseEq(configStr, item.configString)) - { - return item.configType; - } - } - return ConfigurationType::Unknown; -} - -void ConfigurationTypeHelper::forEachConfigType(base::type::EnumType *startIndex, const std::function &fn) -{ - base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; - do - { - if(fn()) - { - break; - } - *startIndex = static_cast(*startIndex << 1); - } while(*startIndex <= cIndexMax); -} - -// Configuration - -Configuration::Configuration(const Configuration &c) : m_level(c.m_level), - m_configurationType(c.m_configurationType), - m_value(c.m_value) -{ -} - -Configuration &Configuration::operator=(const Configuration &c) -{ - if(&c != this) - { - m_level = c.m_level; - m_configurationType = c.m_configurationType; - m_value = c.m_value; - } - return *this; -} - -/// @brief Full constructor used to sets value of configuration -Configuration::Configuration(Level level, ConfigurationType configurationType, const std::string &value) : m_level(level), - m_configurationType(configurationType), - m_value(value) -{ -} - -void Configuration::log(el::base::type::ostream_t &os) const -{ - os << LevelHelper::convertToString(m_level) - << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) - << ELPP_LITERAL(" = ") << m_value.c_str(); -} - -/// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. -Configuration::Predicate::Predicate(Level level, ConfigurationType configurationType) : m_level(level), - m_configurationType(configurationType) -{ -} - -bool Configuration::Predicate::operator()(const Configuration *conf) const -{ - return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); -} - -// Configurations - -Configurations::Configurations(void) : m_configurationFile(std::string()), - m_isFromFile(false) -{ -} - -Configurations::Configurations(const std::string &configurationFile, bool useDefaultsForRemaining, - Configurations *base) : m_configurationFile(configurationFile), - m_isFromFile(false) -{ - parseFromFile(configurationFile, base); - if(useDefaultsForRemaining) - { - setRemainingToDefault(); - } -} - -bool Configurations::parseFromFile(const std::string &configurationFile, Configurations *base) -{ - // We initial assertion with true because if we have assertion diabled, we want to pass this - // check and if assertion is enabled we will have values re-assigned any way. - bool assertionPassed = true; - ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)) == true, - "Configuration file [" << configurationFile << "] does not exist!"); - if(!assertionPassed) - { - return false; - } - bool success = Parser::parseFromFile(configurationFile, this, base); - m_isFromFile = success; - return success; -} - -bool Configurations::parseFromText(const std::string &configurationsString, Configurations *base) -{ - bool success = Parser::parseFromText(configurationsString, this, base); - if(success) - { - m_isFromFile = false; - } - return success; -} - -void Configurations::setFromBase(Configurations *base) -{ - if(base == nullptr || base == this) - { - return; - } - base::threading::ScopedLock scopedLock(base->lock()); - for(Configuration *&conf : base->list()) - { - set(conf); - } -} - -bool Configurations::hasConfiguration(ConfigurationType configurationType) -{ - base::type::EnumType lIndex = LevelHelper::kMinValid; - bool result = false; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - if(hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) - { - result = true; - } - return result; - }); - return result; -} - -bool Configurations::hasConfiguration(Level level, ConfigurationType configurationType) -{ - base::threading::ScopedLock scopedLock(lock()); -#if ELPP_COMPILER_INTEL - // We cant specify template types here, Intel C++ throws compilation error - // "error: type name is not allowed" - return RegistryWithPred::get(level, configurationType) != nullptr; -#else - return RegistryWithPred::get(level, configurationType) != nullptr; -#endif // ELPP_COMPILER_INTEL -} - -void Configurations::set(Level level, ConfigurationType configurationType, const std::string &value) -{ - base::threading::ScopedLock scopedLock(lock()); - unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex - if(level == Level::Global) - { - unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either - } -} - -void Configurations::set(Configuration *conf) -{ - if(conf == nullptr) - { - return; - } - set(conf->level(), conf->configurationType(), conf->value()); -} - -void Configurations::setToDefault(void) -{ - setGlobally(ConfigurationType::Enabled, std::string("true"), true); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); -#else - ELPP_UNUSED(base::consts::kDefaultLogFile); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) -#if defined(ELPP_NO_LOG_TO_FILE) - setGlobally(ConfigurationType::ToFile, std::string("false"), true); -#else - setGlobally(ConfigurationType::ToFile, std::string("true"), true); -#endif // defined(ELPP_NO_LOG_TO_FILE) - setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); - setGlobally(ConfigurationType::SubsecondPrecision, std::string("3"), true); - setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); - setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); - setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); - - setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); - set(Level::Debug, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); -} - -void Configurations::setRemainingToDefault(void) -{ - base::threading::ScopedLock scopedLock(lock()); -#if defined(ELPP_NO_LOG_TO_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("false")); -#else - unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); -#endif // defined(ELPP_NO_LOG_TO_FILE) -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) - unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::SubsecondPrecision, std::string("3")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); - unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); - // INFO and WARNING are set to default by Level::Global - unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); - unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); - unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, - std::string("%datetime %level [%logger] [%func] [%loc] %msg")); -} - -bool Configurations::Parser::parseFromFile(const std::string &configurationFile, Configurations *sender, - Configurations *base) -{ - sender->setFromBase(base); - std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); - ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); - bool parsedSuccessfully = false; - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while(fileStream_.good()) - { - std::getline(fileStream_, line); - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; -} - -bool Configurations::Parser::parseFromText(const std::string &configurationsString, Configurations *sender, - Configurations *base) -{ - sender->setFromBase(base); - bool parsedSuccessfully = false; - std::stringstream ss(configurationsString); - std::string line = std::string(); - Level currLevel = Level::Unknown; - std::string currConfigStr = std::string(); - std::string currLevelStr = std::string(); - while(std::getline(ss, line)) - { - parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); - ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); - } - return parsedSuccessfully; -} - -void Configurations::Parser::ignoreComments(std::string *line) -{ - std::size_t foundAt = 0; - std::size_t quotesStart = line->find("\""); - std::size_t quotesEnd = std::string::npos; - if(quotesStart != std::string::npos) - { - quotesEnd = line->find("\"", quotesStart + 1); - while(quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') - { - // Do not erase slash yet - we will erase it in parseLine(..) while loop - quotesEnd = line->find("\"", quotesEnd + 2); - } - } - if((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) - { - if(foundAt < quotesEnd) - { - foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); - } - *line = line->substr(0, foundAt); - } -} - -bool Configurations::Parser::isLevel(const std::string &line) -{ - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); -} - -bool Configurations::Parser::isComment(const std::string &line) -{ - return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); -} - -bool Configurations::Parser::isConfig(const std::string &line) -{ - std::size_t assignment = line.find('='); - return line != "" && - ((line[0] >= 'A' && line[0] <= 'Z') || (line[0] >= 'a' && line[0] <= 'z')) && - (assignment != std::string::npos) && - (line.size() > assignment); -} - -bool Configurations::Parser::parseLine(std::string *line, std::string *currConfigStr, std::string *currLevelStr, - Level *currLevel, - Configurations *conf) -{ - ConfigurationType currConfig = ConfigurationType::Unknown; - std::string currValue = std::string(); - *line = base::utils::Str::trim(*line); - if(isComment(*line)) - return true; - ignoreComments(line); - *line = base::utils::Str::trim(*line); - if(line->empty()) - { - // Comment ignored - return true; - } - if(isLevel(*line)) - { - if(line->size() <= 2) - { - return true; - } - *currLevelStr = line->substr(1, line->size() - 2); - *currLevelStr = base::utils::Str::toUpper(*currLevelStr); - *currLevelStr = base::utils::Str::trim(*currLevelStr); - *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); - return true; - } - if(isConfig(*line)) - { - std::size_t assignment = line->find('='); - *currConfigStr = line->substr(0, assignment); - *currConfigStr = base::utils::Str::toUpper(*currConfigStr); - *currConfigStr = base::utils::Str::trim(*currConfigStr); - currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); - currValue = line->substr(assignment + 1); - currValue = base::utils::Str::trim(currValue); - std::size_t quotesStart = currValue.find("\"", 0); - std::size_t quotesEnd = std::string::npos; - if(quotesStart != std::string::npos) - { - quotesEnd = currValue.find("\"", quotesStart + 1); - while(quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') - { - currValue = currValue.erase(quotesEnd - 1, 1); - quotesEnd = currValue.find("\"", quotesEnd + 2); - } - } - if(quotesStart != std::string::npos && quotesEnd != std::string::npos) - { - // Quote provided - check and strip if valid - ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" - << currConfigStr << "]"); - ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); - if((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) - { - // Explicit check in case if assertion is disabled - currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); - } - } - } - ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); - ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); - if(*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) - { - return false; // unrecognizable level or config - } - conf->set(*currLevel, currConfig, currValue); - return true; -} - -void Configurations::unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string &value) -{ - Configuration *conf = RegistryWithPred::get(level, configurationType); - if(conf == nullptr) - { - unsafeSet(level, configurationType, value); - } -} - -void Configurations::unsafeSet(Level level, ConfigurationType configurationType, const std::string &value) -{ - Configuration *conf = RegistryWithPred::get(level, configurationType); - if(conf == nullptr) - { - registerNew(new Configuration(level, configurationType, value)); - } - else - { - conf->setValue(value); - } - if(level == Level::Global) - { - unsafeSetGlobally(configurationType, value, false); - } -} - -void Configurations::setGlobally(ConfigurationType configurationType, const std::string &value, - bool includeGlobalLevel) -{ - if(includeGlobalLevel) - { - set(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - set(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); -} - -void Configurations::unsafeSetGlobally(ConfigurationType configurationType, const std::string &value, - bool includeGlobalLevel) -{ - if(includeGlobalLevel) - { - unsafeSet(Level::Global, configurationType, value); - } - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); - return false; // Do not break lambda function yet as we need to set all levels regardless - }); -} - -// LogBuilder - -void LogBuilder::convertToColoredOutput(base::type::string_t *logLine, Level level) -{ - if(!m_termSupportsColor) - return; - const base::type::char_t *resetColor = ELPP_LITERAL("\x1b[0m"); - if(level == Level::Error || level == Level::Fatal) - *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; - else if(level == Level::Warning) - *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; - else if(level == Level::Debug) - *logLine = ELPP_LITERAL("\x1b[32m") + *logLine + resetColor; - else if(level == Level::Info) - *logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor; - else if(level == Level::Trace) - *logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor; -} - -// Logger - -Logger::Logger(const std::string &id, base::LogStreamsReferenceMap *logStreamsReference) : m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) -{ - initUnflushedCount(); -} - -Logger::Logger(const std::string &id, const Configurations &configurations, - base::LogStreamsReferenceMap *logStreamsReference) : m_id(id), - m_typedConfigurations(nullptr), - m_parentApplicationName(std::string()), - m_isConfigured(false), - m_logStreamsReference(logStreamsReference) -{ - initUnflushedCount(); - configure(configurations); -} - -Logger::Logger(const Logger &logger) -{ - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; -} - -Logger &Logger::operator=(const Logger &logger) -{ - if(&logger != this) - { - base::utils::safeDelete(m_typedConfigurations); - m_id = logger.m_id; - m_typedConfigurations = logger.m_typedConfigurations; - m_parentApplicationName = logger.m_parentApplicationName; - m_isConfigured = logger.m_isConfigured; - m_configurations = logger.m_configurations; - m_unflushedCount = logger.m_unflushedCount; - m_logStreamsReference = logger.m_logStreamsReference; - } - return *this; -} - -void Logger::configure(const Configurations &configurations) -{ - m_isConfigured = false; // we set it to false in case if we fail - initUnflushedCount(); - if(m_typedConfigurations != nullptr) - { - Configurations *c = const_cast(m_typedConfigurations->configurations()); - if(c->hasConfiguration(Level::Global, ConfigurationType::Filename)) - { - // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE - flush(); - } - } - base::threading::ScopedLock scopedLock(lock()); - if(m_configurations != configurations) - { - m_configurations.setFromBase(const_cast(&configurations)); - } - base::utils::safeDelete(m_typedConfigurations); - m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); - resolveLoggerFormatSpec(); - m_isConfigured = true; -} - -void Logger::reconfigure(void) -{ - ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); - configure(m_configurations); -} - -bool Logger::isValidId(const std::string &id) -{ - for(std::string::const_iterator it = id.begin(); it != id.end(); ++it) - { - if(!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) - { - return false; - } - } - return true; -} - -void Logger::flush(void) -{ - ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); - base::threading::ScopedLock scopedLock(lock()); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - flush(LevelHelper::castFromInt(lIndex), nullptr); - return false; - }); -} - -void Logger::flush(Level level, base::type::fstream_t *fs) -{ - if(fs == nullptr && m_typedConfigurations->toFile(level)) - { - fs = m_typedConfigurations->fileStream(level); - } - if(fs != nullptr) - { - fs->flush(); - m_unflushedCount.find(level)->second = 0; - } -} - -void Logger::initUnflushedCount(void) -{ - m_unflushedCount.clear(); - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); - return false; - }); -} - -void Logger::resolveLoggerFormatSpec(void) const -{ - base::type::EnumType lIndex = LevelHelper::kMinValid; - LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { - base::LogFormat *logFormat = - const_cast(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); - base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); - return false; - }); -} - -// el::base -namespace base -{ - -// el::base::utils -namespace utils -{ - -// File - -base::type::fstream_t *File::newFileStream(const std::string &filename) -{ - base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), - base::type::fstream_t::out -#if !defined(ELPP_FRESH_LOG_FILE) - | base::type::fstream_t::app -#endif - ); -#if defined(ELPP_UNICODE) - std::locale elppUnicodeLocale(""); -#if ELPP_OS_WINDOWS - std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16); - elppUnicodeLocale = elppUnicodeLocaleWindows; -#endif // ELPP_OS_WINDOWS - fs->imbue(elppUnicodeLocale); -#endif // defined(ELPP_UNICODE) - if(fs->is_open()) - { - fs->flush(); - } - else - { - base::utils::safeDelete(fs); - ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); - } - return fs; -} - -std::size_t File::getSizeOfFile(base::type::fstream_t *fs) -{ - if(fs == nullptr) - { - return 0; - } - std::streampos currPos = fs->tellg(); - fs->seekg(0, fs->end); - std::size_t size = static_cast(fs->tellg()); - fs->seekg(currPos); - return size; -} - -bool File::pathExists(const char *path, bool considerFile) -{ - if(path == nullptr) - { - return false; - } -#if ELPP_OS_UNIX - ELPP_UNUSED(considerFile); - struct stat st; - return (stat(path, &st) == 0); -#elif ELPP_OS_WINDOWS - DWORD fileType = GetFileAttributesA(path); - if(fileType == INVALID_FILE_ATTRIBUTES) - { - return false; - } - return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); -#endif // ELPP_OS_UNIX -} - -bool File::createPath(const std::string &path) -{ - if(path.empty()) - { - return false; - } - if(base::utils::File::pathExists(path.c_str())) - { - return true; - } - int status = -1; - - char *currPath = const_cast(path.c_str()); - std::string builtPath = std::string(); -#if ELPP_OS_UNIX - if(path[0] == '/') - { - builtPath = "/"; - } - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - // Use secure functions API - char *nextTok_ = nullptr; - currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_); - ELPP_UNUSED(nextTok_); -#endif // ELPP_OS_UNIX - while(currPath != nullptr) - { - builtPath.append(currPath); - builtPath.append(base::consts::kFilePathSeperator); -#if ELPP_OS_UNIX - status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0); -#elif ELPP_OS_WINDOWS - status = _mkdir(builtPath.c_str()); - currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_); -#endif // ELPP_OS_UNIX - } - if(status == -1) - { - ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); - return false; - } - return true; -} - -std::string File::extractPathFromFilename(const std::string &fullPath, const char *separator) -{ - if((fullPath == "") || (fullPath.find(separator) == std::string::npos)) - { - return fullPath; - } - std::size_t lastSlashAt = fullPath.find_last_of(separator); - if(lastSlashAt == 0) - { - return std::string(separator); - } - return fullPath.substr(0, lastSlashAt + 1); -} - -void File::buildStrippedFilename(const char *filename, char buff[], const std::string &commonPrefix, std::size_t limit) -{ - if(!commonPrefix.empty()) - { - if(!strncmp(filename, commonPrefix.c_str(), commonPrefix.size())) - filename += commonPrefix.size(); - } - std::size_t sizeOfFilename = strlen(filename); - if(sizeOfFilename >= limit) - { - filename += (sizeOfFilename - limit); - if(filename[0] != '.' && filename[1] != '.') - { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); -} - -void File::buildBaseFilename(const std::string &fullPath, char buff[], std::size_t limit, const char *separator) -{ - const char *filename = fullPath.c_str(); - std::size_t lastSlashAt = fullPath.find_last_of(separator); - filename += lastSlashAt ? lastSlashAt + 1 : 0; - std::size_t sizeOfFilename = strlen(filename); - if(sizeOfFilename >= limit) - { - filename += (sizeOfFilename - limit); - if(filename[0] != '.' && filename[1] != '.') - { // prepend if not already - filename += 3; // 3 = '..' - STRCAT(buff, "..", limit); - } - } - STRCAT(buff, filename, limit); -} - -// Str - -bool Str::wildCardMatch(const char *str, const char *pattern) -{ - while(*pattern) - { - switch(*pattern) - { - case '?': - if(!*str) - return false; - ++str; - ++pattern; - break; - case '*': - if(wildCardMatch(str, pattern + 1)) - return true; - if(*str && wildCardMatch(str + 1, pattern)) - return true; - return false; - default: - if(*str++ != *pattern++) - return false; - break; - } - } - return !*str && !*pattern; -} - -std::string &Str::ltrim(std::string &str) -{ - str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](char c) { - return !std::isspace(c); - })); - return str; -} - -std::string &Str::rtrim(std::string &str) -{ - str.erase(std::find_if(str.rbegin(), str.rend(), [](char c) { - return !std::isspace(c); - }).base(), - str.end()); - return str; -} - -std::string &Str::trim(std::string &str) -{ - return ltrim(rtrim(str)); -} - -bool Str::startsWith(const std::string &str, const std::string &start) -{ - return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); -} - -bool Str::endsWith(const std::string &str, const std::string &end) -{ - return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); -} - -std::string &Str::replaceAll(std::string &str, char replaceWhat, char replaceWith) -{ - std::replace(str.begin(), str.end(), replaceWhat, replaceWith); - return str; -} - -std::string &Str::replaceAll(std::string &str, const std::string &replaceWhat, - const std::string &replaceWith) -{ - if(replaceWhat == replaceWith) - return str; - std::size_t foundAt = std::string::npos; - while((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) - { - str.replace(foundAt, replaceWhat.length(), replaceWith); - } - return str; -} - -void Str::replaceFirstWithEscape(base::type::string_t &str, const base::type::string_t &replaceWhat, - const base::type::string_t &replaceWith) -{ - std::size_t foundAt = base::type::string_t::npos; - while((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) - { - if(foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) - { - str.erase(foundAt > 0 ? foundAt - 1 : 0, 1); - ++foundAt; - } - else - { - str.replace(foundAt, replaceWhat.length(), replaceWith); - return; - } - } -} -#if defined(ELPP_UNICODE) -void Str::replaceFirstWithEscape(base::type::string_t &str, const base::type::string_t &replaceWhat, - const std::string &replaceWith) -{ - replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); -} -#endif // defined(ELPP_UNICODE) - -std::string &Str::toUpper(std::string &str) -{ - std::transform(str.begin(), str.end(), str.begin(), ::toupper); - return str; -} - -bool Str::cStringEq(const char *s1, const char *s2) -{ - if(s1 == nullptr && s2 == nullptr) - return true; - if(s1 == nullptr || s2 == nullptr) - return false; - return strcmp(s1, s2) == 0; -} - -bool Str::cStringCaseEq(const char *s1, const char *s2) -{ - if(s1 == nullptr && s2 == nullptr) - return true; - if(s1 == nullptr || s2 == nullptr) - return false; - - // With thanks to cygwin for this code - int d = 0; - - while(true) - { - const int c1 = toupper(*s1++); - const int c2 = toupper(*s2++); - - if(((d = c1 - c2) != 0) || (c2 == '\0')) - { - break; - } - } - - return d == 0; -} - -bool Str::contains(const char *str, char c) -{ - for(; *str; ++str) - { - if(*str == c) - return true; - } - return false; -} - -char *Str::convertAndAddToBuff(std::size_t n, int len, char *buf, const char *bufLim, bool zeroPadded) -{ - char localBuff[10] = ""; - char *p = localBuff + sizeof(localBuff) - 2; - if(n > 0) - { - for(; n > 0 && p > localBuff && len > 0; n /= 10, --len) - *--p = static_cast(n % 10 + '0'); - } - else - { - *--p = '0'; - --len; - } - if(zeroPadded) - while(p > localBuff && len-- > 0) - *--p = static_cast('0'); - return addToBuff(p, buf, bufLim); -} - -char *Str::addToBuff(const char *str, char *buf, const char *bufLim) -{ - while((buf < bufLim) && ((*buf = *str++) != '\0')) - ++buf; - return buf; -} - -char *Str::clearBuff(char buff[], std::size_t lim) -{ - STRCPY(buff, "", lim); - ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro - return buff; -} - -/// @brief Converst wchar* to char* -/// NOTE: Need to free return value after use! -char *Str::wcharPtrToCharPtr(const wchar_t *line) -{ - std::size_t len_ = wcslen(line) + 1; - char *buff_ = static_cast(malloc(len_ + 1)); -#if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - std::wcstombs(buff_, line, len_); -#elif ELPP_OS_WINDOWS - std::size_t convCount_ = 0; - mbstate_t mbState_; - ::memset(static_cast(&mbState_), 0, sizeof(mbState_)); - wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); -#endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) - return buff_; -} - -// OS - -#if ELPP_OS_WINDOWS -/// @brief Gets environment variables for Windows based OS. -/// We are not using getenv(const char*) because of CRT deprecation -/// @param varname Variable name to get environment variable value for -/// @return If variable exist the value of it otherwise nullptr -const char *OS::getWindowsEnvironmentVariable(const char *varname) -{ - const DWORD bufferLen = 50; - static char buffer[bufferLen]; - if(GetEnvironmentVariableA(varname, buffer, bufferLen)) - { - return buffer; - } - return nullptr; -} -#endif // ELPP_OS_WINDOWS -#if ELPP_OS_ANDROID -std::string OS::getProperty(const char *prop) -{ - char propVal[PROP_VALUE_MAX + 1]; - int ret = __system_property_get(prop, propVal); - return ret == 0 ? std::string() : std::string(propVal); -} - -std::string OS::getDeviceName(void) -{ - std::stringstream ss; - std::string manufacturer = getProperty("ro.product.manufacturer"); - std::string model = getProperty("ro.product.model"); - if(manufacturer.empty() || model.empty()) - { - return std::string(); - } - ss << manufacturer << "-" << model; - return ss.str(); -} -#endif // ELPP_OS_ANDROID - -const std::string OS::getBashOutput(const char *command) -{ -#if(ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) - if(command == nullptr) - { - return std::string(); - } - FILE *proc = nullptr; - if((proc = popen(command, "r")) == nullptr) - { - ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); - return std::string(); - } - char hBuff[4096]; - if(fgets(hBuff, sizeof(hBuff), proc) != nullptr) - { - pclose(proc); - const size_t len = strlen(hBuff); - if(len > 0 && hBuff[len - 1] == '\n') - { - hBuff[len - 1] = '\0'; - } - return std::string(hBuff); - } - return std::string(); -#else - ELPP_UNUSED(command); - return std::string(); -#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) -} - -std::string OS::getEnvironmentVariable(const char *variableName, const char *defaultVal, - const char *alternativeBashCommand) -{ -#if ELPP_OS_UNIX - const char *val = getenv(variableName); -#elif ELPP_OS_WINDOWS - const char *val = getWindowsEnvironmentVariable(variableName); -#endif // ELPP_OS_UNIX - if((val == nullptr) || ((strcmp(val, "") == 0))) - { -#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - // Try harder on unix-based systems - std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); - if(valBash.empty()) - { - return std::string(defaultVal); - } - else - { - return valBash; - } -#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX - ELPP_UNUSED(alternativeBashCommand); - return std::string(defaultVal); -#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) - } - return std::string(val); -} - -std::string OS::currentUser(void) -{ -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownUser); - return std::string("android"); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID -} - -std::string OS::currentHost(void) -{ -#if ELPP_OS_UNIX && !ELPP_OS_ANDROID - return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); -#elif ELPP_OS_WINDOWS - return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); -#elif ELPP_OS_ANDROID - ELPP_UNUSED(base::consts::kUnknownHost); - return getDeviceName(); -#else - return std::string(); -#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID -} - -bool OS::termSupportsColor(void) -{ - std::string term = getEnvironmentVariable("TERM", ""); - return term == "xterm" || term == "xterm-color" || term == "xterm-256color" || term == "screen" || term == "linux" || term == "cygwin" || term == "screen-256color"; -} - -// DateTime - -void DateTime::gettimeofday(struct timeval *tv) -{ -#if ELPP_OS_WINDOWS - if(tv != nullptr) - { -#if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const unsigned __int64 delta_ = 11644473600000000Ui64; -#else - const unsigned __int64 delta_ = 11644473600000000ULL; -#endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) - const double secOffSet = 0.000001; - const unsigned long usecOffSet = 1000000; - FILETIME fileTime; - GetSystemTimeAsFileTime(&fileTime); - unsigned __int64 present = 0; - present |= fileTime.dwHighDateTime; - present = present << 32; - present |= fileTime.dwLowDateTime; - present /= 10; // mic-sec - // Subtract the difference - present -= delta_; - tv->tv_sec = static_cast(present * secOffSet); - tv->tv_usec = static_cast(present % usecOffSet); - } -#else - ::gettimeofday(tv, nullptr); -#endif // ELPP_OS_WINDOWS -} - -std::string DateTime::getDateTime(const char *format, const base::SubsecondPrecision *ssPrec) -{ - struct timeval currTime; - gettimeofday(&currTime); - return timevalToString(currTime, format, ssPrec); -} - -std::string DateTime::timevalToString(struct timeval tval, const char *format, - const el::base::SubsecondPrecision *ssPrec) -{ - struct ::tm timeInfo; - buildTimeInfo(&tval, &timeInfo); - const int kBuffSize = 30; - char buff_[kBuffSize] = ""; - parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast(tval.tv_usec / ssPrec->m_offset), - ssPrec); - return std::string(buff_); -} - -base::type::string_t DateTime::formatTime(unsigned long long time, base::TimestampUnit timestampUnit) -{ - base::type::EnumType start = static_cast(timestampUnit); - const base::type::char_t *unit = base::consts::kTimeFormats[start].unit; - for(base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) - { - if(time <= base::consts::kTimeFormats[i].value) - { - break; - } - if(base::consts::kTimeFormats[i].value == 1000.0f && time / 1000.0f < 1.9f) - { - break; - } - time /= static_cast(base::consts::kTimeFormats[i].value); - unit = base::consts::kTimeFormats[i + 1].unit; - } - base::type::stringstream_t ss; - ss << time << " " << unit; - return ss.str(); -} - -unsigned long long DateTime::getTimeDifference(const struct timeval &endTime, const struct timeval &startTime, - base::TimestampUnit timestampUnit) -{ - if(timestampUnit == base::TimestampUnit::Microsecond) - { - return static_cast(static_cast(1000000 * endTime.tv_sec + endTime.tv_usec) - - static_cast(1000000 * startTime.tv_sec + startTime.tv_usec)); - } - // milliseconds - auto conv = [](const struct timeval &tim) { - return static_cast((tim.tv_sec * 1000) + (tim.tv_usec / 1000)); - }; - return static_cast(conv(endTime) - conv(startTime)); -} - -struct ::tm *DateTime::buildTimeInfo(struct timeval *currTime, struct ::tm *timeInfo) -{ -#if ELPP_OS_UNIX - time_t rawTime = currTime->tv_sec; - ::gmtime_r(&rawTime, timeInfo); - return timeInfo; -#else -#if ELPP_COMPILER_MSVC - ELPP_UNUSED(currTime); - time_t t; - _time64(&t); - gmtime_s(timeInfo, &t); - return timeInfo; -#else - // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method - time_t rawTime = currTime->tv_sec; - struct tm *tmInf = gmtime(&rawTime); - *timeInfo = *tmInf; - return timeInfo; -#endif // ELPP_COMPILER_MSVC -#endif // ELPP_OS_UNIX -} - -char *DateTime::parseFormat(char *buf, std::size_t bufSz, const char *format, const struct tm *tInfo, - std::size_t msec, const base::SubsecondPrecision *ssPrec) -{ - const char *bufLim = buf + bufSz; - for(; *format; ++format) - { - if(*format == base::consts::kFormatSpecifierChar) - { - switch(*++format) - { - case base::consts::kFormatSpecifierChar: // Escape - break; - case '\0': // End - --format; - break; - case 'd': // Day - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); - continue; - case 'a': // Day of week (short) - buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); - continue; - case 'A': // Day of week (long) - buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); - continue; - case 'M': // month - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); - continue; - case 'b': // month (short) - buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); - continue; - case 'B': // month (long) - buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); - continue; - case 'y': // year (two digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); - continue; - case 'Y': // year (four digits) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); - continue; - case 'h': // hour (12-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); - continue; - case 'H': // hour (24-hour) - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); - continue; - case 'm': // minute - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); - continue; - case 's': // second - buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); - continue; - case 'z': // subsecond part - case 'g': - buf = base::utils::Str::convertAndAddToBuff(msec, ssPrec->m_width, buf, bufLim); - continue; - case 'F': // AM/PM - buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); - continue; - default: - continue; - } - } - if(buf == bufLim) - break; - *buf++ = *format; - } - return buf; -} - -// CommandLineArgs - -void CommandLineArgs::setArgs(int argc, char **argv) -{ - m_params.clear(); - m_paramsWithValue.clear(); - if(argc == 0 || argv == nullptr) - { - return; - } - m_argc = argc; - m_argv = argv; - for(int i = 1; i < m_argc; ++i) - { - const char *v = (strstr(m_argv[i], "=")); - if(v != nullptr && strlen(v) > 0) - { - std::string key = std::string(m_argv[i]); - key = key.substr(0, key.find_first_of('=')); - if(hasParamWithValue(key.c_str())) - { - ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" - << getParamValue(key.c_str()) << "]"); - } - else - { - m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); - } - } - if(v == nullptr) - { - if(hasParam(m_argv[i])) - { - ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); - } - else - { - m_params.push_back(std::string(m_argv[i])); - } - } - } -} - -bool CommandLineArgs::hasParamWithValue(const char *paramKey) const -{ - return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); -} - -const char *CommandLineArgs::getParamValue(const char *paramKey) const -{ - return m_paramsWithValue.find(std::string(paramKey))->second.c_str(); -} - -bool CommandLineArgs::hasParam(const char *paramKey) const -{ - return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); -} - -bool CommandLineArgs::empty(void) const -{ - return m_params.empty() && m_paramsWithValue.empty(); -} - -std::size_t CommandLineArgs::size(void) const -{ - return m_params.size() + m_paramsWithValue.size(); -} - -base::type::ostream_t &operator<<(base::type::ostream_t &os, const CommandLineArgs &c) -{ - for(int i = 1; i < c.m_argc; ++i) - { - os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); - if(i < c.m_argc - 1) - { - os << ELPP_LITERAL(" "); - } - } - return os; -} - -} // namespace utils - -// el::base::threading -namespace threading -{ - -#if ELPP_THREADING_ENABLED -#if ELPP_USE_STD_THREADING -#if ELPP_ASYNC_LOGGING -static void msleep(int ms) -{ -// Only when async logging enabled - this is because async is strict on compiler -#if defined(ELPP_NO_SLEEP_FOR) - usleep(ms * 1000); -#else - std::this_thread::sleep_for(std::chrono::milliseconds(ms)); -#endif // defined(ELPP_NO_SLEEP_FOR) -} -#endif // ELPP_ASYNC_LOGGING -#endif // !ELPP_USE_STD_THREADING -#endif // ELPP_THREADING_ENABLED - -} // namespace threading - -// el::base - -// SubsecondPrecision - -void SubsecondPrecision::init(int width) -{ - if(width < 1 || width > 6) - { - width = base::consts::kDefaultSubsecondPrecision; - } - m_width = width; - switch(m_width) - { - case 3: - m_offset = 1000; - break; - case 4: - m_offset = 100; - break; - case 5: - m_offset = 10; - break; - case 6: - m_offset = 1; - break; - default: - m_offset = 1000; - break; - } -} - -// LogFormat - -LogFormat::LogFormat(void) : m_level(Level::Unknown), - m_userFormat(base::type::string_t()), - m_format(base::type::string_t()), - m_dateTimeFormat(std::string()), - m_flags(0x0), - m_currentUser(base::utils::OS::currentUser()), - m_currentHost(base::utils::OS::currentHost()) -{ -} - -LogFormat::LogFormat(Level level, const base::type::string_t &format) - : m_level(level), m_userFormat(format), m_currentUser(base::utils::OS::currentUser()), - m_currentHost(base::utils::OS::currentHost()) -{ - parseFromFormat(m_userFormat); -} - -LogFormat::LogFormat(const LogFormat &logFormat) : m_level(logFormat.m_level), - m_userFormat(logFormat.m_userFormat), - m_format(logFormat.m_format), - m_dateTimeFormat(logFormat.m_dateTimeFormat), - m_flags(logFormat.m_flags), - m_currentUser(logFormat.m_currentUser), - m_currentHost(logFormat.m_currentHost) -{ -} - -LogFormat::LogFormat(LogFormat &&logFormat) -{ - m_level = std::move(logFormat.m_level); - m_userFormat = std::move(logFormat.m_userFormat); - m_format = std::move(logFormat.m_format); - m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); - m_flags = std::move(logFormat.m_flags); - m_currentUser = std::move(logFormat.m_currentUser); - m_currentHost = std::move(logFormat.m_currentHost); -} - -LogFormat &LogFormat::operator=(const LogFormat &logFormat) -{ - if(&logFormat != this) - { - m_level = logFormat.m_level; - m_userFormat = logFormat.m_userFormat; - m_dateTimeFormat = logFormat.m_dateTimeFormat; - m_flags = logFormat.m_flags; - m_currentUser = logFormat.m_currentUser; - m_currentHost = logFormat.m_currentHost; - } - return *this; -} - -bool LogFormat::operator==(const LogFormat &other) -{ - return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && - m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; -} - -/// @brief Updates format to be used while logging. -/// @param userFormat User provided format -void LogFormat::parseFromFormat(const base::type::string_t &userFormat) -{ - // We make copy because we will be changing the format - // i.e, removing user provided date format from original format - // and then storing it. - base::type::string_t formatCopy = userFormat; - m_flags = 0x0; - auto conditionalAddFlag = [&](const base::type::char_t *specifier, base::FormatFlags flag) { - std::size_t foundAt = base::type::string_t::npos; - while((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) - { - if(foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) - { - if(hasFlag(flag)) - { - // If we already have flag we remove the escape chars so that '%%' is turned to '%' - // even after specifier resolution - this is because we only replaceFirst specifier - formatCopy.erase(foundAt > 0 ? foundAt - 1 : 0, 1); - ++foundAt; - } - } - else - { - if(!hasFlag(flag)) - addFlag(flag); - } - } - }; - conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); - conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); - conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); - conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); - conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); - conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); - conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); - conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); - conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); - conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); - conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); - conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); - conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); - conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); - // For date/time we need to extract user's date format first - std::size_t dateIndex = std::string::npos; - if((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) - { - while(dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) - { - dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); - } - if(dateIndex != std::string::npos) - { - addFlag(base::FormatFlags::DateTime); - updateDateFormat(dateIndex, formatCopy); - } - } - m_format = formatCopy; - updateFormatSpec(); -} - -void LogFormat::updateDateFormat(std::size_t index, base::type::string_t &currFormat) -{ - if(hasFlag(base::FormatFlags::DateTime)) - { - index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); - } - const base::type::char_t *ptr = currFormat.c_str() + index; - if((currFormat.size() > index) && (ptr[0] == '{')) - { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for(; *ptr; ++ptr, ++count) - { - if(*ptr == '}') - { - ++count; // In order to remove ending brace - break; - } - ss << static_cast(*ptr); - } - currFormat.erase(index, count); - m_dateTimeFormat = ss.str(); - } - else - { - // No format provided, use default - if(hasFlag(base::FormatFlags::DateTime)) - { - m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); - } - } -} - -void LogFormat::updateFormatSpec(void) -{ - // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. - if(m_level == Level::Debug) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kDebugLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kDebugLevelShortLogValue); - } - else if(m_level == Level::Info) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kInfoLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kInfoLevelShortLogValue); - } - else if(m_level == Level::Warning) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kWarningLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kWarningLevelShortLogValue); - } - else if(m_level == Level::Error) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kErrorLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kErrorLevelShortLogValue); - } - else if(m_level == Level::Fatal) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kFatalLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kFatalLevelShortLogValue); - } - else if(m_level == Level::Verbose) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kVerboseLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kVerboseLevelShortLogValue); - } - else if(m_level == Level::Trace) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, - base::consts::kTraceLevelLogValue); - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, - base::consts::kTraceLevelShortLogValue); - } - if(hasFlag(base::FormatFlags::User)) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, - m_currentUser); - } - if(hasFlag(base::FormatFlags::Host)) - { - base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, - m_currentHost); - } - // Ignore Level::Global and Level::Unknown -} - -// TypedConfigurations - -TypedConfigurations::TypedConfigurations(Configurations *configurations, - base::LogStreamsReferenceMap *logStreamsReference) -{ - m_configurations = configurations; - m_logStreamsReference = logStreamsReference; - build(m_configurations); -} - -TypedConfigurations::TypedConfigurations(const TypedConfigurations &other) -{ - this->m_configurations = other.m_configurations; - this->m_logStreamsReference = other.m_logStreamsReference; - build(m_configurations); -} - -bool TypedConfigurations::enabled(Level level) -{ - return getConfigByVal(level, &m_enabledMap, "enabled"); -} - -bool TypedConfigurations::toFile(Level level) -{ - return getConfigByVal(level, &m_toFileMap, "toFile"); -} - -const std::string &TypedConfigurations::filename(Level level) -{ - return getConfigByRef(level, &m_filenameMap, "filename"); -} - -bool TypedConfigurations::toStandardOutput(Level level) -{ - return getConfigByVal(level, &m_toStandardOutputMap, "toStandardOutput"); -} - -const base::LogFormat &TypedConfigurations::logFormat(Level level) -{ - return getConfigByRef(level, &m_logFormatMap, "logFormat"); -} - -const base::SubsecondPrecision &TypedConfigurations::subsecondPrecision(Level level) -{ - return getConfigByRef(level, &m_subsecondPrecisionMap, "subsecondPrecision"); -} - -const base::MillisecondsWidth &TypedConfigurations::millisecondsWidth(Level level) -{ - return getConfigByRef(level, &m_subsecondPrecisionMap, "millisecondsWidth"); -} - -bool TypedConfigurations::performanceTracking(Level level) -{ - return getConfigByVal(level, &m_performanceTrackingMap, "performanceTracking"); -} - -base::type::fstream_t *TypedConfigurations::fileStream(Level level) -{ - return getConfigByRef(level, &m_fileStreamMap, "fileStream").get(); -} - -std::size_t TypedConfigurations::maxLogFileSize(Level level) -{ - return getConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); -} - -std::size_t TypedConfigurations::logFlushThreshold(Level level) -{ - return getConfigByVal(level, &m_logFlushThresholdMap, "logFlushThreshold"); -} - -void TypedConfigurations::build(Configurations *configurations) -{ - base::threading::ScopedLock scopedLock(lock()); - auto getBool = [](std::string boolStr) -> bool { // Pass by value for trimming - base::utils::Str::trim(boolStr); - return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); - }; - setValue(Level::Global, base::FileStreamPtr(NULL), &m_fileStreamMap); - std::vector withFileSizeLimit; - for(Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) - { - Configuration *conf = *it; - // We cannot use switch on strong enums because Intel C++ dont support them yet - if(conf->configurationType() == ConfigurationType::Enabled) - { - setValue(conf->level(), getBool(conf->value()), &m_enabledMap); - } - else if(conf->configurationType() == ConfigurationType::ToFile) - { - setValue(conf->level(), getBool(conf->value()), &m_toFileMap); - } - else if(conf->configurationType() == ConfigurationType::ToStandardOutput) - { - setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); - } - else if(conf->configurationType() == ConfigurationType::Filename) - { - // We do not yet configure filename but we will configure in another - // loop. This is because if file cannot be created, we will force ToFile - // to be false. Because configuring logger is not necessarily performance - // sensative operation, we can live with another loop; (by the way this loop - // is not very heavy either) - } - else if(conf->configurationType() == ConfigurationType::Format) - { - setValue(conf->level(), base::LogFormat(conf->level(), - base::type::string_t(conf->value().begin(), conf->value().end())), - &m_logFormatMap); - } - else if(conf->configurationType() == ConfigurationType::SubsecondPrecision) - { - setValue(Level::Global, - base::SubsecondPrecision(static_cast(getULong(conf->value()))), &m_subsecondPrecisionMap); - } - else if(conf->configurationType() == ConfigurationType::PerformanceTracking) - { - setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); - } - else if(conf->configurationType() == ConfigurationType::MaxLogFileSize) - { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_maxLogFileSizeMap); -#if !defined(ELPP_NO_DEFAULT_LOG_FILE) - withFileSizeLimit.push_back(conf); -#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) - } - else if(conf->configurationType() == ConfigurationType::LogFlushThreshold) - { - setValue(conf->level(), static_cast(getULong(conf->value())), &m_logFlushThresholdMap); - } - } - // As mentioned earlier, we will now set filename configuration in separate loop to deal with non-existent files - for(Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) - { - Configuration *conf = *it; - if(conf->configurationType() == ConfigurationType::Filename) - { - insertFile(conf->level(), conf->value()); - } - } - for(std::vector::iterator conf = withFileSizeLimit.begin(); - conf != withFileSizeLimit.end(); ++conf) - { - // This is not unsafe as mutex is locked in currect scope - unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); - } -} - -unsigned long TypedConfigurations::getULong(std::string confVal) -{ - bool valid = true; - base::utils::Str::trim(confVal); - valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), [](char c) { - return !base::utils::Str::isDigit(c); - }) == confVal.end(); - if(!valid) - { - valid = false; - ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); - return 0; - } - return atol(confVal.c_str()); -} - -std::string TypedConfigurations::resolveFilename(const std::string &filename) -{ - std::string resultingFilename = filename; - std::size_t dateIndex = std::string::npos; - std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); - if((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) - { - while(dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) - { - dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); - } - if(dateIndex != std::string::npos) - { - const char *ptr = resultingFilename.c_str() + dateIndex; - // Goto end of specifier - ptr += dateTimeFormatSpecifierStr.size(); - std::string fmt; - if((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) - { - // User has provided format for date/time - ++ptr; - int count = 1; // Start by 1 in order to remove starting brace - std::stringstream ss; - for(; *ptr; ++ptr, ++count) - { - if(*ptr == '}') - { - ++count; // In order to remove ending brace - break; - } - ss << *ptr; - } - resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); - fmt = ss.str(); - } - else - { - fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); - } - base::SubsecondPrecision ssPrec(3); - std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &ssPrec); - base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename - base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); - } - } - return resultingFilename; -} - -void TypedConfigurations::insertFile(Level level, const std::string &fullFilename) -{ -#if defined(ELPP_NO_LOG_TO_FILE) - setValue(level, false, &m_toFileMap); - ELPP_UNUSED(fullFilename); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(nullptr))); - return; -#endif - if(fullFilename.empty()) - return; - std::string resolvedFilename = resolveFilename(fullFilename); - if(resolvedFilename.empty()) - { - std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" - << LevelHelper::convertToString(level) << "]"; - } - std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator); - if(filePath.size() < resolvedFilename.size()) - { - base::utils::File::createPath(filePath); - } - auto create = [&](Level level) { - base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); - base::type::fstream_t *fs = nullptr; - if(filestreamIter == m_logStreamsReference->end()) - { - // We need a completely new stream, nothing to share with - fs = base::utils::File::newFileStream(resolvedFilename); - m_filenameMap.insert(std::make_pair(level, resolvedFilename)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); - m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); - } - else - { - // Woops! we have an existing one, share it! - m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); - m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); - fs = filestreamIter->second.get(); - } - if(fs == nullptr) - { - // We display bad file error from newFileStream() - ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" - << LevelHelper::convertToString(level) << "] to FALSE", - false); - setValue(level, false, &m_toFileMap); - } - }; - // If we dont have file conf for any level, create it for Level::Global first - // otherwise create for specified level - create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); -} - -bool TypedConfigurations::unsafeValidateFileRolling(Level level, const PreRollOutCallback &preRollOutCallback) -{ - base::type::fstream_t *fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); - if(fs == nullptr) - { - return true; - } - std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); - std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); - if(maxLogFileSize != 0 && currFileSize >= maxLogFileSize) - { - std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); - ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" - << LevelHelper::convertToString(level) << "]"); - fs->close(); - preRollOutCallback(fname.c_str(), currFileSize); - fs->open(fname, std::fstream::out | std::fstream::trunc); - return true; - } - return false; -} - -// RegisteredHitCounters - -bool RegisteredHitCounters::validateEveryN(const char *filename, base::type::LineNumber lineNumber, std::size_t n) -{ - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter *counter = get(filename, lineNumber); - if(counter == nullptr) - { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->validateHitCounts(n); - bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); - return result; -} - -/// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one -/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned -bool RegisteredHitCounters::validateAfterN(const char *filename, base::type::LineNumber lineNumber, std::size_t n) -{ - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter *counter = get(filename, lineNumber); - if(counter == nullptr) - { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - // Do not use validateHitCounts here since we do not want to reset counter here - // Note the >= instead of > because we are incrementing - // after this check - if(counter->hitCounts() >= n) - return true; - counter->increment(); - return false; -} - -/// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one -/// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned -bool RegisteredHitCounters::validateNTimes(const char *filename, base::type::LineNumber lineNumber, std::size_t n) -{ - base::threading::ScopedLock scopedLock(lock()); - base::HitCounter *counter = get(filename, lineNumber); - if(counter == nullptr) - { - registerNew(counter = new base::HitCounter(filename, lineNumber)); - } - counter->increment(); - // Do not use validateHitCounts here since we do not want to reset counter here - if(counter->hitCounts() <= n) - return true; - return false; -} - -// RegisteredLoggers - -RegisteredLoggers::RegisteredLoggers(const LogBuilderPtr &defaultLogBuilder) : m_defaultLogBuilder(defaultLogBuilder) -{ - m_defaultConfigurations.setToDefault(); -} - -Logger *RegisteredLoggers::get(const std::string &id, bool forceCreation) -{ - base::threading::ScopedLock scopedLock(lock()); - Logger *logger_ = base::utils::Registry::get(id); - if(logger_ == nullptr && forceCreation) - { - bool validId = Logger::isValidId(id); - if(!validId) - { - ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); - return nullptr; - } - logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference); - logger_->m_logBuilder = m_defaultLogBuilder; - registerNew(id, logger_); - LoggerRegistrationCallback *callback = nullptr; - for(const std::pair &h : m_loggerRegistrationCallbacks) - { - callback = h.second.get(); - if(callback != nullptr && callback->enabled()) - { - callback->handle(logger_); - } - } - } - return logger_; -} - -bool RegisteredLoggers::remove(const std::string &id) -{ - if(id == base::consts::kDefaultLoggerId) - { - return false; - } - Logger *logger = base::utils::Registry::get(id); - if(logger != nullptr) - { - unregister(logger); - } - return true; -} - -void RegisteredLoggers::unsafeFlushAll(void) -{ - ELPP_INTERNAL_INFO(1, "Flushing all log files"); - for(base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin(); - it != m_logStreamsReference.end(); ++it) - { - if(it->second.get() == nullptr) - continue; - it->second->flush(); - } -} - -// VRegistry - -VRegistry::VRegistry(base::type::VerboseLevel level, base::type::EnumType *pFlags) : m_level(level), m_pFlags(pFlags) -{ -} - -/// @brief Sets verbose level. Accepted range is 0-9 -void VRegistry::setLevel(base::type::VerboseLevel level) -{ - base::threading::ScopedLock scopedLock(lock()); - if(level > 9) - m_level = base::consts::kMaxVerboseLevel; - else - m_level = level; -} - -void VRegistry::setModules(const char *modules) -{ - base::threading::ScopedLock scopedLock(lock()); - auto addSuffix = [](std::stringstream &ss, const char *sfx, const char *prev) { - if(prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) - { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); - ss.str(std::string("")); - ss << chr; - } - if(base::utils::Str::endsWith(ss.str(), std::string(sfx))) - { - std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); - ss.str(std::string("")); - ss << chr; - } - ss << sfx; - }; - auto insert = [&](std::stringstream &ss, base::type::VerboseLevel level) { - if(!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) - { - addSuffix(ss, ".h", nullptr); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".c", ".h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cpp", ".c"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cc", ".cpp"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".cxx", ".cc"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".-inl.h", ".cxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hxx", ".-inl.h"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hpp", ".hxx"); - m_modules.insert(std::make_pair(ss.str(), level)); - addSuffix(ss, ".hh", ".hpp"); - } - m_modules.insert(std::make_pair(ss.str(), level)); - }; - bool isMod = true; - bool isLevel = false; - std::stringstream ss; - int level = -1; - for(; *modules; ++modules) - { - switch(*modules) - { - case '=': - isLevel = true; - isMod = false; - break; - case ',': - isLevel = false; - isMod = true; - if(!ss.str().empty() && level != -1) - { - insert(ss, static_cast(level)); - ss.str(std::string("")); - level = -1; - } - break; - default: - if(isMod) - { - ss << *modules; - } - else if(isLevel) - { - if(isdigit(*modules)) - { - level = static_cast(*modules) - 48; - } - } - break; - } - } - if(!ss.str().empty() && level != -1) - { - insert(ss, static_cast(level)); - } -} - -void VRegistry::setCategories(const char *categories, bool clear) -{ - base::threading::ScopedLock scopedLock(lock()); - auto insert = [&](std::stringstream &ss, Level level) { - m_categories.push_back(std::make_pair(ss.str(), level)); - }; - - if(clear) - { - m_categories.clear(); - m_categoriesString.clear(); - } - if(!m_categoriesString.empty()) - m_categoriesString += ","; - m_categoriesString += categories; - if(!categories) - return; - - bool isCat = true; - bool isLevel = false; - std::stringstream ss; - Level level = Level::Unknown; - for(; *categories; ++categories) - { - switch(*categories) - { - case ':': - isLevel = true; - isCat = false; - break; - case ',': - isLevel = false; - isCat = true; - if(!ss.str().empty() && level != Level::Unknown) - { - insert(ss, level); - ss.str(std::string("")); - level = Level::Unknown; - } - break; - default: - if(isCat) - { - ss << *categories; - } - else if(isLevel) - { - level = LevelHelper::convertFromStringPrefix(categories); - if(level != Level::Unknown) - categories += strlen(LevelHelper::convertToString(level)) - 1; - } - break; - } - } - if(!ss.str().empty() && level != Level::Unknown) - { - insert(ss, level); - } -} - -std::string VRegistry::getCategories() -{ - base::threading::ScopedLock scopedLock(lock()); - return m_categoriesString; -} - -// Log levels are sorted in a weird way... -static int priority(Level level) -{ - if(level == Level::Fatal) - return 0; - if(level == Level::Error) - return 1; - if(level == Level::Warning) - return 2; - if(level == Level::Info) - return 3; - if(level == Level::Debug) - return 4; - if(level == Level::Verbose) - return 5; - if(level == Level::Trace) - return 6; - return 7; -} - -bool VRegistry::allowed(Level level, const char *category) -{ - base::threading::ScopedLock scopedLock(lock()); - if(m_categories.empty() || category == nullptr) - { - return false; - } - else - { - std::deque>::const_reverse_iterator it = m_categories.rbegin(); - for(; it != m_categories.rend(); ++it) - { - if(base::utils::Str::wildCardMatch(category, it->first.c_str())) - { - return priority(level) <= priority(it->second); - } - } - return false; - } -} - -bool VRegistry::allowed(base::type::VerboseLevel vlevel, const char *file) -{ - base::threading::ScopedLock scopedLock(lock()); - if(m_modules.empty() || file == nullptr) - { - return vlevel <= m_level; - } - else - { - std::map::iterator it = m_modules.begin(); - for(; it != m_modules.end(); ++it) - { - if(base::utils::Str::wildCardMatch(file, it->first.c_str())) - { - return vlevel <= it->second; - } - } - if(base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) - { - return true; - } - return false; - } -} - -void VRegistry::setFromArgs(const base::utils::CommandLineArgs *commandLineArgs) -{ - if(commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || - commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) - { - setLevel(base::consts::kMaxVerboseLevel); - } - else if(commandLineArgs->hasParamWithValue("--v")) - { - setLevel(static_cast(atoi(commandLineArgs->getParamValue("--v")))); - } - else if(commandLineArgs->hasParamWithValue("--V")) - { - setLevel(static_cast(atoi(commandLineArgs->getParamValue("--V")))); - } - else if((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) - { - setModules(commandLineArgs->getParamValue("-vmodule")); - } - else if(commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) - { - setModules(commandLineArgs->getParamValue("-VMODULE")); - } -} - -#if !defined(ELPP_DEFAULT_LOGGING_FLAGS) -#define ELPP_DEFAULT_LOGGING_FLAGS 0x0 -#endif // !defined(ELPP_DEFAULT_LOGGING_FLAGS) -// Storage -#if ELPP_ASYNC_LOGGING -Storage::Storage(const LogBuilderPtr &defaultLogBuilder, base::IWorker *asyncDispatchWorker) : -#else -Storage::Storage(const LogBuilderPtr &defaultLogBuilder) : -#endif // ELPP_ASYNC_LOGGING - m_registeredHitCounters(new base::RegisteredHitCounters()), - m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), - m_flags(ELPP_DEFAULT_LOGGING_FLAGS), - m_vRegistry(new base::VRegistry(0, &m_flags)), -#if ELPP_ASYNC_LOGGING - m_asyncLogQueue(new base::AsyncLogQueue()), - m_asyncDispatchWorker(asyncDispatchWorker), -#endif // ELPP_ASYNC_LOGGING - m_preRollOutCallback(base::defaultPreRollOutCallback) -{ - // Register default logger - m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); - // We register default logger anyway (worse case it's not going to register) just in case - m_registeredLoggers->get("default"); - // Register performance logger and reconfigure format - Logger *performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); - m_registeredLoggers->get("performance"); - performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); - performanceLogger->reconfigure(); -#if defined(ELPP_SYSLOG) - // Register syslog logger and reconfigure format - Logger *sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); - sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); - sysLogLogger->reconfigure(); -#endif // defined(ELPP_SYSLOG) - addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); - addFlag(LoggingFlag::CreateLoggerAutomatically); -#if ELPP_ASYNC_LOGGING - installLogDispatchCallback(std::string("AsyncLogDispatchCallback")); -#else - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); -#endif // ELPP_ASYNC_LOGGING -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - installPerformanceTrackingCallback(std::string("DefaultPerformanceTrackingCallback")); -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); -#if ELPP_ASYNC_LOGGING - m_asyncDispatchWorker->start(); -#endif // ELPP_ASYNC_LOGGING -} - -Storage::~Storage(void) -{ - ELPP_INTERNAL_INFO(4, "Destroying storage"); -#if ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); - uninstallLogDispatchCallback(std::string("AsyncLogDispatchCallback")); - installLogDispatchCallback(std::string("DefaultLogDispatchCallback")); - ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); - base::utils::safeDelete(m_asyncDispatchWorker); - ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); - base::utils::safeDelete(m_asyncLogQueue); -#endif // ELPP_ASYNC_LOGGING - ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); - base::utils::safeDelete(m_registeredHitCounters); - ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); - base::utils::safeDelete(m_registeredLoggers); - ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); - base::utils::safeDelete(m_vRegistry); -} - -bool Storage::hasCustomFormatSpecifier(const char *formatSpecifier) -{ - base::threading::ScopedLock scopedLock(lock()); - return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), - formatSpecifier) != m_customFormatSpecifiers.end(); -} - -void Storage::installCustomFormatSpecifier(const CustomFormatSpecifier &customFormatSpecifier) -{ - if(hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) - { - return; - } - base::threading::ScopedLock scopedLock(lock()); - m_customFormatSpecifiers.push_back(customFormatSpecifier); -} - -bool Storage::uninstallCustomFormatSpecifier(const char *formatSpecifier) -{ - base::threading::ScopedLock scopedLock(lock()); - std::vector::iterator it = std::find(m_customFormatSpecifiers.begin(), - m_customFormatSpecifiers.end(), formatSpecifier); - if(it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) - { - m_customFormatSpecifiers.erase(it); - return true; - } - return false; -} - -void Storage::setApplicationArguments(int argc, char **argv) -{ - m_commandLineArgs.setArgs(argc, argv); - m_vRegistry->setFromArgs(commandLineArgs()); -// default log file -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) - if(m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) - { - Configurations c; - c.setGlobally(ConfigurationType::Filename, - std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); - registeredLoggers()->setDefaultConfigurations(c); - for(base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); - it != registeredLoggers()->end(); ++it) - { - it->second->configure(c); - } - } -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) - if(m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) - { - int userInput = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); - if(ELPP_DEFAULT_LOGGING_FLAGS == 0x0) - { - m_flags = userInput; - } - else - { - base::utils::addFlag(userInput, &m_flags); - } - } -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) -} - -// DefaultLogDispatchCallback - -void DefaultLogDispatchCallback::handle(const LogDispatchData *data) -{ - m_data = data; - dispatch(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), - m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog)); -} - -void DefaultLogDispatchCallback::dispatch(base::type::string_t &&logLine) -{ - if(m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog) - { - if(m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) - { - base::type::fstream_t *fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream( - m_data->logMessage()->level()); - if(fs != nullptr) - { - fs->write(logLine.c_str(), logLine.size()); - if(fs->fail()) - { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" - << "Few possible reasons (could be something else):\n" - << " * Permission denied\n" - << " * Disk full\n" - << " * Disk is not writable", - true); - } - else - { - if(ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) - { - m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); - } - } - } - else - { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " - << m_data->logMessage()->logger()->id() << "]", - false); - } - } - if(m_data->dispatchAction() != base::DispatchAction::FileOnlyLog) - { - if(m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) - { - if(ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - } - } -#if defined(ELPP_SYSLOG) - else if(m_data->dispatchAction() == base::DispatchAction::SysLog) - { - // Determine syslog priority - int sysLogPriority = 0; - if(m_data->logMessage()->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if(m_data->logMessage()->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if(m_data->logMessage()->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if(m_data->logMessage()->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if(m_data->logMessage()->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -#if defined(ELPP_UNICODE) - char *line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -#else - syslog(sysLogPriority, "%s", logLine.c_str()); -#endif - } -#endif // defined(ELPP_SYSLOG) -} - -#if ELPP_ASYNC_LOGGING - -// AsyncLogDispatchCallback - -void AsyncLogDispatchCallback::handle(const LogDispatchData *data) -{ - base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), - data->dispatchAction() == base::DispatchAction::NormalLog || data->dispatchAction() == base::DispatchAction::FileOnlyLog); - if((data->dispatchAction() == base::DispatchAction::NormalLog || data->dispatchAction() == base::DispatchAction::FileOnlyLog) && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) - { - if(ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) - data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); - ELPP_COUT << ELPP_COUT_LINE(logLine); - } - // Save resources and only queue if we want to write to file otherwise just ignore handler - if(data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) - { - ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); - } -} - -// AsyncDispatchWorker -AsyncDispatchWorker::AsyncDispatchWorker() -{ - setContinueRunning(false); -} - -AsyncDispatchWorker::~AsyncDispatchWorker() -{ - setContinueRunning(false); - ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); - clean(); - ELPP_INTERNAL_INFO(6, "Log queue cleaned"); -} - -bool AsyncDispatchWorker::clean(void) -{ - std::mutex m; - std::unique_lock lk(m); - cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); - emptyQueue(); - lk.unlock(); - cv.notify_one(); - return ELPP->asyncLogQueue()->empty(); -} - -void AsyncDispatchWorker::emptyQueue(void) -{ - while(!ELPP->asyncLogQueue()->empty()) - { - AsyncLogItem data = ELPP->asyncLogQueue()->next(); - handle(&data); - base::threading::msleep(100); - } -} - -void AsyncDispatchWorker::start(void) -{ - base::threading::msleep(5000); // 5s (why?) - setContinueRunning(true); - std::thread t1(&AsyncDispatchWorker::run, this); - t1.join(); -} - -void AsyncDispatchWorker::handle(AsyncLogItem *logItem) -{ - LogDispatchData *data = logItem->data(); - LogMessage *logMessage = logItem->logMessage(); - Logger *logger = logMessage->logger(); - base::TypedConfigurations *conf = logger->typedConfigurations(); - base::type::string_t logLine = logItem->logLine(); - if(data->dispatchAction() == base::DispatchAction::NormalLog || data->dispatchAction() == base::DispatchAction::FileOnlyLog) - { - if(conf->toFile(logMessage->level())) - { - base::type::fstream_t *fs = conf->fileStream(logMessage->level()); - if(fs != nullptr) - { - fs->write(logLine.c_str(), logLine.size()); - if(fs->fail()) - { - ELPP_INTERNAL_ERROR("Unable to write log to file [" - << conf->filename(logMessage->level()) << "].\n" - << "Few possible reasons (could be something else):\n" - << " * Permission denied\n" - << " * Disk full\n" - << " * Disk is not writable", - true); - } - else - { - if(ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) - { - logger->flush(logMessage->level(), fs); - } - } - } - else - { - ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " - << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", - false); - } - } - } -#if defined(ELPP_SYSLOG) - else if(data->dispatchAction() == base::DispatchAction::SysLog) - { - // Determine syslog priority - int sysLogPriority = 0; - if(logMessage->level() == Level::Fatal) - sysLogPriority = LOG_EMERG; - else if(logMessage->level() == Level::Error) - sysLogPriority = LOG_ERR; - else if(logMessage->level() == Level::Warning) - sysLogPriority = LOG_WARNING; - else if(logMessage->level() == Level::Info) - sysLogPriority = LOG_INFO; - else if(logMessage->level() == Level::Debug) - sysLogPriority = LOG_DEBUG; - else - sysLogPriority = LOG_NOTICE; -#if defined(ELPP_UNICODE) - char *line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); - syslog(sysLogPriority, "%s", line); - free(line); -#else - syslog(sysLogPriority, "%s", logLine.c_str()); -#endif - } -#endif // defined(ELPP_SYSLOG) -} - -void AsyncDispatchWorker::run(void) -{ - while(continueRunning()) - { - emptyQueue(); - base::threading::msleep(10); // 10ms - } -} -#endif // ELPP_ASYNC_LOGGING - -// DefaultLogBuilder - -base::type::string_t DefaultLogBuilder::build(const LogMessage *logMessage, bool appendNewLine) const -{ - base::TypedConfigurations *tc = logMessage->logger()->typedConfigurations(); - const base::LogFormat *logFormat = &tc->logFormat(logMessage->level()); - base::type::string_t logLine = logFormat->format(); - char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; - const char *bufLim = buff + sizeof(buff); - if(logFormat->hasFlag(base::FormatFlags::AppName)) - { - // App name - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, - logMessage->logger()->parentApplicationName()); - } - if(logFormat->hasFlag(base::FormatFlags::ThreadId)) - { - // Thread ID - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, - ELPP->getThreadName(base::threading::getCurrentThreadId())); - } - if(logFormat->hasFlag(base::FormatFlags::DateTime)) - { - // DateTime - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, - base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), - &tc->subsecondPrecision(logMessage->level()))); - } - if(logFormat->hasFlag(base::FormatFlags::Function)) - { - // Function - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); - } - if(logFormat->hasFlag(base::FormatFlags::File)) - { - // File - base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff, ELPP->vRegistry()->getFilenameCommonPrefix()); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); - } - if(logFormat->hasFlag(base::FormatFlags::FileBase)) - { - // FileBase - base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); - base::utils::File::buildBaseFilename(logMessage->file(), buff); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); - } - if(logFormat->hasFlag(base::FormatFlags::Line)) - { - // Line - char *buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); - } - if(logFormat->hasFlag(base::FormatFlags::Location)) - { - // Location - char *buf = base::utils::Str::clearBuff(buff, - base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); - base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff, ELPP->vRegistry()->getFilenameCommonPrefix()); - buf = base::utils::Str::addToBuff(buff, buf, bufLim); - buf = base::utils::Str::addToBuff(":", buf, bufLim); - buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), base::consts::kSourceLineMaxLength, buf, bufLim, - false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); - } - if(logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) - { - // Verbose level - char *buf = base::utils::Str::clearBuff(buff, 1); - buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); - } - if(logFormat->hasFlag(base::FormatFlags::LogMessage)) - { - // Log message - base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); - } -#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - for(std::vector::const_iterator it = ELPP->customFormatSpecifiers()->begin(); - it != ELPP->customFormatSpecifiers()->end(); ++it) - { - std::string fs(it->formatSpecifier()); - base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); - base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, it->resolver()(logMessage)); - } -#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) - if(appendNewLine) - logLine += ELPP_LITERAL("\n"); - return logLine; -} - -// LogDispatcher - -void LogDispatcher::dispatch(void) -{ - if(m_proceed && m_dispatchAction == base::DispatchAction::None) - { - m_proceed = false; - } - if(!m_proceed) - { - return; - } - base::threading::ScopedLock scopedLock(ELPP->lock()); - base::TypedConfigurations *tc = m_logMessage.logger()->m_typedConfigurations; - if(ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) - { - tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback()); - } - LogDispatchCallback *callback = nullptr; - LogDispatchData data; - for(const std::pair &h : ELPP->m_logDispatchCallbacks) - { - callback = h.second.get(); - if(callback != nullptr && callback->enabled()) - { - data.setLogMessage(&m_logMessage); - data.setDispatchAction(m_dispatchAction); - callback->handle(&data); - } - } -} - -// MessageBuilder - -void MessageBuilder::initialize(Logger *logger) -{ - m_logger = logger; - m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); -} - -MessageBuilder &MessageBuilder::operator<<(const wchar_t *msg) -{ - if(msg == nullptr) - { - m_logger->stream() << base::consts::kNullPointer; - return *this; - } -#if defined(ELPP_UNICODE) - m_logger->stream() << msg; -#else - char *buff_ = base::utils::Str::wcharPtrToCharPtr(msg); - m_logger->stream() << buff_; - free(buff_); -#endif - if(ELPP->hasFlag(LoggingFlag::AutoSpacing)) - { - m_logger->stream() << " "; - } - return *this; -} - -// Writer - -Writer &Writer::construct(Logger *logger, bool needLock) -{ - m_logger = logger; - initializeLogger(logger->id(), false, needLock); - m_messageBuilder.initialize(m_logger); - return *this; -} - -Writer &Writer::construct(int count, const char *loggerIds, ...) -{ - if(ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) - { - va_list loggersList; - va_start(loggersList, loggerIds); - const char *id = loggerIds; - for(int i = 0; i < count; ++i) - { - m_loggerIds.push_back(std::string(id)); - id = va_arg(loggersList, const char *); - } - va_end(loggersList); - initializeLogger(m_loggerIds.at(0)); - } - else - { - initializeLogger(std::string(loggerIds)); - } - m_messageBuilder.initialize(m_logger); - return *this; -} - -void Writer::initializeLogger(const std::string &loggerId, bool lookup, bool needLock) -{ - if(lookup) - { - m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); - } - if(m_logger == nullptr) - { - ELPP->acquireLock(); - if(!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) - { - // Somehow default logger has been unregistered. Not good! Register again - ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); - } - ELPP->releaseLock(); // Need to unlock it for next writer - Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Logger [" << loggerId << "] is not registered yet!"; - m_proceed = false; - } - else - { - if(needLock) - { - m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because - // m_proceed can be changed by lines below - } - if(ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) - { - m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : ELPP->vRegistry()->allowed(m_level, loggerId.c_str()); - } - else - { - m_proceed = m_logger->enabled(m_level); - } - } -} - -void Writer::processDispatch() -{ -#if ELPP_LOGGING_ENABLED - if(ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) - { - bool firstDispatched = false; - base::type::string_t logMessage; - std::size_t i = 0; - do - { - if(m_proceed) - { - if(firstDispatched) - { - m_logger->stream() << logMessage; - } - else - { - firstDispatched = true; - if(m_loggerIds.size() > 1) - { - logMessage = m_logger->stream().str(); - } - } - triggerDispatch(); - } - else if(m_logger != nullptr) - { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if(i + 1 < m_loggerIds.size()) - { - initializeLogger(m_loggerIds.at(i + 1)); - } - } while(++i < m_loggerIds.size()); - } - else - { - if(m_proceed) - { - triggerDispatch(); - } - else if(m_logger != nullptr) - { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - } -#else - if(m_logger != nullptr) - { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } -#endif // ELPP_LOGGING_ENABLED -} - -void Writer::triggerDispatch(void) -{ - if(m_proceed) - { - base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel, - m_logger), - m_dispatchAction) - .dispatch(); - } - if(m_logger != nullptr) - { - m_logger->stream().str(ELPP_LITERAL("")); - m_logger->releaseLock(); - } - if(m_proceed && m_level == Level::Fatal && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) - { - base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) - << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; - std::stringstream reasonStream; - reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" - << " If you wish to disable 'abort on fatal log' please use " - << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; - base::utils::abort(1, reasonStream.str()); - } - m_proceed = false; -} - -// PErrorWriter - -PErrorWriter::~PErrorWriter(void) -{ - if(m_proceed) - { -#if ELPP_COMPILER_MSVC - char buff[256]; - strerror_s(buff, 256, errno); - m_logger->stream() << ": " << buff << " [" << errno << "]"; -#else - m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; -#endif - } -} - -// PerformanceTracker - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - -PerformanceTracker::PerformanceTracker(const std::string &blockName, - base::TimestampUnit timestampUnit, - const std::string &loggerId, - bool scopedLog, Level level) : m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), - m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) -{ -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - // We store it locally so that if user happen to change configuration by the end of scope - // or before calling checkpoint, we still depend on state of configuraton at time of construction - el::Logger *loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); - m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); - if(m_enabled) - { - base::utils::DateTime::gettimeofday(&m_startTime); - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED -} - -PerformanceTracker::~PerformanceTracker(void) -{ -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if(m_enabled) - { - base::threading::ScopedLock scopedLock(lock()); - if(m_scopedLog) - { - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = getFormattedTimeTaken(); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); - data.init(this); - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback *callback = nullptr; - for(const std::pair &h : ELPP->m_performanceTrackingCallbacks) - { - callback = h.second.get(); - if(callback != nullptr && callback->enabled()) - { - callback->handle(&data); - } - } - } - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) -} - -void PerformanceTracker::checkpoint(const std::string &id, const char *file, base::type::LineNumber line, - const char *func) -{ -#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - if(m_enabled) - { - base::threading::ScopedLock scopedLock(lock()); - base::utils::DateTime::gettimeofday(&m_endTime); - base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); - PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); - data.init(this); - data.m_checkpointId = id; - data.m_file = file; - data.m_line = line; - data.m_func = func; - data.m_formattedTimeTaken = formattedTime; - PerformanceTrackingCallback *callback = nullptr; - for(const std::pair &h : ELPP->m_performanceTrackingCallbacks) - { - callback = h.second.get(); - if(callback != nullptr && callback->enabled()) - { - callback->handle(&data); - } - } - base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); - m_hasChecked = true; - m_lastCheckpointId = id; - } -#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED - ELPP_UNUSED(id); - ELPP_UNUSED(file); - ELPP_UNUSED(line); - ELPP_UNUSED(func); -} - -const base::type::string_t PerformanceTracker::getFormattedTimeTaken(struct timeval startTime) const -{ - if(ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) - { - base::type::stringstream_t ss; - ss << base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit) - << " " << base::consts::kTimeFormats[static_cast(m_timestampUnit)].unit; - return ss.str(); - } - return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, - startTime, m_timestampUnit), - m_timestampUnit); -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - -namespace debug -{ -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -// StackTrace - -StackTrace::StackTraceEntry::StackTraceEntry(std::size_t index, const char *loc, const char *demang, const char *hex, - const char *addr) -{ - m_index = index; - m_location = std::string(loc); - m_demangled = std::string(demang); - m_hex = std::string(hex); - m_addr = std::string(addr); -} - -std::ostream &operator<<(std::ostream &ss, const StackTrace::StackTraceEntry &si) -{ - ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled - << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr; - return ss; -} - -std::ostream &operator<<(std::ostream &os, const StackTrace &st) -{ - std::vector::const_iterator it = st.m_stack.begin(); - while(it != st.m_stack.end()) - { - os << " " << *it++ << "\n"; - } - return os; -} - -void StackTrace::generateNew(void) -{ -#if ELPP_STACKTRACE - m_stack.clear(); - void *stack[kMaxStack]; - unsigned int size = backtrace(stack, kMaxStack); - char **strings = backtrace_symbols(stack, size); - if(size > kStackStart) - { // Skip StackTrace c'tor and generateNew - for(std::size_t i = kStackStart; i < size; ++i) - { - char *mangName = nullptr; - char *hex = nullptr; - char *addr = nullptr; - for(char *c = strings[i]; *c; ++c) - { - switch(*c) - { - case '(': - mangName = c; - break; - case '+': - hex = c; - break; - case ')': - addr = c; - break; - default: - break; - } - } - // Perform demangling if parsed properly - if(mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex) - { - *mangName++ = '\0'; - *hex++ = '\0'; - *addr++ = '\0'; - int status = 0; - char *demangName = abi::__cxa_demangle(mangName, 0, 0, &status); - // if demangling is successful, output the demangled function name - if(status == 0) - { - // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) - StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr); - m_stack.push_back(entry); - } - else - { - // Not successful - we will use mangled name - StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr); - m_stack.push_back(entry); - } - free(demangName); - } - else - { - StackTraceEntry entry(i - 1, strings[i]); - m_stack.push_back(entry); - } - } - } - free(strings); -#else - ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); -#endif // ELPP_STACKTRACE -} - -// Static helper functions - -static std::string crashReason(int sig) -{ - std::stringstream ss; - bool foundReason = false; - for(int i = 0; i < base::consts::kCrashSignalsCount; ++i) - { - if(base::consts::kCrashSignals[i].numb == sig) - { - ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; - if(ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) - { - ss << std::endl - << " " << base::consts::kCrashSignals[i].brief << std::endl - << " " << base::consts::kCrashSignals[i].detail; - } - foundReason = true; - } - } - if(!foundReason) - { - ss << "Application has crashed due to unknown signal [" << sig << "]"; - } - return ss.str(); -} -/// @brief Logs reason of crash from sig -static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char *logger) -{ - std::stringstream ss; - ss << "CRASH HANDLED; "; - ss << crashReason(sig); -#if ELPP_STACKTRACE - if(stackTraceIfAvailable) - { - ss << std::endl - << " ======= Backtrace: =========" << std::endl - << base::debug::StackTrace(); - } -#else - ELPP_UNUSED(stackTraceIfAvailable); -#endif // ELPP_STACKTRACE - ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); -} - -static inline void crashAbort(int sig) -{ - base::utils::abort(sig, std::string()); -} - -/// @brief Default application crash handler -/// -/// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. -static inline void defaultCrashHandler(int sig) -{ - base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); - base::debug::crashAbort(sig); -} - -// CrashHandler - -CrashHandler::CrashHandler(bool useDefault) -{ - if(useDefault) - { - setHandler(defaultCrashHandler); - } -} - -void CrashHandler::setHandler(const Handler &cHandler) -{ - m_handler = cHandler; -#if defined(ELPP_HANDLE_SIGABRT) - int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] -#else - int i = 1; -#endif // defined(ELPP_HANDLE_SIGABRT) - for(; i < base::consts::kCrashSignalsCount; ++i) - { - m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); - } -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -} // namespace debug -} // namespace base - -// el - -// Helpers - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -void Helpers::crashAbort(int sig, const char *sourceFile, unsigned int long line) -{ - std::stringstream ss; - ss << base::debug::crashReason(sig).c_str(); - ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; - if(sourceFile != nullptr && strlen(sourceFile) > 0) - { - ss << " - Source: " << sourceFile; - if(line > 0) - ss << ":" << line; - else - ss << " (line number not specified)"; - } - base::utils::abort(sig, ss.str()); -} - -void Helpers::logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char *logger) -{ - el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); -} - -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - -// Loggers - -Logger *Loggers::getLogger(const std::string &identity, bool registerIfNotAvailable) -{ - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); -} - -void Loggers::setDefaultLogBuilder(el::LogBuilderPtr &logBuilderPtr) -{ - ELPP->registeredLoggers()->setDefaultLogBuilder(logBuilderPtr); -} - -bool Loggers::unregisterLogger(const std::string &identity) -{ - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->remove(identity); -} - -bool Loggers::hasLogger(const std::string &identity) -{ - base::threading::ScopedLock scopedLock(ELPP->lock()); - return ELPP->registeredLoggers()->has(identity); -} - -Logger *Loggers::reconfigureLogger(Logger *logger, const Configurations &configurations) -{ - if(!logger) - return nullptr; - logger->configure(configurations); - return logger; -} - -Logger *Loggers::reconfigureLogger(const std::string &identity, const Configurations &configurations) -{ - return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); -} - -Logger *Loggers::reconfigureLogger(const std::string &identity, ConfigurationType configurationType, - const std::string &value) -{ - Logger *logger = Loggers::getLogger(identity); - if(logger == nullptr) - { - return nullptr; - } - logger->configurations()->set(Level::Global, configurationType, value); - logger->reconfigure(); - return logger; -} - -void Loggers::reconfigureAllLoggers(const Configurations &configurations) -{ - for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) - { - Loggers::reconfigureLogger(it->second, configurations); - } -} - -void Loggers::reconfigureAllLoggers(Level level, ConfigurationType configurationType, - const std::string &value) -{ - for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); - it != ELPP->registeredLoggers()->end(); ++it) - { - Logger *logger = it->second; - logger->configurations()->set(level, configurationType, value); - logger->reconfigure(); - } -} - -void Loggers::setDefaultConfigurations(const Configurations &configurations, bool reconfigureExistingLoggers) -{ - ELPP->registeredLoggers()->setDefaultConfigurations(configurations); - if(reconfigureExistingLoggers) - { - Loggers::reconfigureAllLoggers(configurations); - } -} - -const Configurations *Loggers::defaultConfigurations(void) -{ - return ELPP->registeredLoggers()->defaultConfigurations(); -} - -const base::LogStreamsReferenceMap *Loggers::logStreamsReference(void) -{ - return ELPP->registeredLoggers()->logStreamsReference(); -} - -base::TypedConfigurations Loggers::defaultTypedConfigurations(void) -{ - return base::TypedConfigurations( - ELPP->registeredLoggers()->defaultConfigurations(), - ELPP->registeredLoggers()->logStreamsReference()); -} - -std::vector *Loggers::populateAllLoggerIds(std::vector *targetList) -{ - targetList->clear(); - for(base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); - it != ELPP->registeredLoggers()->list().end(); ++it) - { - targetList->push_back(it->first); - } - return targetList; -} - -void Loggers::configureFromGlobal(const char *globalConfigurationFilePath) -{ - std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); - ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath - << "] for parsing."); - std::string line = std::string(); - std::stringstream ss; - Logger *logger = nullptr; - auto configure = [&](void) { - ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" - << ss.str() - << "\n--------------"); - Configurations c; - c.parseFromText(ss.str()); - logger->configure(c); - }; - while(gcfStream.good()) - { - std::getline(gcfStream, line); - ELPP_INTERNAL_INFO(1, "Parsing line: " << line); - base::utils::Str::trim(line); - if(Configurations::Parser::isComment(line)) - continue; - Configurations::Parser::ignoreComments(&line); - base::utils::Str::trim(line); - if(line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) - { - if(!ss.str().empty() && logger != nullptr) - { - configure(); - } - ss.str(std::string("")); - line = line.substr(2); - base::utils::Str::trim(line); - if(line.size() > 1) - { - ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); - logger = getLogger(line); - } - } - else - { - ss << line << "\n"; - } - } - if(!ss.str().empty() && logger != nullptr) - { - configure(); - } -} - -bool Loggers::configureFromArg(const char *argKey) -{ -#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - ELPP_UNUSED(argKey); -#else - if(!Helpers::commandLineArgs()->hasParamWithValue(argKey)) - { - return false; - } - configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); -#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) - return true; -} - -void Loggers::flushAll(void) -{ - ELPP->registeredLoggers()->flushAll(); -} - -void Loggers::setVerboseLevel(base::type::VerboseLevel level) -{ - ELPP->vRegistry()->setLevel(level); -} - -base::type::VerboseLevel Loggers::verboseLevel(void) -{ - return ELPP->vRegistry()->level(); -} - -void Loggers::setVModules(const char *modules) -{ - if(ELPP->vRegistry()->vModulesEnabled()) - { - ELPP->vRegistry()->setModules(modules); - } -} - -void Loggers::clearVModules(void) -{ - ELPP->vRegistry()->clearModules(); -} - -void Loggers::setCategories(const char *categories, bool clear) -{ - ELPP->vRegistry()->setCategories(categories, clear); -} - -std::string Loggers::getCategories() -{ - return ELPP->vRegistry()->getCategories(); -} - -void Loggers::clearCategories(void) -{ - ELPP->vRegistry()->clearCategories(); -} - -void Loggers::setFilenameCommonPrefix(const std::string &prefix) -{ - ELPP->vRegistry()->setFilenameCommonPrefix(prefix); -} - -const std::string &Loggers::getFilenameCommonPrefix() -{ - return ELPP->vRegistry()->getFilenameCommonPrefix(); -} - -// VersionInfo - -const std::string VersionInfo::version(void) -{ - return std::string("9.94.1"); -} -/// @brief Release date of current version -const std::string VersionInfo::releaseDate(void) -{ - return std::string("25-02-2017 0813hrs"); -} - -} // namespace el diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h deleted file mode 100644 index 78c69ac8..00000000 --- a/external/easylogging++/easylogging++.h +++ /dev/null @@ -1,5261 +0,0 @@ -// -// Bismillah ar-Rahmaan ar-Raheem -// -// Easylogging++ v9.94.1 -// Single-header only, cross-platform logging library for C++ applications -// -// Copyright (c) 2017 muflihun.com -// -// This library is released under the MIT Licence. -// http://labs.muflihun.com/easyloggingpp/licence.php -// -// https://github.com/muflihun/easyloggingpp -// https://muflihun.github.io/easyloggingpp -// http://muflihun.com -// -#ifndef EASYLOGGINGPP_H -#define EASYLOGGINGPP_H -#include "ea_config.h" -// Compilers and C++0x/C++11 Evaluation -#if __cplusplus >= 201103L -#define ELPP_CXX11 1 -#endif // __cplusplus >= 201103L -#if(defined(__GNUC__)) -#define ELPP_COMPILER_GCC 1 -#else -#define ELPP_COMPILER_GCC 0 -#endif -#if ELPP_COMPILER_GCC -#define ELPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if defined(__GXX_EXPERIMENTAL_CXX0X__) -#define ELPP_CXX0X 1 -#endif -#endif -// Visual C++ -#if defined(_MSC_VER) -#define ELPP_COMPILER_MSVC 1 -#else -#define ELPP_COMPILER_MSVC 0 -#endif -#define ELPP_CRT_DBG_WARNINGS ELPP_COMPILER_MSVC -#if ELPP_COMPILER_MSVC -#if(_MSC_VER == 1600) -#define ELPP_CXX0X 1 -#elif(_MSC_VER >= 1700) -#define ELPP_CXX11 1 -#endif -#endif -// Clang++ -#if(defined(__clang__) && (__clang__ == 1)) -#define ELPP_COMPILER_CLANG 1 -#else -#define ELPP_COMPILER_CLANG 0 -#endif -#if ELPP_COMPILER_CLANG -#if __has_include() -#include // Make __GLIBCXX__ defined when using libstdc++ -#if !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 -#define ELPP_CLANG_SUPPORTS_THREAD -#endif // !defined(__GLIBCXX__) || __GLIBCXX__ >= 20150426 -#endif // __has_include() -#endif -#if(defined(__MINGW32__) || defined(__MINGW64__)) -#define ELPP_MINGW 1 -#else -#define ELPP_MINGW 0 -#endif -#if(defined(__CYGWIN__) && (__CYGWIN__ == 1)) -#define ELPP_CYGWIN 1 -#else -#define ELPP_CYGWIN 0 -#endif -#if(defined(__INTEL_COMPILER)) -#define ELPP_COMPILER_INTEL 1 -#else -#define ELPP_COMPILER_INTEL 0 -#endif -// Operating System Evaluation -// Windows -#if(defined(_WIN32) || defined(_WIN64)) -#define ELPP_OS_WINDOWS 1 -#else -#define ELPP_OS_WINDOWS 0 -#endif -// Linux -#if(defined(__linux) || defined(__linux__)) -#define ELPP_OS_LINUX 1 -#else -#define ELPP_OS_LINUX 0 -#endif -#if(defined(__APPLE__)) -#define ELPP_OS_MAC 1 -#else -#define ELPP_OS_MAC 0 -#endif -#if(defined(__FreeBSD__)) -#define ELPP_OS_FREEBSD 1 -#else -#define ELPP_OS_FREEBSD 0 -#endif -#if(defined(__OpenBSD__)) -#define ELPP_OS_OPENBSD 1 -#else -#define ELPP_OS_OPENBSD 0 -#endif -#if(defined(__sun)) -#define ELPP_OS_SOLARIS 1 -#else -#define ELPP_OS_SOLARIS 0 -#endif -#if(defined(__DragonFly__)) -#define ELPP_OS_DRAGONFLY 1 -#else -#define ELPP_OS_DRAGONFLY 0 -#endif -// Unix -#if((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS || ELPP_OS_DRAGONFLY || ELPP_OS_OPENBSD) && (!ELPP_OS_WINDOWS)) -#define ELPP_OS_UNIX 1 -#else -#define ELPP_OS_UNIX 0 -#endif -#if(defined(__ANDROID__)) -#define ELPP_OS_ANDROID 1 -#else -#define ELPP_OS_ANDROID 0 -#endif -// Evaluating Cygwin as *nix OS -#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -#undef ELPP_OS_UNIX -#undef ELPP_OS_LINUX -#define ELPP_OS_UNIX 1 -#define ELPP_OS_LINUX 1 -#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) -#define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) -#define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) -#define ELPP_INTERNAL_DEBUGGING_ENDL std::endl -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) -#define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg -#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) -// Internal Assertions and errors -#if !defined(ELPP_DISABLE_ASSERT) -#if(defined(ELPP_DEBUG_ASSERT_FAILURE)) -#define ELPP_ASSERT(expr, msg) \ - if(!(expr)) \ - { \ - std::stringstream internalInfoStream; \ - internalInfoStream << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ - << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ - << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; \ - base::utils::abort(1, \ - "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); \ - } -#else -#define ELPP_ASSERT(expr, msg) \ - if(!(expr)) \ - { \ - std::stringstream internalInfoStream; \ - internalInfoStream << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ - << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ - << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ - << ELPP_INTERNAL_DEBUGGING_ENDL; \ - } -#endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) -#else -#define ELPP_ASSERT(x, y) -#endif //(!defined(ELPP_DISABLE_ASSERT) -#if ELPP_COMPILER_MSVC -#define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ - { \ - char buff[256]; \ - strerror_s(buff, 256, errno); \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]"; \ - } \ - (void)0 -#else -#define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; \ - (void)0 -#endif // ELPP_COMPILER_MSVC -#if defined(ELPP_DEBUG_ERRORS) -#if !defined(ELPP_INTERNAL_ERROR) -#define ELPP_INTERNAL_ERROR(msg, pe) \ - { \ - std::stringstream internalInfoStream; \ - internalInfoStream << " " << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ - << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ - << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ - if(pe) \ - { \ - ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; \ - ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; \ - } \ - } \ - (void)0 -#endif -#else -#undef ELPP_INTERNAL_INFO -#define ELPP_INTERNAL_ERROR(msg, pe) -#endif // defined(ELPP_DEBUG_ERRORS) -#if(defined(ELPP_DEBUG_INFO)) -#if !(defined(ELPP_INTERNAL_INFO_LEVEL)) -#define ELPP_INTERNAL_INFO_LEVEL 9 -#endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) -#if !defined(ELPP_INTERNAL_INFO) -#define ELPP_INTERNAL_INFO(lvl, msg) \ - { \ - if(lvl <= ELPP_INTERNAL_INFO_LEVEL) \ - { \ - std::stringstream internalInfoStream; \ - internalInfoStream << " " << msg; \ - ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ - << ELPP_INTERNAL_DEBUGGING_ENDL; \ - } \ - } -#endif -#else -#undef ELPP_INTERNAL_INFO -#define ELPP_INTERNAL_INFO(lvl, msg) -#endif // (defined(ELPP_DEBUG_INFO)) -#if(defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) -#if(ELPP_COMPILER_GCC && !ELPP_MINGW && !ELPP_OS_OPENBSD) -#define ELPP_STACKTRACE 1 -#else -#define ELPP_STACKTRACE 0 -#ifdef EASYLOGGING_CC -#if ELPP_COMPILER_MSVC -#pragma message("Stack trace not available for this compiler") -#else -#warning "Stack trace not available for this compiler"; -#endif // ELPP_COMPILER_MSVC -#endif -#endif // ELPP_COMPILER_GCC -#else -#define ELPP_STACKTRACE 0 -#endif // (defined(ELPP_FEATURE_ALL)) || (defined(ELPP_FEATURE_CRASH_LOG)) -// Miscellaneous macros -#define ELPP_UNUSED(x) (void)x -#if ELPP_OS_UNIX -// Log file permissions for unix-based systems -#define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH -#endif // ELPP_OS_UNIX -#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -#if defined(ELPP_EXPORT_SYMBOLS) -#define ELPP_EXPORT __declspec(dllexport) -#else -#define ELPP_EXPORT __declspec(dllimport) -#endif // defined(ELPP_EXPORT_SYMBOLS) -#else -#define ELPP_EXPORT -#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC -// Some special functions that are VC++ specific -#undef STRTOK -#undef STRERROR -#undef STRCAT -#undef STRCPY -#if ELPP_CRT_DBG_WARNINGS -#define STRTOK(a, b, c) strtok_s(a, b, c) -#define STRERROR(a, b, c) strerror_s(a, b, c) -#define STRCAT(a, b, len) strcat_s(a, len, b) -#define STRCPY(a, b, len) strcpy_s(a, len, b) -#else -#define STRTOK(a, b, c) strtok(a, b) -#define STRERROR(a, b, c) strerror(c) -#define STRCAT(a, b, len) strcat(a, b) -#define STRCPY(a, b, len) strcpy(a, b) -#endif -// Compiler specific support evaluations -#if(ELPP_MINGW && !defined(ELPP_FORCE_USE_STD_THREAD)) -#define ELPP_USE_STD_THREADING 0 -#else -#if((ELPP_COMPILER_CLANG && defined(ELPP_CLANG_SUPPORTS_THREAD)) || \ - (!ELPP_COMPILER_CLANG && defined(ELPP_CXX11)) || \ - defined(ELPP_FORCE_USE_STD_THREAD)) -#define ELPP_USE_STD_THREADING 1 -#else -#define ELPP_USE_STD_THREADING 0 -#endif -#endif -#undef ELPP_FINAL -#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -#define ELPP_FINAL -#else -#define ELPP_FINAL final -#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) -#if defined(ELPP_EXPERIMENTAL_ASYNC) -#define ELPP_ASYNC_LOGGING 1 -#else -#define ELPP_ASYNC_LOGGING 0 -#endif // defined(ELPP_EXPERIMENTAL_ASYNC) -#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -#define ELPP_THREADING_ENABLED 1 -#else -#define ELPP_THREADING_ENABLED 0 -#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING -// Function macro ELPP_FUNC -#undef ELPP_FUNC -#if ELPP_COMPILER_MSVC // Visual C++ -#define ELPP_FUNC __FUNCSIG__ -#elif ELPP_COMPILER_GCC // GCC -#define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_INTEL // Intel C++ -#define ELPP_FUNC __PRETTY_FUNCTION__ -#elif ELPP_COMPILER_CLANG // Clang++ -#define ELPP_FUNC __PRETTY_FUNCTION__ -#else -#if defined(__func__) -#define ELPP_FUNC __func__ -#else -#define ELPP_FUNC "" -#endif // defined(__func__) -#endif // defined(_MSC_VER) -#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED -// Keep following line commented until features are fixed -#define ELPP_VARIADIC_TEMPLATES_SUPPORTED \ - (ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800)) -// Logging Enable/Disable macros -#ifdef ELPP_DISABLE_LOGS -#define ELPP_LOGGING_ENABLED 0 -#else -#define ELPP_LOGGING_ENABLED 1 -#endif -#if(!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_DEBUG_LOG 1 -#else -#define ELPP_DEBUG_LOG 0 -#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_INFO_LOG 1 -#else -#define ELPP_INFO_LOG 0 -#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_WARNING_LOG 1 -#else -#define ELPP_WARNING_LOG 0 -#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_ERROR_LOG 1 -#else -#define ELPP_ERROR_LOG 0 -#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_FATAL_LOG 1 -#else -#define ELPP_FATAL_LOG 0 -#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_TRACE_LOG 1 -#else -#define ELPP_TRACE_LOG 0 -#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -#define ELPP_VERBOSE_LOG 1 -#else -#define ELPP_VERBOSE_LOG 0 -#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) -#if(!(ELPP_CXX0X || ELPP_CXX11)) -#error "C++0x (or higher) support not detected! (Is `-std=c++11' missing?)" -#endif // (!(ELPP_CXX0X || ELPP_CXX11)) -// Headers -#if defined(ELPP_SYSLOG) -#include -#endif // defined(ELPP_SYSLOG) -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(ELPP_UNICODE) -#include -#if ELPP_OS_WINDOWS -#include -#endif // ELPP_OS_WINDOWS -#endif // defined(ELPP_UNICODE) -#if ELPP_STACKTRACE -#include -#include -#endif // ELPP_STACKTRACE -#if ELPP_OS_ANDROID -#include -#endif // ELPP_OS_ANDROID -#if ELPP_OS_UNIX -#include -#include -#elif ELPP_OS_WINDOWS -#include -#include -#if defined(WIN32_LEAN_AND_MEAN) -#if defined(ELPP_WINSOCK2) -#include -#else -#include -#endif // defined(ELPP_WINSOCK2) -#endif // defined(WIN32_LEAN_AND_MEAN) -#endif // ELPP_OS_UNIX -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if ELPP_THREADING_ENABLED -#if ELPP_USE_STD_THREADING -#include -#include -#else -#if ELPP_OS_UNIX -#include -#endif // ELPP_OS_UNIX -#endif // ELPP_USE_STD_THREADING -#endif // ELPP_THREADING_ENABLED -#if ELPP_ASYNC_LOGGING -#if defined(ELPP_NO_SLEEP_FOR) -#include -#endif // defined(ELPP_NO_SLEEP_FOR) -#include -#include -#include -#endif // ELPP_ASYNC_LOGGING -#if defined(ELPP_STL_LOGGING) -// For logging STL based templates -#include -#include -#include -#include -#include -#include -#if defined(ELPP_LOG_STD_ARRAY) -#include -#endif // defined(ELPP_LOG_STD_ARRAY) -#if defined(ELPP_LOG_UNORDERED_MAP) -#include -#endif // defined(ELPP_LOG_UNORDERED_MAP) -#if defined(ELPP_LOG_UNORDERED_SET) -#include -#endif // defined(ELPP_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) -// For logging Qt based classes & templates -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) -// For logging boost based classes & templates -#include -#include -#include -#include -#include -#include -#include -#include -#endif // defined(ELPP_BOOST_LOGGING) -#if defined(ELPP_WXWIDGETS_LOGGING) -// For logging wxWidgets based classes & templates -#include -#endif // defined(ELPP_WXWIDGETS_LOGGING) -// Forward declarations -namespace el -{ -class Logger; -class LogMessage; -class PerformanceTrackingData; -class Loggers; -class Helpers; -template -class Callback; -class LogDispatchCallback; -class PerformanceTrackingCallback; -class LoggerRegistrationCallback; -class LogDispatchData; -namespace base -{ -class Storage; -class RegisteredLoggers; -class PerformanceTracker; -class MessageBuilder; -class Writer; -class PErrorWriter; -class LogDispatcher; -class DefaultLogBuilder; -class DefaultLogDispatchCallback; -#if ELPP_ASYNC_LOGGING -class AsyncLogDispatchCallback; -class AsyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING -class DefaultPerformanceTrackingCallback; -} // namespace base -} // namespace el -/// @brief Easylogging++ entry namespace -namespace el -{ -/// @brief Namespace containing base/internal functionality used by Easylogging++ -namespace base -{ -/// @brief Data types used by Easylogging++ -namespace type -{ -#undef ELPP_LITERAL -#undef ELPP_STRLEN -#undef ELPP_COUT -#if defined(ELPP_UNICODE) -#define ELPP_LITERAL(txt) L##txt -#define ELPP_STRLEN wcslen -#if defined ELPP_CUSTOM_COUT -#define ELPP_COUT ELPP_CUSTOM_COUT -#else -#define ELPP_COUT std::wcout -#endif // defined ELPP_CUSTOM_COUT -typedef wchar_t char_t; -typedef std::wstring string_t; -typedef std::wstringstream stringstream_t; -typedef std::wfstream fstream_t; -typedef std::wostream ostream_t; -#else -#define ELPP_LITERAL(txt) txt -#define ELPP_STRLEN strlen -#if defined ELPP_CUSTOM_COUT -#define ELPP_COUT ELPP_CUSTOM_COUT -#else -#define ELPP_COUT std::cout -#endif // defined ELPP_CUSTOM_COUT -typedef char char_t; -typedef std::string string_t; -typedef std::stringstream stringstream_t; -typedef std::fstream fstream_t; -typedef std::ostream ostream_t; -#endif // defined(ELPP_UNICODE) -#if defined(ELPP_CUSTOM_COUT_LINE) -#define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) -#else -#define ELPP_COUT_LINE(logLine) logLine << std::flush -#endif // defined(ELPP_CUSTOM_COUT_LINE) -typedef unsigned int EnumType; -typedef unsigned short VerboseLevel; -typedef unsigned long int LineNumber; -typedef std::shared_ptr StoragePointer; -typedef std::shared_ptr LogDispatchCallbackPtr; -typedef std::shared_ptr PerformanceTrackingCallbackPtr; -typedef std::shared_ptr LoggerRegistrationCallbackPtr; -typedef std::unique_ptr PerformanceTrackerPtr; -} // namespace type -/// @brief Internal helper class that prevent copy constructor for class -/// -/// @detail When using this class simply inherit it privately -class NoCopy -{ - protected: - NoCopy(void) {} - private: - NoCopy(const NoCopy &); - NoCopy &operator=(const NoCopy &); -}; -/// @brief Internal helper class that makes all default constructors private. -/// -/// @detail This prevents initializing class making it static unless an explicit constructor is declared. -/// When using this class simply inherit it privately -class StaticClass -{ - private: - StaticClass(void); - StaticClass(const StaticClass &); - StaticClass &operator=(const StaticClass &); -}; -} // namespace base -/// @brief Represents enumeration for severity level used to determine level of logging -/// -/// @detail With Easylogging++, developers may disable or enable any level regardless of -/// what the severity is. Or they can choose to log using hierarchical logging flag -enum class Level : base::type::EnumType -{ - /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels - Global = 1, - /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. - Trace = 2, - /// @brief Informational events most useful for developers to debug application - Debug = 4, - /// @brief Severe error information that will presumably abort application - Fatal = 8, - /// @brief Information representing errors in application but application will keep running - Error = 16, - /// @brief Useful when application has potentially harmful situtaions - Warning = 32, - /// @brief Information that can be highly useful and vary with verbose logging level. - Verbose = 64, - /// @brief Mainly useful to represent current progress of application - Info = 128, - /// @brief Represents unknown level - Unknown = 1010 -}; -/// @brief Static class that contains helper functions for el::Level -class LevelHelper : base::StaticClass -{ - public: - /// @brief Represents minimum valid level. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(Level::Trace); - /// @brief Represents maximum valid level. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(Level::Info); - /// @brief Casts level to int, useful for iterating through enum. - static base::type::EnumType castToInt(Level level) - { - return static_cast(level); - } - /// @brief Casts int(ushort) to level, useful for iterating through enum. - static Level castFromInt(base::type::EnumType l) - { - return static_cast(l); - } - /// @brief Converts level to associated const char* - /// @return Upper case string based level. - static const char *convertToString(Level level); - /// @brief Converts from prefix of levelStr to Level - /// @param levelStr Upper case string based level. - /// Lower case is also valid but providing upper case is recommended. - static Level convertFromStringPrefix(const char *levelStr); - /// @brief Converts from levelStr to Level - /// @param levelStr Upper case string based level. - /// Lower case is also valid but providing upper case is recommended. - static Level convertFromString(const char *levelStr); - /// @brief Applies specified function to each level starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed as pointer and - /// is left-shifted so this can be used inside function (fn) to represent current level. - /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. - static void forEachLevel(base::type::EnumType *startIndex, const std::function &fn); -}; -/// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect -/// of logging -enum class ConfigurationType : base::type::EnumType -{ - /// @brief Determines whether or not corresponding level and logger of logging is enabled - /// You may disable all logs by using el::Level::Global - Enabled = 1, - /// @brief Whether or not to write corresponding log to log file - ToFile = 2, - /// @brief Whether or not to write corresponding level and logger log to standard output. - /// By standard output meaning termnal, command prompt etc - ToStandardOutput = 4, - /// @brief Determines format of logging corresponding level and logger. - Format = 8, - /// @brief Determines log file (full path) to write logs to for correponding level and logger - Filename = 16, - /// @brief Specifies precision of the subsecond part. It should be within range (1-6). - SubsecondPrecision = 32, - /// @brief Alias of SubsecondPrecision (for backward compatibility) - MillisecondsWidth = SubsecondPrecision, - /// @brief Determines whether or not performance tracking is enabled. - /// - /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger - PerformanceTracking = 64, - /// @brief Specifies log file max size. - /// - /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will - /// be truncated and re-initiated. - MaxLogFileSize = 128, - /// @brief Specifies number of log entries to hold until we flush pending log data - LogFlushThreshold = 256, - /// @brief Represents unknown configuration - Unknown = 1010 -}; -/// @brief Static class that contains helper functions for el::ConfigurationType -class ConfigurationTypeHelper : base::StaticClass -{ - public: - /// @brief Represents minimum valid configuration type. Useful when iterating through enum. - static const base::type::EnumType kMinValid = static_cast(ConfigurationType::Enabled); - /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. - static const base::type::EnumType kMaxValid = static_cast(ConfigurationType::MaxLogFileSize); - /// @brief Casts configuration type to int, useful for iterating through enum. - static base::type::EnumType castToInt(ConfigurationType configurationType) - { - return static_cast(configurationType); - } - /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. - static ConfigurationType castFromInt(base::type::EnumType c) - { - return static_cast(c); - } - /// @brief Converts configuration type to associated const char* - /// @returns Upper case string based configuration type. - static const char *convertToString(ConfigurationType configurationType); - /// @brief Converts from configStr to ConfigurationType - /// @param configStr Upper case string based configuration type. - /// Lower case is also valid but providing upper case is recommended. - static ConfigurationType convertFromString(const char *configStr); - /// @brief Applies specified function to each configuration type starting from startIndex - /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted - /// so this can be used inside function (fn) to represent current configuration type. - /// @param fn function to apply with each configuration type. - /// This bool represent whether or not to stop iterating through configurations. - static inline void forEachConfigType(base::type::EnumType *startIndex, const std::function &fn); -}; -/// @brief Flags used while writing logs. This flags are set by user -enum class LoggingFlag : base::type::EnumType -{ - /// @brief Makes sure we have new line for each container log entry - NewLineForContainer = 1, - /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose - /// logging is allowed via that module. - AllowVerboseIfModuleNotSpecified = 2, - /// @brief When handling crashes by default, detailed crash reason will be logged as well - LogDetailedCrashReason = 4, - /// @brief Allows to disable application abortion when logged using FATAL level - DisableApplicationAbortOnFatalLog = 8, - /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default - ImmediateFlush = 16, - /// @brief Enables strict file rolling - StrictLogFileSizeCheck = 32, - /// @brief Make terminal output colorful for supported terminals - ColoredTerminalOutput = 64, - /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") - MultiLoggerSupport = 128, - /// @brief Disables comparing performance tracker's checkpoints - DisablePerformanceTrackingCheckpointComparison = 256, - /// @brief Disable VModules - DisableVModules = 512, - /// @brief Disable VModules extensions - DisableVModulesExtensions = 1024, - /// @brief Enables hierarchical logging - HierarchicalLogging = 2048, - /// @brief Creates logger automatically when not available - CreateLoggerAutomatically = 4096, - /// @brief Adds spaces b/w logs that separated by left-shift operator - AutoSpacing = 8192, - /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) - FixedTimeFormat = 16384 -}; -namespace base -{ -/// @brief Namespace containing constants used internally. -namespace consts -{ -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif -// Level log values - These are values that are replaced in place of %level format specifier -static const base::type::char_t *kInfoLevelLogValue = ELPP_LITERAL("INFO "); -static const base::type::char_t *kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); -static const base::type::char_t *kWarningLevelLogValue = ELPP_LITERAL("WARN "); -static const base::type::char_t *kErrorLevelLogValue = ELPP_LITERAL("ERROR"); -static const base::type::char_t *kFatalLevelLogValue = ELPP_LITERAL("FATAL"); -static const base::type::char_t *kVerboseLevelLogValue = ELPP_LITERAL("VER"); -static const base::type::char_t *kTraceLevelLogValue = ELPP_LITERAL("TRACE"); -static const base::type::char_t *kInfoLevelShortLogValue = ELPP_LITERAL("I"); -static const base::type::char_t *kDebugLevelShortLogValue = ELPP_LITERAL("D"); -static const base::type::char_t *kWarningLevelShortLogValue = ELPP_LITERAL("W"); -static const base::type::char_t *kErrorLevelShortLogValue = ELPP_LITERAL("E"); -static const base::type::char_t *kFatalLevelShortLogValue = ELPP_LITERAL("F"); -static const base::type::char_t *kVerboseLevelShortLogValue = ELPP_LITERAL("V"); -static const base::type::char_t *kTraceLevelShortLogValue = ELPP_LITERAL("T"); -// Format specifiers - These are used to define log format -static const base::type::char_t *kAppNameFormatSpecifier = ELPP_LITERAL("%app"); -static const base::type::char_t *kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); -static const base::type::char_t *kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); -static const base::type::char_t *kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); -static const base::type::char_t *kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); -static const base::type::char_t *kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); -static const base::type::char_t *kLogFileFormatSpecifier = ELPP_LITERAL("%file"); -static const base::type::char_t *kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); -static const base::type::char_t *kLogLineFormatSpecifier = ELPP_LITERAL("%line"); -static const base::type::char_t *kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); -static const base::type::char_t *kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); -static const base::type::char_t *kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); -static const base::type::char_t *kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); -static const base::type::char_t *kMessageFormatSpecifier = ELPP_LITERAL("%msg"); -static const base::type::char_t *kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); -static const char *kDateTimeFormatSpecifierForFilename = "%datetime"; -// Date/time -static const char *kDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; -static const char *kDaysAbbrev[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -static const char *kMonths[12] = {"January", "February", "March", "Apri", "May", "June", "July", "August", - "September", "October", "November", "December"}; -static const char *kMonthsAbbrev[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; -static const char *kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; -static const char *kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; -static const int kYearBase = 1900; -static const char *kAm = "AM"; -static const char *kPm = "PM"; -// Miscellaneous constants -#ifdef ELPP_DEFAULT_LOGGER -static const char *kDefaultLoggerId = ELPP_DEFAULT_LOGGER; -#else -static const char *kDefaultLoggerId = "default"; -#endif -#ifdef ELPP_DEFAULT_PERFORMANCE_LOGGER -static const char *kPerformanceLoggerId = ELPP_DEFAULT_PERFORMANCE_LOGGER; -#else -static const char *kPerformanceLoggerId = "performance"; -#endif -#if defined(ELPP_SYSLOG) -static const char *kSysLogLoggerId = "syslog"; -#endif // defined(ELPP_SYSLOG) -static const char *kNullPointer = "nullptr"; -static const char kFormatSpecifierChar = '%'; -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -static const char kFormatSpecifierCharValue = 'v'; -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -static const unsigned int kMaxLogPerContainer = 100; -static const unsigned int kMaxLogPerCounter = 100000; -static const unsigned int kDefaultSubsecondPrecision = 3; -static const base::type::VerboseLevel kMaxVerboseLevel = 9; -static const char *kUnknownUser = "user"; -static const char *kUnknownHost = "unknown-host"; -#if defined(ELPP_DEFAULT_LOG_FILE) -static const char *kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; -#else -#if ELPP_OS_UNIX -#if ELPP_OS_ANDROID -static const char *kDefaultLogFile = "logs/myeasylog.log"; -#else -static const char *kDefaultLogFile = "logs/myeasylog.log"; -#endif // ELPP_OS_ANDROID -#elif ELPP_OS_WINDOWS -static const char *kDefaultLogFile = "logs\\myeasylog.log"; -#endif // ELPP_OS_UNIX -#endif // defined(ELPP_DEFAULT_LOG_FILE) -#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -static const char *kDefaultLogFileParam = "--default-log-file"; -#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) -#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) -static const char *kLoggingFlagsParam = "--logging-flags"; -#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) -#if ELPP_OS_WINDOWS -static const char *kFilePathSeperator = "\\"; -#else -static const char *kFilePathSeperator = "/"; -#endif // ELPP_OS_WINDOWS -static const char *kValidLoggerIdSymbols = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; -static const char *kConfigurationComment = "##"; -static const char *kConfigurationLevel = "*"; -static const char *kConfigurationLoggerId = "--"; -static const std::size_t kSourceFilenameMaxLength = 100; -static const std::size_t kSourceLineMaxLength = 10; -static const Level kPerformanceTrackerDefaultLevel = Level::Info; -const struct -{ - double value; - const base::type::char_t *unit; -} kTimeFormats[] = { - {1000.0f, ELPP_LITERAL("us")}, - {1000.0f, ELPP_LITERAL("ms")}, - {60.0f, ELPP_LITERAL("seconds")}, - {60.0f, ELPP_LITERAL("minutes")}, - {24.0f, ELPP_LITERAL("hours")}, - {7.0f, ELPP_LITERAL("days")}}; -static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); -const struct -{ - int numb; - const char *name; - const char *brief; - const char *detail; -} kCrashSignals[] = { - // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) - { - SIGABRT, "SIGABRT", "Abnormal termination", - "Program was abnormally terminated."}, - {SIGFPE, "SIGFPE", "Erroneous arithmetic operation", - "Arithemetic operation issue such as division by zero or operation resulting in overflow."}, - {SIGILL, "SIGILL", "Illegal instruction", - "Generally due to a corruption in the code or to an attempt to execute data."}, - {SIGSEGV, "SIGSEGV", "Invalid access to memory", - "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory."}, - {SIGINT, "SIGINT", "Interactive attention signal", - "Interruption generated (generally) by user or operating system."}, -}; -static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif -} // namespace consts -} // namespace base -typedef std::function PreRollOutCallback; -namespace base -{ -static inline void defaultPreRollOutCallback(const char *, std::size_t) {} -/// @brief Enum to represent timestamp unit -enum class TimestampUnit : base::type::EnumType -{ - Microsecond = 0, - Millisecond = 1, - Second = 2, - Minute = 3, - Hour = 4, - Day = 5 -}; -/// @brief Format flags used to determine specifiers that are active for performance improvements. -enum class FormatFlags : base::type::EnumType -{ - DateTime = 1 << 1, - LoggerId = 1 << 2, - File = 1 << 3, - Line = 1 << 4, - Location = 1 << 5, - Function = 1 << 6, - User = 1 << 7, - Host = 1 << 8, - LogMessage = 1 << 9, - VerboseLevel = 1 << 10, - AppName = 1 << 11, - ThreadId = 1 << 12, - Level = 1 << 13, - FileBase = 1 << 14, - LevelShort = 1 << 15 -}; -/// @brief A subsecond precision class containing actual width and offset of the subsecond part -class SubsecondPrecision -{ - public: - SubsecondPrecision(void) - { - init(base::consts::kDefaultSubsecondPrecision); - } - explicit SubsecondPrecision(int width) - { - init(width); - } - bool operator==(const SubsecondPrecision &ssPrec) - { - return m_width == ssPrec.m_width && m_offset == ssPrec.m_offset; - } - int m_width; - unsigned int m_offset; - - private: - void init(int width); -}; -/// @brief Type alias of SubsecondPrecision -typedef SubsecondPrecision MillisecondsWidth; -/// @brief Namespace containing utility functions/static classes used internally -namespace utils -{ -/// @brief Deletes memory safely and points to null -template -static - typename std::enable_if::value, void>::type - safeDelete(T *&pointer) -{ - if(pointer == nullptr) - return; - delete pointer; - pointer = nullptr; -} -/// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation -/// Use these function as
flag = bitwise::Or(MyEnum::val1, flag);
-namespace bitwise -{ -template -static inline base::type::EnumType And(Enum e, base::type::EnumType flag) -{ - return static_cast(flag) & static_cast(e); -} -template -static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) -{ - return static_cast(flag) & ~(static_cast(e)); -} -template -static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) -{ - return static_cast(flag) | static_cast(e); -} -} // namespace bitwise -template -static inline void addFlag(Enum e, base::type::EnumType *flag) -{ - *flag = base::utils::bitwise::Or(e, *flag); -} -template -static inline void removeFlag(Enum e, base::type::EnumType *flag) -{ - *flag = base::utils::bitwise::Not(e, *flag); -} -template -static inline bool hasFlag(Enum e, base::type::EnumType flag) -{ - return base::utils::bitwise::And(e, flag) > 0x0; -} -} // namespace utils -namespace threading -{ -#if ELPP_THREADING_ENABLED -#if !ELPP_USE_STD_THREADING -namespace internal -{ -/// @brief A mutex wrapper for compiler that dont yet support std::recursive_mutex -class Mutex : base::NoCopy -{ - public: - Mutex(void) - { -#if ELPP_OS_UNIX - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&m_underlyingMutex, &attr); - pthread_mutexattr_destroy(&attr); -#elif ELPP_OS_WINDOWS - InitializeCriticalSection(&m_underlyingMutex); -#endif // ELPP_OS_UNIX - } - - virtual ~Mutex(void) - { -#if ELPP_OS_UNIX - pthread_mutex_destroy(&m_underlyingMutex); -#elif ELPP_OS_WINDOWS - DeleteCriticalSection(&m_underlyingMutex); -#endif // ELPP_OS_UNIX - } - - inline void lock(void) - { -#if ELPP_OS_UNIX - pthread_mutex_lock(&m_underlyingMutex); -#elif ELPP_OS_WINDOWS - EnterCriticalSection(&m_underlyingMutex); -#endif // ELPP_OS_UNIX - } - - inline bool try_lock(void) - { -#if ELPP_OS_UNIX - return (pthread_mutex_trylock(&m_underlyingMutex) == 0); -#elif ELPP_OS_WINDOWS - return TryEnterCriticalSection(&m_underlyingMutex); -#endif // ELPP_OS_UNIX - } - - inline void unlock(void) - { -#if ELPP_OS_UNIX - pthread_mutex_unlock(&m_underlyingMutex); -#elif ELPP_OS_WINDOWS - LeaveCriticalSection(&m_underlyingMutex); -#endif // ELPP_OS_UNIX - } - - private: -#if ELPP_OS_UNIX - pthread_mutex_t m_underlyingMutex; -#elif ELPP_OS_WINDOWS - CRITICAL_SECTION m_underlyingMutex; -#endif // ELPP_OS_UNIX -}; -/// @brief Scoped lock for compiler that dont yet support std::lock_guard -template -class ScopedLock : base::NoCopy -{ - public: - explicit ScopedLock(M &mutex) - { - m_mutex = &mutex; - m_mutex->lock(); - } - - virtual ~ScopedLock(void) - { - m_mutex->unlock(); - } - - private: - M *m_mutex; - ScopedLock(void); -}; -} // namespace internal -typedef base::threading::internal::Mutex Mutex; -typedef base::threading::internal::ScopedLock ScopedLock; -#else -typedef std::recursive_mutex Mutex; -typedef std::lock_guard ScopedLock; -#endif // !ELPP_USE_STD_THREADING -#else -namespace internal -{ -/// @brief Mutex wrapper used when multi-threading is disabled. -class NoMutex : base::NoCopy -{ - public: - NoMutex(void) {} - inline void lock(void) {} - inline bool try_lock(void) - { - return true; - } - inline void unlock(void) {} -}; -/// @brief Lock guard wrapper used when multi-threading is disabled. -template -class NoScopedLock : base::NoCopy -{ - public: - explicit NoScopedLock(Mutex &) - { - } - virtual ~NoScopedLock(void) - { - } - - private: - NoScopedLock(void); -}; -} // namespace internal -typedef base::threading::internal::NoMutex Mutex; -typedef base::threading::internal::NoScopedLock ScopedLock; -#endif // ELPP_THREADING_ENABLED -/// @brief Base of thread safe class, this class is inheritable-only -class ThreadSafe -{ - public: - virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } - virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } - virtual inline base::threading::Mutex &lock(void) ELPP_FINAL { return m_mutex; } - protected: - ThreadSafe(void) {} - virtual ~ThreadSafe(void) {} - private: - base::threading::Mutex m_mutex; -}; - -#if ELPP_THREADING_ENABLED -#if !ELPP_USE_STD_THREADING -/// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. -static std::string getCurrentThreadId(void) -{ - std::stringstream ss; -#if(ELPP_OS_WINDOWS) - ss << GetCurrentThreadId(); -#endif // (ELPP_OS_WINDOWS) - return ss.str(); -} -#else -/// @brief Gets ID of currently running threading using std::this_thread::get_id() -static std::string getCurrentThreadId(void) -{ - std::stringstream ss; - char prev_fill = ss.fill(' '); - auto prev_flags = ss.flags(std::ios::hex); - //ss.setf(std::ios::hex); - auto prev_width = ss.width(16); - ss << std::this_thread::get_id(); - ss.fill(prev_fill); - ss.flags(prev_flags); - ss.width(prev_width); - return ss.str(); -} -#endif // !ELPP_USE_STD_THREADING -#else -static inline std::string getCurrentThreadId(void) -{ - return std::string(); -} -#endif // ELPP_THREADING_ENABLED -} // namespace threading -namespace utils -{ -class File : base::StaticClass -{ - public: - /// @brief Creates new out file stream for specified filename. - /// @return Pointer to newly created fstream or nullptr - static base::type::fstream_t *newFileStream(const std::string &filename); - - /// @brief Gets size of file provided in stream - static std::size_t getSizeOfFile(base::type::fstream_t *fs); - - /// @brief Determines whether or not provided path exist in current file system - static bool pathExists(const char *path, bool considerFile = false); - - /// @brief Creates specified path on file system - /// @param path Path to create. - static bool createPath(const std::string &path); - /// @brief Extracts path of filename with leading slash - static std::string extractPathFromFilename(const std::string &fullPath, - const char *seperator = base::consts::kFilePathSeperator); - /// @brief builds stripped filename and puts it in buff - static void buildStrippedFilename(const char *filename, char buff[], const std::string &commonPrefix = NULL, - std::size_t limit = base::consts::kSourceFilenameMaxLength); - /// @brief builds base filename and puts it in buff - static void buildBaseFilename(const std::string &fullPath, char buff[], - std::size_t limit = base::consts::kSourceFilenameMaxLength, - const char *seperator = base::consts::kFilePathSeperator); -}; -/// @brief String utilities helper class used internally. You should not use it. -class Str : base::StaticClass -{ - public: - /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. - static inline bool isDigit(char c) - { - return c >= '0' && c <= '9'; - } - - /// @brief Matches wildcards, '*' and '?' only supported. - static bool wildCardMatch(const char *str, const char *pattern); - - static std::string <rim(std::string &str); - static std::string &rtrim(std::string &str); - static std::string &trim(std::string &str); - - /// @brief Determines whether or not str starts with specified string - /// @param str String to check - /// @param start String to check against - /// @return Returns true if starts with specified string, false otherwise - static bool startsWith(const std::string &str, const std::string &start); - - /// @brief Determines whether or not str ends with specified string - /// @param str String to check - /// @param end String to check against - /// @return Returns true if ends with specified string, false otherwise - static bool endsWith(const std::string &str, const std::string &end); - - /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. - /// @param [in,out] str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified version of str - static std::string &replaceAll(std::string &str, char replaceWhat, char replaceWith); - - /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place - /// @param str String to replace from - /// @param replaceWhat Character to replace - /// @param replaceWith Character to replace with - /// @return Modified (original) str - static std::string &replaceAll(std::string &str, const std::string &replaceWhat, - const std::string &replaceWith); - - static void replaceFirstWithEscape(base::type::string_t &str, const base::type::string_t &replaceWhat, - const base::type::string_t &replaceWith); -#if defined(ELPP_UNICODE) - static void replaceFirstWithEscape(base::type::string_t &str, const base::type::string_t &replaceWhat, - const std::string &replaceWith); -#endif // defined(ELPP_UNICODE) - /// @brief Converts string to uppercase - /// @param str String to convert - /// @return Uppercase string - static std::string &toUpper(std::string &str); - - /// @brief Compares cstring equality - uses strcmp - static bool cStringEq(const char *s1, const char *s2); - - /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) - /// Dont use strcasecmp because of CRT (VC++) - static bool cStringCaseEq(const char *s1, const char *s2); - - /// @brief Returns true if c exist in str - static bool contains(const char *str, char c); - - static char *convertAndAddToBuff(std::size_t n, int len, char *buf, const char *bufLim, bool zeroPadded = true); - static char *addToBuff(const char *str, char *buf, const char *bufLim); - static char *clearBuff(char buff[], std::size_t lim); - - /// @brief Converst wchar* to char* - /// NOTE: Need to free return value after use! - static char *wcharPtrToCharPtr(const wchar_t *line); -}; -/// @brief Operating System helper static class used internally. You should not use it. -class OS : base::StaticClass -{ - public: -#if ELPP_OS_WINDOWS - /// @brief Gets environment variables for Windows based OS. - /// We are not using getenv(const char*) because of CRT deprecation - /// @param varname Variable name to get environment variable value for - /// @return If variable exist the value of it otherwise nullptr - static const char *getWindowsEnvironmentVariable(const char *varname); -#endif // ELPP_OS_WINDOWS -#if ELPP_OS_ANDROID - /// @brief Reads android property value - static std::string getProperty(const char *prop); - - /// @brief Reads android device name - static std::string getDeviceName(void); -#endif // ELPP_OS_ANDROID - - /// @brief Runs command on terminal and returns the output. - /// - /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. - /// @param command Bash command - /// @return Result of bash output or empty string if no result found. - static const std::string getBashOutput(const char *command); - - /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) - /// @param variableName Environment variable name - /// @param defaultVal If no environment variable or value found the value to return by default - /// @param alternativeBashCommand If environment variable not found what would be alternative bash command - /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' - static std::string getEnvironmentVariable(const char *variableName, const char *defaultVal, - const char *alternativeBashCommand = nullptr); - /// @brief Gets current username. - static std::string currentUser(void); - - /// @brief Gets current host name or computer name. - /// - /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen - static std::string currentHost(void); - /// @brief Whether or not terminal supports colors - static bool termSupportsColor(void); -}; -/// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str -class DateTime : base::StaticClass -{ - public: - /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current microsecond. - /// - /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided - /// @param [in,out] tv Pointer that gets updated - static void gettimeofday(struct timeval *tv); - - /// @brief Gets current date and time with a subsecond part. - /// @param format User provided date/time format - /// @param ssPrec A pointer to base::SubsecondPrecision from configuration (non-null) - /// @returns string based date time in specified format. - static std::string getDateTime(const char *format, const base::SubsecondPrecision *ssPrec); - - /// @brief Converts timeval (struct from ctime) to string using specified format and subsecond precision - static std::string timevalToString(struct timeval tval, const char *format, - const el::base::SubsecondPrecision *ssPrec); - - /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc - static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit); - - /// @brief Gets time difference in milli/micro second depending on timestampUnit - static unsigned long long getTimeDifference(const struct timeval &endTime, const struct timeval &startTime, - base::TimestampUnit timestampUnit); - - private: - static struct ::tm *buildTimeInfo(struct timeval *currTime, struct ::tm *timeInfo); - static char *parseFormat(char *buf, std::size_t bufSz, const char *format, const struct tm *tInfo, - std::size_t msec, const base::SubsecondPrecision *ssPrec); -}; -/// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) -class CommandLineArgs -{ - public: - CommandLineArgs(void) - { - setArgs(0, static_cast(nullptr)); - } - CommandLineArgs(int argc, const char **argv) - { - setArgs(argc, argv); - } - CommandLineArgs(int argc, char **argv) - { - setArgs(argc, argv); - } - virtual ~CommandLineArgs(void) {} - /// @brief Sets arguments and parses them - inline void setArgs(int argc, const char **argv) - { - setArgs(argc, const_cast(argv)); - } - /// @brief Sets arguments and parses them - void setArgs(int argc, char **argv); - /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') - bool hasParamWithValue(const char *paramKey) const; - /// @brief Returns value of arguments - /// @see hasParamWithValue(const char*) - const char *getParamValue(const char *paramKey) const; - /// @brief Return true if arguments has a param (not having a value) i,e without '=' - bool hasParam(const char *paramKey) const; - /// @brief Returns true if no params available. This exclude argv[0] - bool empty(void) const; - /// @brief Returns total number of arguments. This exclude argv[0] - std::size_t size(void) const; - friend base::type::ostream_t &operator<<(base::type::ostream_t &os, const CommandLineArgs &c); - - private: - int m_argc; - char **m_argv; - std::map m_paramsWithValue; - std::vector m_params; -}; -/// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. -/// -/// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement -/// unregisterAll() and deepCopy(const AbstractRegistry&) and write registerNew() method according to container -/// and few more methods; get() to find element, unregister() to unregister single entry. -/// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. -template -class AbstractRegistry : public base::threading::ThreadSafe -{ - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - - /// @brief Default constructor - AbstractRegistry(void) {} - - /// @brief Move constructor that is useful for base classes - AbstractRegistry(AbstractRegistry &&sr) - { - if(this == &sr) - { - return; - } - unregisterAll(); - m_list = std::move(sr.m_list); - } - - bool operator==(const AbstractRegistry &other) - { - if(size() != other.size()) - { - return false; - } - for(std::size_t i = 0; i < m_list.size(); ++i) - { - if(m_list.at(i) != other.m_list.at(i)) - { - return false; - } - } - return true; - } - - bool operator!=(const AbstractRegistry &other) - { - if(size() != other.size()) - { - return true; - } - for(std::size_t i = 0; i < m_list.size(); ++i) - { - if(m_list.at(i) != other.m_list.at(i)) - { - return true; - } - } - return false; - } - - /// @brief Assignment move operator - AbstractRegistry &operator=(AbstractRegistry &&sr) - { - if(this == &sr) - { - return *this; - } - unregisterAll(); - m_list = std::move(sr.m_list); - return *this; - } - - virtual ~AbstractRegistry(void) - { - } - - /// @return Iterator pointer from start of repository - virtual inline iterator begin(void) ELPP_FINAL - { - return m_list.begin(); - } - - /// @return Iterator pointer from end of repository - virtual inline iterator end(void) ELPP_FINAL - { - return m_list.end(); - } - - /// @return Constant iterator pointer from start of repository - virtual inline const_iterator cbegin(void) const ELPP_FINAL - { - return m_list.cbegin(); - } - - /// @return End of repository - virtual inline const_iterator cend(void) const ELPP_FINAL - { - return m_list.cend(); - } - - /// @return Whether or not repository is empty - virtual inline bool empty(void) const ELPP_FINAL - { - return m_list.empty(); - } - - /// @return Size of repository - virtual inline std::size_t size(void) const ELPP_FINAL - { - return m_list.size(); - } - - /// @brief Returns underlying container by reference - virtual inline Container &list(void) ELPP_FINAL - { - return m_list; - } - - /// @brief Returns underlying container by constant reference. - virtual inline const Container &list(void) const ELPP_FINAL - { - return m_list; - } - - /// @brief Unregisters all the pointers from current repository. - virtual void unregisterAll(void) = 0; - - protected: - virtual void deepCopy(const AbstractRegistry &) = 0; - void reinitDeepCopy(const AbstractRegistry &sr) - { - unregisterAll(); - deepCopy(sr); - } - - private: - Container m_list; -}; - -/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) -/// -/// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) -/// of AbstractRegistry. Any implementation of this class should be -/// explicitly (by using lock functions) -template -class Registry : public AbstractRegistry> -{ - public: - typedef typename Registry::iterator iterator; - typedef typename Registry::const_iterator const_iterator; - - Registry(void) {} - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - Registry(const Registry &sr) : AbstractRegistry>() - { - if(this == &sr) - { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - Registry &operator=(const Registry &sr) - { - if(this == &sr) - { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - virtual ~Registry(void) - { - unregisterAll(); - } - - protected: - virtual void unregisterAll(void) ELPP_FINAL - { - if(!this->empty()) - { - for(auto &&curr : this->list()) - { - base::utils::safeDelete(curr.second); - } - this->list().clear(); - } - } - - /// @brief Registers new registry to repository. - virtual void registerNew(const T_Key &uniqKey, T_Ptr *ptr) ELPP_FINAL - { - unregister(uniqKey); - this->list().insert(std::make_pair(uniqKey, ptr)); - } - - /// @brief Unregisters single entry mapped to specified unique key - void unregister(const T_Key &uniqKey) - { - T_Ptr *existing = get(uniqKey); - if(existing != nullptr) - { - base::utils::safeDelete(existing); - this->list().erase(uniqKey); - } - } - - /// @brief Gets pointer from repository. If none found, nullptr is returned. - T_Ptr *get(const T_Key &uniqKey) - { - iterator it = this->list().find(uniqKey); - return it == this->list().end() - ? nullptr - : it->second; - } - - private: - virtual void deepCopy(const AbstractRegistry> &sr) ELPP_FINAL - { - for(const_iterator it = sr.cbegin(); it != sr.cend(); ++it) - { - registerNew(it->first, new T_Ptr(*it->second)); - } - } -}; - -/// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) -/// -/// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry. Any implementation of this class -/// should be made thread-safe explicitly -template -class RegistryWithPred : public AbstractRegistry> -{ - public: - typedef typename RegistryWithPred::iterator iterator; - typedef typename RegistryWithPred::const_iterator const_iterator; - - RegistryWithPred(void) - { - } - - virtual ~RegistryWithPred(void) - { - unregisterAll(); - } - - /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. - RegistryWithPred(const RegistryWithPred &sr) : AbstractRegistry>() - { - if(this == &sr) - { - return; - } - this->reinitDeepCopy(sr); - } - - /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element - /// @see unregisterAll() - /// @see deepCopy(const AbstractRegistry&) - RegistryWithPred &operator=(const RegistryWithPred &sr) - { - if(this == &sr) - { - return *this; - } - this->reinitDeepCopy(sr); - return *this; - } - - friend base::type::ostream_t &operator<<(base::type::ostream_t &os, const RegistryWithPred &sr) - { - for(const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) - { - os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); - } - return os; - } - - protected: - virtual void unregisterAll(void) ELPP_FINAL - { - if(!this->empty()) - { - for(auto &&curr : this->list()) - { - base::utils::safeDelete(curr); - } - this->list().clear(); - } - } - - virtual void unregister(T_Ptr *&ptr) ELPP_FINAL - { - if(ptr) - { - iterator iter = this->begin(); - for(; iter != this->end(); ++iter) - { - if(ptr == *iter) - { - break; - } - } - if(iter != this->end() && *iter != nullptr) - { - this->list().erase(iter); - base::utils::safeDelete(*iter); - } - } - } - - virtual inline void registerNew(T_Ptr *ptr) ELPP_FINAL - { - this->list().push_back(ptr); - } - - /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate - /// in order to validate pointer. - template - T_Ptr *get(const T &arg1, const T2 arg2) - { - iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); - if(iter != this->list().end() && *iter != nullptr) - { - return *iter; - } - return nullptr; - } - - private: - virtual void deepCopy(const AbstractRegistry> &sr) - { - for(const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) - { - registerNew(new T_Ptr(**it)); - } - } -}; -class Utils -{ - public: - template - static bool installCallback(const std::string &id, std::map *mapT) - { - if(mapT->find(id) == mapT->end()) - { - mapT->insert(std::make_pair(id, TPtr(new T()))); - return true; - } - return false; - } - - template - static void uninstallCallback(const std::string &id, std::map *mapT) - { - if(mapT->find(id) != mapT->end()) - { - mapT->erase(id); - } - } - - template - static T *callback(const std::string &id, std::map *mapT) - { - typename std::map::iterator iter = mapT->find(id); - if(iter != mapT->end()) - { - return static_cast(iter->second.get()); - } - return nullptr; - } -}; -} // namespace utils -} // namespace base -/// @brief Base of Easylogging++ friendly class -/// -/// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` -class Loggable -{ - public: - virtual ~Loggable(void) {} - virtual void log(el::base::type::ostream_t &) const = 0; - - private: - friend inline el::base::type::ostream_t &operator<<(el::base::type::ostream_t &os, const Loggable &loggable) - { - loggable.log(os); - return os; - } -}; -namespace base -{ -/// @brief Represents log format containing flags and date format. This is used internally to start initial log -class LogFormat : public Loggable -{ - public: - LogFormat(void); - LogFormat(Level level, const base::type::string_t &format); - LogFormat(const LogFormat &logFormat); - LogFormat(LogFormat &&logFormat); - LogFormat &operator=(const LogFormat &logFormat); - virtual ~LogFormat(void) {} - bool operator==(const LogFormat &other); - - /// @brief Updates format to be used while logging. - /// @param userFormat User provided format - void parseFromFormat(const base::type::string_t &userFormat); - - inline Level level(void) const - { - return m_level; - } - - inline const base::type::string_t &userFormat(void) const - { - return m_userFormat; - } - - inline const base::type::string_t &format(void) const - { - return m_format; - } - - inline const std::string &dateTimeFormat(void) const - { - return m_dateTimeFormat; - } - - inline base::type::EnumType flags(void) const - { - return m_flags; - } - - inline bool hasFlag(base::FormatFlags flag) const - { - return base::utils::hasFlag(flag, m_flags); - } - - virtual void log(el::base::type::ostream_t &os) const - { - os << m_format; - } - - protected: - /// @brief Updates date time format if available in currFormat. - /// @param index Index where %datetime, %date or %time was found - /// @param [in,out] currFormat current format that is being used to format - virtual void updateDateFormat(std::size_t index, base::type::string_t &currFormat) ELPP_FINAL; - - /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level - virtual void updateFormatSpec(void) ELPP_FINAL; - - inline void addFlag(base::FormatFlags flag) - { - base::utils::addFlag(flag, &m_flags); - } - - private: - Level m_level; - base::type::string_t m_userFormat; - base::type::string_t m_format; - std::string m_dateTimeFormat; - base::type::EnumType m_flags; - std::string m_currentUser; - std::string m_currentHost; - friend class el::Logger; // To resolve loggerId format specifier easily -}; -} // namespace base -/// @brief Resolving function for format specifier -typedef std::function FormatSpecifierValueResolver; -/// @brief User-provided custom format specifier -/// @see el::Helpers::installCustomFormatSpecifier -/// @see FormatSpecifierValueResolver -class CustomFormatSpecifier -{ - public: - CustomFormatSpecifier(const char *formatSpecifier, const FormatSpecifierValueResolver &resolver) : m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} - inline const char *formatSpecifier(void) const - { - return m_formatSpecifier; - } - inline const FormatSpecifierValueResolver &resolver(void) const - { - return m_resolver; - } - inline bool operator==(const char *formatSpecifier) - { - return strcmp(m_formatSpecifier, formatSpecifier) == 0; - } - - private: - const char *m_formatSpecifier; - FormatSpecifierValueResolver m_resolver; -}; -/// @brief Represents single configuration that has representing level, configuration type and a string based value. -/// -/// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes -/// and will be parsed later. -/// -/// Consider some examples below: -/// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); -/// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); -/// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); -class Configuration : public Loggable -{ - public: - Configuration(const Configuration &c); - Configuration &operator=(const Configuration &c); - - virtual ~Configuration(void) - { - } - - /// @brief Full constructor used to sets value of configuration - Configuration(Level level, ConfigurationType configurationType, const std::string &value); - - /// @brief Gets level of current configuration - inline Level level(void) const - { - return m_level; - } - - /// @brief Gets configuration type of current configuration - inline ConfigurationType configurationType(void) const - { - return m_configurationType; - } - - /// @brief Gets string based configuration value - inline const std::string &value(void) const - { - return m_value; - } - - /// @brief Set string based configuration value - /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values - /// use them in quotes. They will be parsed when configuring - inline void setValue(const std::string &value) - { - m_value = value; - } - - virtual void log(el::base::type::ostream_t &os) const; - - /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. - class Predicate - { - public: - Predicate(Level level, ConfigurationType configurationType); - - bool operator()(const Configuration *conf) const; - - private: - Level m_level; - ConfigurationType m_configurationType; - }; - - private: - Level m_level; - ConfigurationType m_configurationType; - std::string m_value; -}; - -/// @brief Thread-safe Configuration repository -/// -/// @detail This repository represents configurations for all the levels and configuration type mapped to a value. -class Configurations : public base::utils::RegistryWithPred -{ - public: - /// @brief Default constructor with empty repository - Configurations(void); - - /// @brief Constructor used to set configurations using configuration file. - /// @param configurationFile Full path to configuration file - /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. - /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. - /// @see parseFromFile(const std::string&, Configurations* base) - /// @see setRemainingToDefault() - Configurations(const std::string &configurationFile, bool useDefaultsForRemaining = true, - Configurations *base = nullptr); - - virtual ~Configurations(void) - { - } - - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - bool parseFromFile(const std::string &configurationFile, Configurations *base = nullptr); - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you - /// do not proceed without successful parse. - bool parseFromText(const std::string &configurationsString, Configurations *base = nullptr); - - /// @brief Sets configuration based-off an existing configurations. - /// @param base Pointer to existing configurations. - void setFromBase(Configurations *base); - - /// @brief Determines whether or not specified configuration type exists in the repository. - /// - /// @detail Returns as soon as first level is found. - /// @param configurationType Type of configuration to check existence for. - bool hasConfiguration(ConfigurationType configurationType); - - /// @brief Determines whether or not specified configuration type exists for specified level - /// @param level Level to check - /// @param configurationType Type of configuration to check existence for. - bool hasConfiguration(Level level, ConfigurationType configurationType); - - /// @brief Sets value of configuration for specified level. - /// - /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types - /// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not set for - /// Level::Global because these configurations are not dependant on level. - /// @param level Level to set configuration for (el::Level). - /// @param configurationType Type of configuration (el::ConfigurationType) - /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string - /// from users' point of view. This is then parsed later to be used internally. - /// @see Configuration::setValue(const std::string& value) - /// @see el::Level - /// @see el::ConfigurationType - void set(Level level, ConfigurationType configurationType, const std::string &value); - - /// @brief Sets single configuration based on other single configuration. - /// @see set(Level level, ConfigurationType configurationType, const std::string& value) - void set(Configuration *conf); - - inline Configuration *get(Level level, ConfigurationType configurationType) - { - base::threading::ScopedLock scopedLock(lock()); - return RegistryWithPred::get(level, configurationType); - } - - /// @brief Sets configuration for all levels. - /// @param configurationType Type of configuration - /// @param value String based value - /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) - inline void setGlobally(ConfigurationType configurationType, const std::string &value) - { - setGlobally(configurationType, value, false); - } - - /// @brief Clears repository so that all the configurations are unset - inline void clear(void) - { - base::threading::ScopedLock scopedLock(lock()); - unregisterAll(); - } - - /// @brief Gets configuration file used in parsing this configurations. - /// - /// @detail If this repository was set manually or by text this returns empty string. - inline const std::string &configurationFile(void) const - { - return m_configurationFile; - } - - /// @brief Sets configurations to "factory based" configurations. - void setToDefault(void); - - /// @brief Lets you set the remaining configurations to default. - /// - /// @detail By remaining, it means that the level/type a configuration does not exist for. - /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets - /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, - /// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor - /// and try to access a value, an error is thrown - void setRemainingToDefault(void); - - /// @brief Parser used internally to parse configurations from file or text. - /// - /// @detail This class makes use of base::utils::Str. - /// You should not need this unless you are working on some tool for Easylogging++ - class Parser : base::StaticClass - { - public: - /// @brief Parses configuration from file. - /// @param configurationFile Full path to configuration file - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration file. - /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse. - static bool parseFromFile(const std::string &configurationFile, Configurations *sender, - Configurations *base = nullptr); - - /// @brief Parse configurations from configuration string. - /// - /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary - /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you - /// do not proceed without successful parse (This is recommended) - /// @param configurationsString the configuration in plain text format - /// @param sender Sender configurations pointer. Usually 'this' is used from calling class - /// @param base Configurations to base new configuration repository off. This value is used when you want to use - /// existing Configurations to base all the values and then set rest of configuration via configuration text. - /// @return True if successfully parsed, false otherwise. - static bool parseFromText(const std::string &configurationsString, Configurations *sender, - Configurations *base = nullptr); - - private: - friend class el::Loggers; - static void ignoreComments(std::string *line); - static bool isLevel(const std::string &line); - static bool isComment(const std::string &line); - static inline bool isConfig(const std::string &line); - static bool parseLine(std::string *line, std::string *currConfigStr, std::string *currLevelStr, Level *currLevel, - Configurations *conf); - }; - - private: - std::string m_configurationFile; - bool m_isFromFile; - friend class el::Loggers; - - /// @brief Unsafely sets configuration if does not already exist - void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string &value); - - /// @brief Thread unsafe set - void unsafeSet(Level level, ConfigurationType configurationType, const std::string &value); - - /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void setGlobally(ConfigurationType configurationType, const std::string &value, bool includeGlobalLevel); - - /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true - /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) - void unsafeSetGlobally(ConfigurationType configurationType, const std::string &value, bool includeGlobalLevel); -}; - -namespace base -{ -typedef std::shared_ptr FileStreamPtr; -typedef std::map LogStreamsReferenceMap; -/// @brief Configurations with data types. -/// -/// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. -/// This is to perform faster while writing logs using correct configurations. -/// -/// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) -class TypedConfigurations : public base::threading::ThreadSafe -{ - public: - /// @brief Constructor to initialize (construct) the object off el::Configurations - /// @param configurations Configurations pointer/reference to base this typed configurations off. - /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() - TypedConfigurations(Configurations *configurations, base::LogStreamsReferenceMap *logStreamsReference); - - TypedConfigurations(const TypedConfigurations &other); - - virtual ~TypedConfigurations(void) - { - } - - const Configurations *configurations(void) const - { - return m_configurations; - } - - bool enabled(Level level); - bool toFile(Level level); - const std::string &filename(Level level); - bool toStandardOutput(Level level); - const base::LogFormat &logFormat(Level level); - const base::SubsecondPrecision &subsecondPrecision(Level level = Level::Global); - const base::MillisecondsWidth &millisecondsWidth(Level level = Level::Global); - bool performanceTracking(Level level = Level::Global); - base::type::fstream_t *fileStream(Level level); - std::size_t maxLogFileSize(Level level); - std::size_t logFlushThreshold(Level level); - - private: - Configurations *m_configurations; - std::map m_enabledMap; - std::map m_toFileMap; - std::map m_filenameMap; - std::map m_toStandardOutputMap; - std::map m_logFormatMap; - std::map m_subsecondPrecisionMap; - std::map m_performanceTrackingMap; - std::map m_fileStreamMap; - std::map m_maxLogFileSizeMap; - std::map m_logFlushThresholdMap; - base::LogStreamsReferenceMap *m_logStreamsReference; - - friend class el::Helpers; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::LogDispatcher; - - template - inline Conf_T getConfigByVal(Level level, const std::map *confMap, const char *confName) - { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - inline Conf_T &getConfigByRef(Level level, std::map *confMap, const char *confName) - { - base::threading::ScopedLock scopedLock(lock()); - return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope - } - - template - Conf_T unsafeGetConfigByVal(Level level, const std::map *confMap, const char *confName) - { - ELPP_UNUSED(confName); - typename std::map::const_iterator it = confMap->find(level); - if(it == confMap->end()) - { - try - { - return confMap->at(Level::Global); - } - catch(...) - { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl - << "Please ensure you have properly configured logger.", - false); - return Conf_T(); - } - } - return it->second; - } - - template - Conf_T &unsafeGetConfigByRef(Level level, std::map *confMap, const char *confName) - { - ELPP_UNUSED(confName); - typename std::map::iterator it = confMap->find(level); - if(it == confMap->end()) - { - try - { - return confMap->at(Level::Global); - } - catch(...) - { - ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" - << LevelHelper::convertToString(level) << "]" - << std::endl - << "Please ensure you have properly configured logger.", - false); - } - } - return it->second; - } - - template - void setValue(Level level, const Conf_T &value, std::map *confMap, bool includeGlobalLevel = true) - { - // If map is empty and we are allowed to add into generic level (Level::Global), do it! - if(confMap->empty() && includeGlobalLevel) - { - confMap->insert(std::make_pair(Level::Global, value)); - return; - } - // If same value exist in generic level already, dont add it to explicit level - typename std::map::iterator it = confMap->find(Level::Global); - if(it != confMap->end() && it->second == value) - { - return; - } - // Now make sure we dont double up values if we really need to add it to explicit level - it = confMap->find(level); - if(it == confMap->end()) - { - // Value not found for level, add new - confMap->insert(std::make_pair(level, value)); - } - else - { - // Value found, just update value - confMap->at(level) = value; - } - } - - void build(Configurations *configurations); - unsigned long getULong(std::string confVal); - std::string resolveFilename(const std::string &filename); - void insertFile(Level level, const std::string &fullFilename); - bool unsafeValidateFileRolling(Level level, const PreRollOutCallback &preRollOutCallback); - - inline bool validateFileRolling(Level level, const PreRollOutCallback &preRollOutCallback) - { - base::threading::ScopedLock scopedLock(lock()); - return unsafeValidateFileRolling(level, preRollOutCallback); - } -}; -/// @brief Class that keeps record of current line hit for occasional logging -class HitCounter -{ - public: - HitCounter(void) : m_filename(""), - m_lineNumber(0), - m_hitCounts(0) - { - } - - HitCounter(const char *filename, base::type::LineNumber lineNumber) : m_filename(filename), - m_lineNumber(lineNumber), - m_hitCounts(0) - { - } - - HitCounter(const HitCounter &hitCounter) : m_filename(hitCounter.m_filename), - m_lineNumber(hitCounter.m_lineNumber), - m_hitCounts(hitCounter.m_hitCounts) - { - } - - HitCounter &operator=(const HitCounter &hitCounter) - { - if(&hitCounter != this) - { - m_filename = hitCounter.m_filename; - m_lineNumber = hitCounter.m_lineNumber; - m_hitCounts = hitCounter.m_hitCounts; - } - return *this; - } - - virtual ~HitCounter(void) - { - } - - /// @brief Resets location of current hit counter - inline void resetLocation(const char *filename, base::type::LineNumber lineNumber) - { - m_filename = filename; - m_lineNumber = lineNumber; - } - - /// @brief Validates hit counts and resets it if necessary - inline void validateHitCounts(std::size_t n) - { - if(m_hitCounts >= base::consts::kMaxLogPerCounter) - { - m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); - } - ++m_hitCounts; - } - - inline const char *filename(void) const - { - return m_filename; - } - - inline base::type::LineNumber lineNumber(void) const - { - return m_lineNumber; - } - - inline std::size_t hitCounts(void) const - { - return m_hitCounts; - } - - inline void increment(void) - { - ++m_hitCounts; - } - - class Predicate - { - public: - Predicate(const char *filename, base::type::LineNumber lineNumber) - : m_filename(filename), - m_lineNumber(lineNumber) - { - } - inline bool operator()(const HitCounter *counter) - { - return ((counter != nullptr) && - (strcmp(counter->m_filename, m_filename) == 0) && - (counter->m_lineNumber == m_lineNumber)); - } - - private: - const char *m_filename; - base::type::LineNumber m_lineNumber; - }; - - private: - const char *m_filename; - base::type::LineNumber m_lineNumber; - std::size_t m_hitCounts; -}; -/// @brief Repository for hit counters used across the application -class RegisteredHitCounters : public base::utils::RegistryWithPred -{ - public: - /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateEveryN(const char *filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateAfterN(const char *filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one - /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned - bool validateNTimes(const char *filename, base::type::LineNumber lineNumber, std::size_t n); - - /// @brief Gets hit counter registered at specified position - inline const base::HitCounter *getCounter(const char *filename, base::type::LineNumber lineNumber) - { - base::threading::ScopedLock scopedLock(lock()); - return get(filename, lineNumber); - } -}; -/// @brief Action to be taken for dispatching -enum class DispatchAction : base::type::EnumType -{ - None = 1, - NormalLog = 2, - SysLog = 4, - FileOnlyLog = 8, -}; -} // namespace base -template -class Callback : protected base::threading::ThreadSafe -{ - public: - Callback(void) : m_enabled(true) {} - inline bool enabled(void) const - { - return m_enabled; - } - inline void setEnabled(bool enabled) - { - base::threading::ScopedLock scopedLock(lock()); - m_enabled = enabled; - } - - protected: - virtual void handle(const T *handlePtr) = 0; - - private: - bool m_enabled; -}; -class LogDispatchData -{ - public: - LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} - inline const LogMessage *logMessage(void) const - { - return m_logMessage; - } - inline base::DispatchAction dispatchAction(void) const - { - return m_dispatchAction; - } - - private: - LogMessage *m_logMessage; - base::DispatchAction m_dispatchAction; - friend class base::LogDispatcher; - - inline void setLogMessage(LogMessage *logMessage) - { - m_logMessage = logMessage; - } - inline void setDispatchAction(base::DispatchAction dispatchAction) - { - m_dispatchAction = dispatchAction; - } -}; -class LogDispatchCallback : public Callback -{ - private: - friend class base::LogDispatcher; -}; -class PerformanceTrackingCallback : public Callback -{ - private: - friend class base::PerformanceTracker; -}; -class LoggerRegistrationCallback : public Callback -{ - private: - friend class base::RegisteredLoggers; -}; -class LogBuilder : base::NoCopy -{ - public: - LogBuilder() : m_termSupportsColor(base::utils::OS::termSupportsColor()) {} - virtual ~LogBuilder(void) - { - ELPP_INTERNAL_INFO(3, "Destroying log builder...") - } - virtual base::type::string_t build(const LogMessage *logMessage, bool appendNewLine) const = 0; - void convertToColoredOutput(base::type::string_t *logLine, Level level); - - private: - bool m_termSupportsColor; - friend class el::base::DefaultLogDispatchCallback; -}; -typedef std::shared_ptr LogBuilderPtr; -/// @brief Represents a logger holding ID and configurations we need to write logs -/// -/// @detail This class does not write logs itself instead its used by writer to read configuations from. -class Logger : public base::threading::ThreadSafe, public Loggable -{ - public: - Logger(const std::string &id, base::LogStreamsReferenceMap *logStreamsReference); - Logger(const std::string &id, const Configurations &configurations, base::LogStreamsReferenceMap *logStreamsReference); - Logger(const Logger &logger); - Logger &operator=(const Logger &logger); - - virtual ~Logger(void) - { - base::utils::safeDelete(m_typedConfigurations); - } - - virtual inline void log(el::base::type::ostream_t &os) const - { - os << m_id.c_str(); - } - - /// @brief Configures the logger using specified configurations. - void configure(const Configurations &configurations); - - /// @brief Reconfigures logger using existing configurations - void reconfigure(void); - - inline const std::string &id(void) const - { - return m_id; - } - - inline const std::string &parentApplicationName(void) const - { - return m_parentApplicationName; - } - - inline void setParentApplicationName(const std::string &parentApplicationName) - { - m_parentApplicationName = parentApplicationName; - } - - inline Configurations *configurations(void) - { - return &m_configurations; - } - - inline base::TypedConfigurations *typedConfigurations(void) - { - return m_typedConfigurations; - } - - static bool isValidId(const std::string &id); - - /// @brief Flushes logger to sync all log files for all levels - void flush(void); - - void flush(Level level, base::type::fstream_t *fs); - - inline bool isFlushNeeded(Level level) - { - return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); - } - - inline LogBuilder *logBuilder(void) const - { - return m_logBuilder.get(); - } - - inline void setLogBuilder(const LogBuilderPtr &logBuilder) - { - m_logBuilder = logBuilder; - } - - inline bool enabled(Level level) const - { - return m_typedConfigurations->enabled(level); - } - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -#define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME) \ - template \ - inline void FUNCTION_NAME(const char *, const T &, const Args &...); \ - template \ - inline void FUNCTION_NAME(const T &); - - template - inline void verbose(int, const char *, const T &, const Args &...); - - template - inline void verbose(int, const T &); - - LOGGER_LEVEL_WRITERS_SIGNATURES(info) - LOGGER_LEVEL_WRITERS_SIGNATURES(debug) - LOGGER_LEVEL_WRITERS_SIGNATURES(warn) - LOGGER_LEVEL_WRITERS_SIGNATURES(error) - LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) - LOGGER_LEVEL_WRITERS_SIGNATURES(trace) -#undef LOGGER_LEVEL_WRITERS_SIGNATURES -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - private: - std::string m_id; - base::TypedConfigurations *m_typedConfigurations; - base::type::stringstream_t m_stream; - std::string m_parentApplicationName; - bool m_isConfigured; - Configurations m_configurations; - std::map m_unflushedCount; - base::LogStreamsReferenceMap *m_logStreamsReference; - LogBuilderPtr m_logBuilder; - - friend class el::LogMessage; - friend class el::Loggers; - friend class el::Helpers; - friend class el::base::RegisteredLoggers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PErrorWriter; - friend class el::base::Storage; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - Logger(void); - -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED - template - void log_(Level, int, const char *, const T &, const Args &...); - - template - inline void log_(Level, int, const T &); - - template - void log(Level, const char *, const T &, const Args &...); - - template - inline void log(Level, const T &); -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED - - void initUnflushedCount(void); - - inline base::type::stringstream_t &stream(void) - { - return m_stream; - } - - void resolveLoggerFormatSpec(void) const; -}; -namespace base -{ -/// @brief Loggers repository -class RegisteredLoggers : public base::utils::Registry -{ - public: - explicit RegisteredLoggers(const LogBuilderPtr &defaultLogBuilder); - - virtual ~RegisteredLoggers(void) - { - unsafeFlushAll(); - } - - inline void setDefaultConfigurations(const Configurations &configurations) - { - base::threading::ScopedLock scopedLock(lock()); - m_defaultConfigurations.setFromBase(const_cast(&configurations)); - } - - inline Configurations *defaultConfigurations(void) - { - return &m_defaultConfigurations; - } - - Logger *get(const std::string &id, bool forceCreation = true); - - template - inline bool installLoggerRegistrationCallback(const std::string &id) - { - return base::utils::Utils::installCallback(id, - &m_loggerRegistrationCallbacks); - } - - template - inline void uninstallLoggerRegistrationCallback(const std::string &id) - { - base::utils::Utils::uninstallCallback(id, &m_loggerRegistrationCallbacks); - } - - template - inline T *loggerRegistrationCallback(const std::string &id) - { - return base::utils::Utils::callback(id, &m_loggerRegistrationCallbacks); - } - - bool remove(const std::string &id); - - inline bool has(const std::string &id) - { - return get(id, false) != nullptr; - } - - inline void unregister(Logger *&logger) - { - base::threading::ScopedLock scopedLock(lock()); - base::utils::Registry::unregister(logger->id()); - } - - inline base::LogStreamsReferenceMap *logStreamsReference(void) - { - return &m_logStreamsReference; - } - - inline void flushAll(void) - { - base::threading::ScopedLock scopedLock(lock()); - unsafeFlushAll(); - } - - inline void setDefaultLogBuilder(LogBuilderPtr &logBuilderPtr) - { - base::threading::ScopedLock scopedLock(lock()); - m_defaultLogBuilder = logBuilderPtr; - } - - private: - LogBuilderPtr m_defaultLogBuilder; - Configurations m_defaultConfigurations; - base::LogStreamsReferenceMap m_logStreamsReference; - std::map m_loggerRegistrationCallbacks; - friend class el::base::Storage; - - void unsafeFlushAll(void); -}; -/// @brief Represents registries for verbose logging -class VRegistry : base::NoCopy, public base::threading::ThreadSafe -{ - public: - explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType *pFlags); - - /// @brief Sets verbose level. Accepted range is 0-9 - void setLevel(base::type::VerboseLevel level); - - inline base::type::VerboseLevel level(void) const - { - return m_level; - } - - inline void clearCategories(void) - { - base::threading::ScopedLock scopedLock(lock()); - m_categories.clear(); - } - - inline void clearModules(void) - { - base::threading::ScopedLock scopedLock(lock()); - m_modules.clear(); - } - - void setCategories(const char *categories, bool clear = true); - - std::string getCategories(); - - void setModules(const char *modules); - - bool allowed(Level level, const char *category); - - bool allowed(base::type::VerboseLevel vlevel, const char *file); - - inline const std::map &modules(void) const - { - return m_modules; - } - - void setFromArgs(const base::utils::CommandLineArgs *commandLineArgs); - - /// @brief Whether or not vModules enabled - inline bool vModulesEnabled(void) - { - return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); - } - - inline void setFilenameCommonPrefix(const std::string &prefix) - { - m_filenameCommonPrefix = prefix; - } - - inline const std::string &getFilenameCommonPrefix() const - { - return m_filenameCommonPrefix; - } - - private: - base::type::VerboseLevel m_level; - base::type::EnumType *m_pFlags; - std::map m_modules; - std::deque> m_categories; - std::string m_categoriesString; - std::string m_filenameCommonPrefix; -}; -} // namespace base -class LogMessage -{ - public: - LogMessage(Level level, const std::string &file, base::type::LineNumber line, const std::string &func, - base::type::VerboseLevel verboseLevel, Logger *logger) : m_level(level), m_file(file), m_line(line), m_func(func), - m_verboseLevel(verboseLevel), m_logger(logger), m_message(logger->stream().str()) - { - } - inline Level level(void) const - { - return m_level; - } - inline const std::string &file(void) const - { - return m_file; - } - inline base::type::LineNumber line(void) const - { - return m_line; - } - inline const std::string &func(void) const - { - return m_func; - } - inline base::type::VerboseLevel verboseLevel(void) const - { - return m_verboseLevel; - } - inline Logger *logger(void) const - { - return m_logger; - } - inline const base::type::string_t &message(void) const - { - return m_message; - } - - private: - Level m_level; - std::string m_file; - base::type::LineNumber m_line; - std::string m_func; - base::type::VerboseLevel m_verboseLevel; - Logger *m_logger; - base::type::string_t m_message; -}; -namespace base -{ -#if ELPP_ASYNC_LOGGING -class AsyncLogItem -{ - public: - explicit AsyncLogItem(const LogMessage &logMessage, const LogDispatchData &data, const base::type::string_t &logLine) - : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} - virtual ~AsyncLogItem() {} - inline LogMessage *logMessage(void) - { - return &m_logMessage; - } - inline LogDispatchData *data(void) - { - return &m_dispatchData; - } - inline base::type::string_t logLine(void) - { - return m_logLine; - } - - private: - LogMessage m_logMessage; - LogDispatchData m_dispatchData; - base::type::string_t m_logLine; -}; -class AsyncLogQueue : public base::threading::ThreadSafe -{ - public: - virtual ~AsyncLogQueue() - { - ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); - } - - inline AsyncLogItem next(void) - { - base::threading::ScopedLock scopedLock(lock()); - AsyncLogItem result = m_queue.front(); - m_queue.pop(); - return result; - } - - inline void push(const AsyncLogItem &item) - { - base::threading::ScopedLock scopedLock(lock()); - m_queue.push(item); - } - inline void pop(void) - { - base::threading::ScopedLock scopedLock(lock()); - m_queue.pop(); - } - inline AsyncLogItem front(void) - { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.front(); - } - inline bool empty(void) - { - base::threading::ScopedLock scopedLock(lock()); - return m_queue.empty(); - } - - private: - std::queue m_queue; -}; -class IWorker -{ - public: - virtual ~IWorker() {} - virtual void start() = 0; -}; -#endif // ELPP_ASYNC_LOGGING -/// @brief Easylogging++ management storage -class Storage : base::NoCopy, public base::threading::ThreadSafe -{ - public: -#if ELPP_ASYNC_LOGGING - Storage(const LogBuilderPtr &defaultLogBuilder, base::IWorker *asyncDispatchWorker); -#else - explicit Storage(const LogBuilderPtr &defaultLogBuilder); -#endif // ELPP_ASYNC_LOGGING - - virtual ~Storage(void); - - inline bool validateEveryNCounter(const char *filename, base::type::LineNumber lineNumber, std::size_t occasion) - { - return hitCounters()->validateEveryN(filename, lineNumber, occasion); - } - - inline bool validateAfterNCounter(const char *filename, base::type::LineNumber lineNumber, std::size_t n) - { - return hitCounters()->validateAfterN(filename, lineNumber, n); - } - - inline bool validateNTimesCounter(const char *filename, base::type::LineNumber lineNumber, std::size_t n) - { - return hitCounters()->validateNTimes(filename, lineNumber, n); - } - - inline base::RegisteredHitCounters *hitCounters(void) const - { - return m_registeredHitCounters; - } - - inline base::RegisteredLoggers *registeredLoggers(void) const - { - return m_registeredLoggers; - } - - inline base::VRegistry *vRegistry(void) const - { - return m_vRegistry; - } - -#if ELPP_ASYNC_LOGGING - inline base::AsyncLogQueue *asyncLogQueue(void) const - { - return m_asyncLogQueue; - } -#endif // ELPP_ASYNC_LOGGING - - inline const base::utils::CommandLineArgs *commandLineArgs(void) const - { - return &m_commandLineArgs; - } - - inline void addFlag(LoggingFlag flag) - { - base::utils::addFlag(flag, &m_flags); - } - - inline void removeFlag(LoggingFlag flag) - { - base::utils::removeFlag(flag, &m_flags); - } - - inline bool hasFlag(LoggingFlag flag) const - { - return base::utils::hasFlag(flag, m_flags); - } - - inline base::type::EnumType flags(void) const - { - return m_flags; - } - - inline void setFlags(base::type::EnumType flags) - { - m_flags = flags; - } - - inline void setPreRollOutCallback(const PreRollOutCallback &callback) - { - m_preRollOutCallback = callback; - } - - inline void unsetPreRollOutCallback(void) - { - m_preRollOutCallback = base::defaultPreRollOutCallback; - } - - inline PreRollOutCallback &preRollOutCallback(void) - { - return m_preRollOutCallback; - } - - bool hasCustomFormatSpecifier(const char *formatSpecifier); - void installCustomFormatSpecifier(const CustomFormatSpecifier &customFormatSpecifier); - bool uninstallCustomFormatSpecifier(const char *formatSpecifier); - - const std::vector *customFormatSpecifiers(void) const - { - return &m_customFormatSpecifiers; - } - - inline void setLoggingLevel(Level level) - { - m_loggingLevel = level; - } - - template - inline bool installLogDispatchCallback(const std::string &id) - { - return base::utils::Utils::installCallback(id, &m_logDispatchCallbacks); - } - - template - inline void uninstallLogDispatchCallback(const std::string &id) - { - base::utils::Utils::uninstallCallback(id, &m_logDispatchCallbacks); - } - template - inline T *logDispatchCallback(const std::string &id) - { - return base::utils::Utils::callback(id, &m_logDispatchCallbacks); - } - -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - template - inline bool installPerformanceTrackingCallback(const std::string &id) - { - return base::utils::Utils::installCallback(id, - &m_performanceTrackingCallbacks); - } - - template - inline void uninstallPerformanceTrackingCallback(const std::string &id) - { - base::utils::Utils::uninstallCallback(id, - &m_performanceTrackingCallbacks); - } - - template - inline T *performanceTrackingCallback(const std::string &id) - { - return base::utils::Utils::callback(id, &m_performanceTrackingCallbacks); - } -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - - /// @brief Sets thread name for current thread. Requires std::thread - inline void setThreadName(const std::string &name) - { - if(name.empty()) - return; - base::threading::ScopedLock scopedLock(lock()); - m_threadNames[base::threading::getCurrentThreadId()] = name; - } - - inline std::string getThreadName(const std::string &threadId) - { - base::threading::ScopedLock scopedLock(lock()); - std::map::const_iterator it = m_threadNames.find(threadId); - if(it == m_threadNames.end()) - { - return threadId; - } - return it->second; - } - - private: - base::RegisteredHitCounters *m_registeredHitCounters; - base::RegisteredLoggers *m_registeredLoggers; - base::type::EnumType m_flags; - base::VRegistry *m_vRegistry; -#if ELPP_ASYNC_LOGGING - base::AsyncLogQueue *m_asyncLogQueue; - base::IWorker *m_asyncDispatchWorker; -#endif // ELPP_ASYNC_LOGGING - base::utils::CommandLineArgs m_commandLineArgs; - PreRollOutCallback m_preRollOutCallback; - std::map m_logDispatchCallbacks; - std::map m_performanceTrackingCallbacks; - std::map m_threadNames; - std::vector m_customFormatSpecifiers; - Level m_loggingLevel; - - friend class el::Helpers; - friend class el::base::DefaultLogDispatchCallback; - friend class el::LogBuilder; - friend class el::base::MessageBuilder; - friend class el::base::Writer; - friend class el::base::PerformanceTracker; - friend class el::base::LogDispatcher; - - void setApplicationArguments(int argc, char **argv); - - inline void setApplicationArguments(int argc, const char **argv) - { - setApplicationArguments(argc, const_cast(argv)); - } -}; -extern ELPP_EXPORT base::type::StoragePointer elStorage; -#define ELPP el::base::elStorage -class DefaultLogDispatchCallback : public LogDispatchCallback -{ - protected: - void handle(const LogDispatchData *data); - - private: - const LogDispatchData *m_data; - void dispatch(base::type::string_t &&logLine); -}; -#if ELPP_ASYNC_LOGGING -class AsyncLogDispatchCallback : public LogDispatchCallback -{ - protected: - void handle(const LogDispatchData *data); -}; -class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe -{ - public: - AsyncDispatchWorker(); - virtual ~AsyncDispatchWorker(); - - bool clean(void); - void emptyQueue(void); - virtual void start(void); - void handle(AsyncLogItem *logItem); - void run(void); - - void setContinueRunning(bool value) - { - base::threading::ScopedLock scopedLock(m_continueRunningMutex); - m_continueRunning = value; - } - - bool continueRunning(void) const - { - return m_continueRunning; - } - - private: - std::condition_variable cv; - bool m_continueRunning; - base::threading::Mutex m_continueRunningMutex; -}; -#endif // ELPP_ASYNC_LOGGING -} // namespace base -namespace base -{ -class DefaultLogBuilder : public LogBuilder -{ - public: - base::type::string_t build(const LogMessage *logMessage, bool appendNewLine) const; -}; -/// @brief Dispatches log messages -class LogDispatcher : base::NoCopy -{ - public: - LogDispatcher(bool proceed, LogMessage &&logMessage, base::DispatchAction dispatchAction) : m_proceed(proceed), - m_logMessage(std::move(logMessage)), - m_dispatchAction(std::move(dispatchAction)) - { - } - - void dispatch(void); - - private: - bool m_proceed; - LogMessage m_logMessage; - base::DispatchAction m_dispatchAction; -}; -#if defined(ELPP_STL_LOGGING) -/// @brief Workarounds to write some STL logs -/// -/// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers -/// of same type and provide iterator interface and pass it on to writeIterator(). -/// Remember, this is passed by value in constructor so that we dont change original containers. -/// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) -namespace workarounds -{ -/// @brief Abstract IterableContainer template that provides interface for iterable classes of type T -template -class IterableContainer -{ - public: - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - IterableContainer(void) {} - virtual ~IterableContainer(void) {} - iterator begin(void) - { - return getContainer().begin(); - } - iterator end(void) - { - return getContainer().end(); - } - - private: - virtual Container &getContainer(void) = 0; -}; -/// @brief Implements IterableContainer and provides iterable std::priority_queue class -template , typename Comparator = std::less> -class IterablePriorityQueue : public IterableContainer, - public std::priority_queue -{ - public: - IterablePriorityQueue(std::priority_queue queue_) - { - std::size_t count_ = 0; - while(++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) - { - this->push(queue_.top()); - queue_.pop(); - } - } - - private: - inline Container &getContainer(void) - { - return this->c; - } -}; -/// @brief Implements IterableContainer and provides iterable std::queue class -template > -class IterableQueue : public IterableContainer, public std::queue -{ - public: - IterableQueue(std::queue queue_) - { - std::size_t count_ = 0; - while(++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) - { - this->push(queue_.front()); - queue_.pop(); - } - } - - private: - inline Container &getContainer(void) - { - return this->c; - } -}; -/// @brief Implements IterableContainer and provides iterable std::stack class -template > -class IterableStack : public IterableContainer, public std::stack -{ - public: - IterableStack(std::stack stack_) - { - std::size_t count_ = 0; - while(++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) - { - this->push(stack_.top()); - stack_.pop(); - } - } - - private: - inline Container &getContainer(void) - { - return this->c; - } -}; -} // namespace workarounds -#endif // defined(ELPP_STL_LOGGING) -// Log message builder -class MessageBuilder -{ - public: - MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} - void initialize(Logger *logger); - -#define ELPP_SIMPLE_LOG(LOG_TYPE) \ - MessageBuilder &operator<<(LOG_TYPE msg) \ - { \ - m_logger->stream() << msg; \ - if(ELPP->hasFlag(LoggingFlag::AutoSpacing)) \ - { \ - m_logger->stream() << " "; \ - } \ - return *this; \ - } - - inline MessageBuilder &operator<<(const std::string &msg) - { - return operator<<(msg.c_str()); - } - ELPP_SIMPLE_LOG(char) - ELPP_SIMPLE_LOG(bool) - ELPP_SIMPLE_LOG(signed short) - ELPP_SIMPLE_LOG(unsigned short) - ELPP_SIMPLE_LOG(signed int) - ELPP_SIMPLE_LOG(unsigned int) - ELPP_SIMPLE_LOG(signed long) - ELPP_SIMPLE_LOG(unsigned long) - ELPP_SIMPLE_LOG(float) - ELPP_SIMPLE_LOG(double) - ELPP_SIMPLE_LOG(char *) - ELPP_SIMPLE_LOG(const char *) - ELPP_SIMPLE_LOG(const void *) - ELPP_SIMPLE_LOG(long double) - inline MessageBuilder &operator<<(const std::wstring &msg) - { - return operator<<(msg.c_str()); - } - MessageBuilder &operator<<(const wchar_t *msg); - // ostream manipulators - inline MessageBuilder &operator<<(std::ostream &(*OStreamMani)(std::ostream &)) - { - m_logger->stream() << OStreamMani; - return *this; - } -#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ - template \ - inline MessageBuilder &operator<<(const temp &template_inst) \ - { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ - template \ - inline MessageBuilder &operator<<(const temp &template_inst) \ - { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ - template \ - inline MessageBuilder &operator<<(const temp &template_inst) \ - { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ - template \ - inline MessageBuilder &operator<<(const temp &template_inst) \ - { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } -#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ - template \ - inline MessageBuilder &operator<<(const temp &template_inst) \ - { \ - return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ - } - -#if defined(ELPP_STL_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) - template - inline MessageBuilder &operator<<(const std::queue &queue_) - { - base::workarounds::IterableQueue iterableQueue_ = - static_cast>(queue_); - return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); - } - template - inline MessageBuilder &operator<<(const std::stack &stack_) - { - base::workarounds::IterableStack iterableStack_ = - static_cast>(stack_); - return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); - } - template - inline MessageBuilder &operator<<(const std::priority_queue &priorityQueue_) - { - base::workarounds::IterablePriorityQueue iterablePriorityQueue_ = - static_cast>(priorityQueue_); - return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); - } - template - MessageBuilder &operator<<(const std::pair &pair_) - { - m_logger->stream() << ELPP_LITERAL("("); - operator<<(static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator<<(static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - MessageBuilder &operator<<(const std::bitset &bitset_) - { - m_logger->stream() << ELPP_LITERAL("["); - operator<<(bitset_.to_string()); - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } -#if defined(ELPP_LOG_STD_ARRAY) - template - inline MessageBuilder &operator<<(const std::array &array) - { - return writeIterator(array.begin(), array.end(), array.size()); - } -#endif // defined(ELPP_LOG_STD_ARRAY) -#if defined(ELPP_LOG_UNORDERED_MAP) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) - ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) -#endif // defined(ELPP_LOG_UNORDERED_MAP) -#if defined(ELPP_LOG_UNORDERED_SET) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) -#endif // defined(ELPP_LOG_UNORDERED_SET) -#endif // defined(ELPP_STL_LOGGING) -#if defined(ELPP_QT_LOGGING) - inline MessageBuilder &operator<<(const QString &msg) - { -#if defined(ELPP_UNICODE) - m_logger->stream() << msg.toStdWString(); -#else - m_logger->stream() << msg.toStdString(); -#endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder &operator<<(const QByteArray &msg) - { - return operator<<(QString(msg)); - } - inline MessageBuilder &operator<<(const QStringRef &msg) - { - return operator<<(msg.toString()); - } - inline MessageBuilder &operator<<(qint64 msg) - { -#if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -#else - m_logger->stream() << QString::number(msg).toStdString(); -#endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder &operator<<(quint64 msg) - { -#if defined(ELPP_UNICODE) - m_logger->stream() << QString::number(msg).toStdWString(); -#else - m_logger->stream() << QString::number(msg).toStdString(); -#endif // defined(ELPP_UNICODE) - return *this; - } - inline MessageBuilder &operator<<(QChar msg) - { - m_logger->stream() << msg.toLatin1(); - return *this; - } - inline MessageBuilder &operator<<(const QLatin1String &msg) - { - m_logger->stream() << msg.latin1(); - return *this; - } - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) - template - MessageBuilder &operator<<(const QPair &pair_) - { - m_logger->stream() << ELPP_LITERAL("("); - operator<<(static_cast(pair_.first)); - m_logger->stream() << ELPP_LITERAL(", "); - operator<<(static_cast(pair_.second)); - m_logger->stream() << ELPP_LITERAL(")"); - return *this; - } - template - MessageBuilder &operator<<(const QMap &map_) - { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = map_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // to prevent warning - for(int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) - { - m_logger->stream() << ELPP_LITERAL("("); - operator<<(static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator<<(static_cast(map_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if(begin != end) - { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder &operator<<(const QMultiMap &map_) - { - operator<<(static_cast>(map_)); - return *this; - } - template - MessageBuilder &operator<<(const QHash &hash_) - { - m_logger->stream() << ELPP_LITERAL("["); - QList keys = hash_.keys(); - typename QList::const_iterator begin = keys.begin(); - typename QList::const_iterator end = keys.end(); - int max_ = static_cast(base::consts::kMaxLogPerContainer); // prevent type warning - for(int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) - { - m_logger->stream() << ELPP_LITERAL("("); - operator<<(static_cast(*begin)); - m_logger->stream() << ELPP_LITERAL(", "); - operator<<(static_cast(hash_.value(*begin))); - m_logger->stream() << ELPP_LITERAL(")"); - m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if(begin != end) - { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - return *this; - } - template - inline MessageBuilder &operator<<(const QMultiHash &multiHash_) - { - operator<<(static_cast>(multiHash_)); - return *this; - } -#endif // defined(ELPP_QT_LOGGING) -#if defined(ELPP_BOOST_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) - ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) - ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) - ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) -#endif // defined(ELPP_BOOST_LOGGING) - -/// @brief Macro used internally that can be used externally to make containers easylogging++ friendly -/// -/// @detail This macro expands to write an ostream& operator<< for container. This container is expected to -/// have begin() and end() methods that return respective iterators -/// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets -/// @param SizeMethod Method used to get size of container. -/// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro -/// for an example usage -#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ - el::base::type::ostream_t &operator<<(el::base::type::ostream_t &ss, const ContainerType &container) \ - { \ - const el::base::type::char_t *sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); \ - ContainerType::const_iterator elem = container.begin(); \ - ContainerType::const_iterator endElem = container.end(); \ - std::size_t size_ = container.SizeMethod; \ - ss << ELPP_LITERAL("["); \ - for(std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) \ - { \ - ss << ElementInstance; \ - ss << ((i < size_ - 1) ? sep : ELPP_LITERAL("")); \ - } \ - if(elem != endElem) \ - { \ - ss << ELPP_LITERAL("..."); \ - } \ - ss << ELPP_LITERAL("]"); \ - return ss; \ - } -#if defined(ELPP_WXWIDGETS_LOGGING) - ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) -#define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) -#define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) -#define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ -ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") -#else -#define ELPP_WX_PTR_ENABLED(ContainerType) -#define ELPP_WX_ENABLED(ContainerType) -#define ELPP_WX_HASH_MAP_ENABLED(ContainerType) -#endif // defined(ELPP_WXWIDGETS_LOGGING) - // Other classes - template - ELPP_SIMPLE_LOG(const Class &) -#undef ELPP_SIMPLE_LOG -#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG -#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG - private : Logger *m_logger; - const base::type::char_t *m_containerLogSeperator; - - template - MessageBuilder &writeIterator(Iterator begin_, Iterator end_, std::size_t size_) - { - m_logger->stream() << ELPP_LITERAL("["); - for(std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) - { - operator<<(*begin_); - m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); - } - if(begin_ != end_) - { - m_logger->stream() << ELPP_LITERAL("..."); - } - m_logger->stream() << ELPP_LITERAL("]"); - if(ELPP->hasFlag(LoggingFlag::AutoSpacing)) - { - m_logger->stream() << " "; - } - return *this; - } -}; -/// @brief Writes nothing - Used when certain log is disabled -class NullWriter : base::NoCopy -{ - public: - NullWriter(void) {} - - // Null manipulator - inline NullWriter &operator<<(std::ostream &(*)(std::ostream &)) - { - return *this; - } - - template - inline NullWriter &operator<<(const T &) - { - return *this; - } - - inline operator bool() - { - return true; - } -}; -/// @brief Main entry point of each logging -class Writer : base::NoCopy -{ - public: - Writer(Level level, const char *file, base::type::LineNumber line, - const char *func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), - m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) - { - } - - virtual ~Writer(void) - { - processDispatch(); - } - - template - inline typename std::enable_if::value, Writer &>::type - operator<<(T log) - { -#if ELPP_LOGGING_ENABLED - if(m_proceed) - { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - template - inline typename std::enable_if::value, Writer &>::type - operator<<(const T &log) - { -#if ELPP_LOGGING_ENABLED - if(m_proceed) - { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - inline Writer &operator<<(std::ostream &(*log)(std::ostream &)) - { -#if ELPP_LOGGING_ENABLED - if(m_proceed) - { - m_messageBuilder << log; - } -#endif // ELPP_LOGGING_ENABLED - return *this; - } - - inline operator bool() - { - return true; - } - - Writer &construct(Logger *logger, bool needLock = true); - Writer &construct(int count, const char *loggerIds, ...); - - protected: - Level m_level; - const char *m_file; - const base::type::LineNumber m_line; - const char *m_func; - base::type::VerboseLevel m_verboseLevel; - Logger *m_logger; - bool m_proceed; - base::MessageBuilder m_messageBuilder; - base::DispatchAction m_dispatchAction; - std::vector m_loggerIds; - friend class el::Helpers; - - void initializeLogger(const std::string &loggerId, bool lookup = true, bool needLock = true); - void processDispatch(); - void triggerDispatch(void); -}; -class PErrorWriter : public base::Writer -{ - public: - PErrorWriter(Level level, const char *file, base::type::LineNumber line, - const char *func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, - base::type::VerboseLevel verboseLevel = 0) : base::Writer(level, file, line, func, dispatchAction, verboseLevel) - { - } - - virtual ~PErrorWriter(void); -}; -} // namespace base -// Logging from Logger class. Why this is here? Because we have Storage and Writer class available -#if ELPP_VARIADIC_TEMPLATES_SUPPORTED -template -void Logger::log_(Level level, int vlevel, const char *s, const T &value, const Args &... args) -{ - base::MessageBuilder b; - b.initialize(this); - while(*s) - { - if(*s == base::consts::kFormatSpecifierChar) - { - if(*(s + 1) == base::consts::kFormatSpecifierChar) - { - ++s; - } - else - { - if(*(s + 1) == base::consts::kFormatSpecifierCharValue) - { - ++s; - b << value; - log_(level, vlevel, ++s, args...); - return; - } - } - } - b << *s++; - } - ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); -} -template -void Logger::log_(Level level, int vlevel, const T &log) -{ - if(level == Level::Verbose) - { - if(ELPP->vRegistry()->allowed(vlevel, __FILE__)) - { - base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", - base::DispatchAction::NormalLog, vlevel) - .construct(this, false) - << log; - } - else - { - stream().str(ELPP_LITERAL("")); - } - } - else - { - base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; - } -} -template -inline void Logger::log(Level level, const char *s, const T &value, const Args &... args) -{ - base::threading::ScopedLock scopedLock(lock()); - log_(level, 0, s, value, args...); -} -template -inline void Logger::log(Level level, const T &log) -{ - base::threading::ScopedLock scopedLock(lock()); - log_(level, 0, log); -} -#if ELPP_VERBOSE_LOG -template -inline void Logger::verbose(int vlevel, const char *s, const T &value, const Args &... args) -{ - base::threading::ScopedLock scopedLock(lock()); - log_(el::Level::Verbose, vlevel, s, value, args...); -} -template -inline void Logger::verbose(int vlevel, const T &log) -{ - base::threading::ScopedLock scopedLock(lock()); - log_(el::Level::Verbose, vlevel, log); -} -#else -template -inline void Logger::verbose(int, const char *, const T &, const Args &...) -{ - return; -} -template -inline void Logger::verbose(int, const T &) -{ - return; -} -#endif // ELPP_VERBOSE_LOG -#define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL) \ - template \ - inline void Logger::FUNCTION_NAME(const char *s, const T &value, const Args &... args) \ - { \ - log(LOG_LEVEL, s, value, args...); \ - } \ - template \ - inline void Logger::FUNCTION_NAME(const T &value) \ - { \ - log(LOG_LEVEL, value); \ - } -#define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL) \ - template \ - inline void Logger::FUNCTION_NAME(const char *, const T &, const Args &...) \ - { \ - return; \ - } \ - template \ - inline void Logger::FUNCTION_NAME(const T &) \ - { \ - return; \ - } - -#if ELPP_INFO_LOG -LOGGER_LEVEL_WRITERS(info, Level::Info) -#else -LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) -#endif // ELPP_INFO_LOG -#if ELPP_DEBUG_LOG -LOGGER_LEVEL_WRITERS(debug, Level::Debug) -#else -LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) -#endif // ELPP_DEBUG_LOG -#if ELPP_WARNING_LOG -LOGGER_LEVEL_WRITERS(warn, Level::Warning) -#else -LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) -#endif // ELPP_WARNING_LOG -#if ELPP_ERROR_LOG -LOGGER_LEVEL_WRITERS(error, Level::Error) -#else -LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) -#else -LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -LOGGER_LEVEL_WRITERS(trace, Level::Trace) -#else -LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) -#endif // ELPP_TRACE_LOG -#undef LOGGER_LEVEL_WRITERS -#undef LOGGER_LEVEL_WRITERS_DISABLED -#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED -#if ELPP_COMPILER_MSVC -#define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs -#define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) -#define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ##__VA_ARGS__, \ - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -#else -#if ELPP_COMPILER_CLANG -#define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -#else -#define el_getVALength(...) el_resolveVALength(0, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) -#endif // ELPP_COMPILER_CLANG -#endif // ELPP_COMPILER_MSVC -#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N -#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) \ - if(condition) \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ - ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ - ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ - ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \ - writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) -class PerformanceTrackingData -{ - public: - enum class DataType : base::type::EnumType - { - Checkpoint = 1, - Complete = 2 - }; - // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) - explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), - m_dataType(dataType), m_firstCheckpoint(false), m_file(""), m_line(0), m_func("") {} - inline const std::string *blockName(void) const; - inline const struct timeval *startTime(void) const; - inline const struct timeval *endTime(void) const; - inline const struct timeval *lastCheckpointTime(void) const; - inline const base::PerformanceTracker *performanceTracker(void) const - { - return m_performanceTracker; - } - inline PerformanceTrackingData::DataType dataType(void) const - { - return m_dataType; - } - inline bool firstCheckpoint(void) const - { - return m_firstCheckpoint; - } - inline std::string checkpointId(void) const - { - return m_checkpointId; - } - inline const char *file(void) const - { - return m_file; - } - inline base::type::LineNumber line(void) const - { - return m_line; - } - inline const char *func(void) const - { - return m_func; - } - inline const base::type::string_t *formattedTimeTaken() const - { - return &m_formattedTimeTaken; - } - inline const std::string &loggerId(void) const; - - private: - base::PerformanceTracker *m_performanceTracker; - base::type::string_t m_formattedTimeTaken; - PerformanceTrackingData::DataType m_dataType; - bool m_firstCheckpoint; - std::string m_checkpointId; - const char *m_file; - base::type::LineNumber m_line; - const char *m_func; - inline void init(base::PerformanceTracker *performanceTracker, bool firstCheckpoint = false) - { - m_performanceTracker = performanceTracker; - m_firstCheckpoint = firstCheckpoint; - } - - friend class el::base::PerformanceTracker; -}; -namespace base -{ -/// @brief Represents performanceTracker block of code that conditionally adds performance status to log -/// either when goes outside the scope of when checkpoint() is called -class PerformanceTracker : public base::threading::ThreadSafe, public Loggable -{ - public: - PerformanceTracker(const std::string &blockName, - base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, - const std::string &loggerId = std::string(el::base::consts::kPerformanceLoggerId), - bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel); - /// @brief Copy constructor - PerformanceTracker(const PerformanceTracker &t) : m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), - m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), - m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) - { - } - virtual ~PerformanceTracker(void); - /// @brief A checkpoint for current performanceTracker block. - void checkpoint(const std::string &id = std::string(), const char *file = __FILE__, - base::type::LineNumber line = __LINE__, - const char *func = ""); - inline Level level(void) const - { - return m_level; - } - - private: - std::string m_blockName; - base::TimestampUnit m_timestampUnit; - std::string m_loggerId; - bool m_scopedLog; - Level m_level; - bool m_hasChecked; - std::string m_lastCheckpointId; - bool m_enabled; - struct timeval m_startTime, m_endTime, m_lastCheckpointTime; - - PerformanceTracker(void); - - friend class el::PerformanceTrackingData; - friend class base::DefaultPerformanceTrackingCallback; - - const inline base::type::string_t getFormattedTimeTaken() const - { - return getFormattedTimeTaken(m_startTime); - } - - const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const; - - virtual inline void log(el::base::type::ostream_t &os) const - { - os << getFormattedTimeTaken(); - } -}; -class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback -{ - protected: - void handle(const PerformanceTrackingData *data) - { - m_data = data; - base::type::stringstream_t ss; - if(m_data->dataType() == PerformanceTrackingData::DataType::Complete) - { - ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); - } - else - { - ss << ELPP_LITERAL("Performance checkpoint"); - if(!m_data->checkpointId().empty()) - { - ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); - } - ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << *m_data->performanceTracker(); - if(!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) && m_data->performanceTracker()->m_hasChecked) - { - ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); - if(m_data->performanceTracker()->m_lastCheckpointId.empty()) - { - ss << ELPP_LITERAL("last checkpoint"); - } - else - { - ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); - } - ss << ELPP_LITERAL(")]"); - } - else - { - ss << ELPP_LITERAL("]"); - } - } - el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, m_data->loggerId().c_str()) << ss.str(); - } - - private: - const PerformanceTrackingData *m_data; -}; -} // namespace base -inline const std::string *PerformanceTrackingData::blockName() const -{ - return const_cast(&m_performanceTracker->m_blockName); -} -inline const struct timeval *PerformanceTrackingData::startTime() const -{ - return const_cast(&m_performanceTracker->m_startTime); -} -inline const struct timeval *PerformanceTrackingData::endTime() const -{ - return const_cast(&m_performanceTracker->m_endTime); -} -inline const struct timeval *PerformanceTrackingData::lastCheckpointTime() const -{ - return const_cast(&m_performanceTracker->m_lastCheckpointTime); -} -inline const std::string &PerformanceTrackingData::loggerId(void) const -{ - return m_performanceTracker->m_loggerId; -} -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) -namespace base -{ -/// @brief Contains some internal debugging tools like crash handler and stack tracer -namespace debug -{ -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -class StackTrace : base::NoCopy -{ - public: - static const unsigned int kMaxStack = 64; - static const unsigned int kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() - class StackTraceEntry - { - public: - StackTraceEntry(std::size_t index, const char *loc, const char *demang, const char *hex, const char *addr); - StackTraceEntry(std::size_t index, char *loc) : m_index(index), - m_location(loc) - { - } - std::size_t m_index; - std::string m_location; - std::string m_demangled; - std::string m_hex; - std::string m_addr; - friend std::ostream &operator<<(std::ostream &ss, const StackTraceEntry &si); - - private: - StackTraceEntry(void); - }; - - StackTrace(void) - { - generateNew(); - } - - virtual ~StackTrace(void) - { - } - - inline std::vector &getLatestStack(void) - { - return m_stack; - } - - friend std::ostream &operator<<(std::ostream &os, const StackTrace &st); - - private: - std::vector m_stack; - - void generateNew(void); -}; -/// @brief Handles unexpected crashes -class CrashHandler : base::NoCopy -{ - public: - typedef void (*Handler)(int); - - explicit CrashHandler(bool useDefault); - explicit CrashHandler(const Handler &cHandler) - { - setHandler(cHandler); - } - void setHandler(const Handler &cHandler); - - private: - Handler m_handler; -}; -#else -class CrashHandler -{ - public: - explicit CrashHandler(bool) {} -}; -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) -} // namespace debug -} // namespace base -extern base::debug::CrashHandler elCrashHandler; -#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ - el::base::type::ostream_t &operator<<(el::base::type::ostream_t &OutputStreamInstance, const ClassType &ClassInstance) -/// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor -class SysLogInitializer -{ - public: - SysLogInitializer(const char *processIdent, int options = 0, int facility = 0) - { -#if defined(ELPP_SYSLOG) - openlog(processIdent, options, facility); -#else - ELPP_UNUSED(processIdent); - ELPP_UNUSED(options); - ELPP_UNUSED(facility); -#endif // defined(ELPP_SYSLOG) - } - virtual ~SysLogInitializer(void) - { -#if defined(ELPP_SYSLOG) - closelog(); -#endif // defined(ELPP_SYSLOG) - } -}; -#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) -/// @brief Static helpers for developers -class Helpers : base::StaticClass -{ - public: - /// @brief Shares logging repository (base::Storage) - static inline void setStorage(base::type::StoragePointer storage) - { - ELPP = storage; - } - /// @return Main storage repository - static inline base::type::StoragePointer storage() - { - return ELPP; - } - /// @brief Sets application arguments and figures out whats active for logging and whats not. - static inline void setArgs(int argc, char **argv) - { - ELPP->setApplicationArguments(argc, argv); - } - /// @copydoc setArgs(int argc, char** argv) - static inline void setArgs(int argc, const char **argv) - { - ELPP->setApplicationArguments(argc, const_cast(argv)); - } - /// @brief Sets thread name for current thread. Requires std::thread - static inline void setThreadName(const std::string &name) - { - ELPP->setThreadName(name); - } - static inline std::string getThreadName() - { - return ELPP->getThreadName(base::threading::getCurrentThreadId()); - } -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - /// @brief Overrides default crash handler and installs custom handler. - /// @param crashHandler A functor with no return type that takes single int argument. - /// Handler is a typedef with specification: void (*Handler)(int) - static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler &crashHandler) - { - el::elCrashHandler.setHandler(crashHandler); - } - /// @brief Abort due to crash with signal in parameter - /// @param sig Crash signal - static void crashAbort(int sig, const char *sourceFile = "", unsigned int long line = 0); - /// @brief Logs reason of crash as per sig - /// @param sig Crash signal - /// @param stackTraceIfAvailable Includes stack trace if available - /// @param level Logging level - /// @param logger Logger to use for logging - static void logCrashReason(int sig, bool stackTraceIfAvailable = false, - Level level = Level::Fatal, const char *logger = base::consts::kDefaultLoggerId); -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_CRASH_LOG) - /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out - /// (can be useful for backing up) - static inline void installPreRollOutCallback(const PreRollOutCallback &callback) - { - ELPP->setPreRollOutCallback(callback); - } - /// @brief Uninstalls pre rollout callback - static inline void uninstallPreRollOutCallback(void) - { - ELPP->unsetPreRollOutCallback(); - } - /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched - template - static inline bool installLogDispatchCallback(const std::string &id) - { - return ELPP->installLogDispatchCallback(id); - } - /// @brief Uninstalls log dispatch callback - template - static inline void uninstallLogDispatchCallback(const std::string &id) - { - ELPP->uninstallLogDispatchCallback(id); - } - template - static inline T *logDispatchCallback(const std::string &id) - { - return ELPP->logDispatchCallback(id); - } -#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished - template - static inline bool installPerformanceTrackingCallback(const std::string &id) - { - return ELPP->installPerformanceTrackingCallback(id); - } - /// @brief Uninstalls post performance tracking handler - template - static inline void uninstallPerformanceTrackingCallback(const std::string &id) - { - ELPP->uninstallPerformanceTrackingCallback(id); - } - template - static inline T *performanceTrackingCallback(const std::string &id) - { - return ELPP->performanceTrackingCallback(id); - } -#endif // defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING) - /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const - template - static std::string convertTemplateToStdString(const T &templ) - { - el::Logger *logger = - ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); - if(logger == nullptr) - { - return std::string(); - } - base::MessageBuilder b; - b.initialize(logger); - logger->acquireLock(); - b << templ; -#if defined(ELPP_UNICODE) - std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); -#else - std::string s = logger->stream().str(); -#endif // defined(ELPP_UNICODE) - logger->stream().str(ELPP_LITERAL("")); - logger->releaseLock(); - return s; - } - /// @brief Returns command line arguments (pointer) provided to easylogging++ - static inline const el::base::utils::CommandLineArgs *commandLineArgs(void) - { - return ELPP->commandLineArgs(); - } - /// @brief Installs user defined format specifier and handler - static inline void installCustomFormatSpecifier(const CustomFormatSpecifier &customFormatSpecifier) - { - ELPP->installCustomFormatSpecifier(customFormatSpecifier); - } - /// @brief Uninstalls user defined format specifier and handler - static inline bool uninstallCustomFormatSpecifier(const char *formatSpecifier) - { - return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); - } - /// @brief Returns true if custom format specifier is installed - static inline bool hasCustomFormatSpecifier(const char *formatSpecifier) - { - return ELPP->hasCustomFormatSpecifier(formatSpecifier); - } - static inline void validateFileRolling(Logger *logger, Level level) - { - if(logger == nullptr) - return; - logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); - } -}; -/// @brief Static helpers to deal with loggers and their configurations -class Loggers : base::StaticClass -{ - public: - /// @brief Gets existing or registers new logger - static Logger *getLogger(const std::string &identity, bool registerIfNotAvailable = true); - /// @brief Changes default log builder for future loggers - static void setDefaultLogBuilder(el::LogBuilderPtr &logBuilderPtr); - /// @brief Installs logger registration callback, this callback is triggered when new logger is registered - template - static inline bool installLoggerRegistrationCallback(const std::string &id) - { - return ELPP->registeredLoggers()->installLoggerRegistrationCallback(id); - } - /// @brief Uninstalls log dispatch callback - template - static inline void uninstallLoggerRegistrationCallback(const std::string &id) - { - ELPP->registeredLoggers()->uninstallLoggerRegistrationCallback(id); - } - template - static inline T *loggerRegistrationCallback(const std::string &id) - { - return ELPP->registeredLoggers()->loggerRegistrationCallback(id); - } - /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister - /// loggers initialized / used by third-party libs. - static bool unregisterLogger(const std::string &identity); - /// @brief Whether or not logger with id is registered - static bool hasLogger(const std::string &identity); - /// @brief Reconfigures specified logger with new configurations - static Logger *reconfigureLogger(Logger *logger, const Configurations &configurations); - /// @brief Reconfigures logger with new configurations after looking it up using identity - static Logger *reconfigureLogger(const std::string &identity, const Configurations &configurations); - /// @brief Reconfigures logger's single configuration - static Logger *reconfigureLogger(const std::string &identity, ConfigurationType configurationType, - const std::string &value); - /// @brief Reconfigures all the existing loggers with new configurations - static void reconfigureAllLoggers(const Configurations &configurations); - /// @brief Reconfigures single configuration for all the loggers - static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string &value) - { - reconfigureAllLoggers(Level::Global, configurationType, value); - } - /// @brief Reconfigures single configuration for all the loggers for specified level - static void reconfigureAllLoggers(Level level, ConfigurationType configurationType, - const std::string &value); - /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers - static void setDefaultConfigurations(const Configurations &configurations, - bool reconfigureExistingLoggers = false); - /// @brief Returns current default - static const Configurations *defaultConfigurations(void); - /// @brief Returns log stream reference pointer if needed by user - static const base::LogStreamsReferenceMap *logStreamsReference(void); - /// @brief Default typed configuration based on existing defaultConf - static base::TypedConfigurations defaultTypedConfigurations(void); - /// @brief Populates all logger IDs in current repository. - /// @param [out] targetList List of fill up. - static std::vector *populateAllLoggerIds(std::vector *targetList); - /// @brief Sets configurations from global configuration file. - static void configureFromGlobal(const char *globalConfigurationFilePath); - /// @brief Configures loggers using command line arg. Ensure you have already set command line args, - /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. - /// If true is returned that does not mean it has been configured successfully, it only means that it - /// has attempeted to configure logger using configuration file provided in argument - static bool configureFromArg(const char *argKey); - /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered - static void flushAll(void); - /// @brief Adds logging flag used internally. - static inline void addFlag(LoggingFlag flag) - { - ELPP->addFlag(flag); - } - /// @brief Removes logging flag used internally. - static inline void removeFlag(LoggingFlag flag) - { - ELPP->removeFlag(flag); - } - /// @brief Determines whether or not certain flag is active - static inline bool hasFlag(LoggingFlag flag) - { - return ELPP->hasFlag(flag); - } - /// @brief Adds flag and removes it when scope goes out - class ScopedAddFlag - { - public: - ScopedAddFlag(LoggingFlag flag) : m_flag(flag) - { - Loggers::addFlag(m_flag); - } - ~ScopedAddFlag(void) - { - Loggers::removeFlag(m_flag); - } - - private: - LoggingFlag m_flag; - }; - /// @brief Removes flag and add it when scope goes out - class ScopedRemoveFlag - { - public: - ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) - { - Loggers::removeFlag(m_flag); - } - ~ScopedRemoveFlag(void) - { - Loggers::addFlag(m_flag); - } - - private: - LoggingFlag m_flag; - }; - /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) - static void setLoggingLevel(Level level) - { - ELPP->setLoggingLevel(level); - } - /// @brief Sets verbose level on the fly - static void setVerboseLevel(base::type::VerboseLevel level); - /// @brief Gets current verbose level - static base::type::VerboseLevel verboseLevel(void); - /// @brief Sets vmodules as specified (on the fly) - static void setVModules(const char *modules); - /// @brief Sets categories as specified (on the fly) - static void setCategories(const char *categories, bool clear = true); - /// @brief Gets current categories - static std::string getCategories(); - /// @brief Clears vmodules - static void clearVModules(void); - /// @brief Clears categories - static void clearCategories(void); - /// @brief Sets filename common prefix - static void setFilenameCommonPrefix(const std::string &prefix); - /// @brief Gets filename common prefix - static const std::string &getFilenameCommonPrefix(); -}; -class VersionInfo : base::StaticClass -{ - public: - /// @brief Current version number - static const std::string version(void); - - /// @brief Release date of current version - static const std::string releaseDate(void); -}; -} // namespace el -#undef VLOG_IS_ON -/// @brief Determines whether verbose logging is on for specified level current file. -#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) -#undef TIMED_BLOCK -#undef TIMED_SCOPE -#undef TIMED_SCOPE_IF -#undef TIMED_FUNC -#undef TIMED_FUNC_IF -#undef ELPP_MIN_UNIT -#if defined(ELPP_PERFORMANCE_MICROSECONDS) -#define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond -#else -#define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond -#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) -/// @brief Performance tracked scope. Performance gets written when goes out of scope using -/// 'performance' logger. -/// -/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); -/// @see el::base::PerformanceTracker -/// @see el::base::PerformanceTracker::checkpoint -// Note: Do not surround this definition with null macro because of obj instance -#define TIMED_SCOPE_IF(obj, blockname, condition) el::base::type::PerformanceTrackerPtr obj(condition ? new el::base::PerformanceTracker(blockname, ELPP_MIN_UNIT) : nullptr) -#define TIMED_SCOPE(obj, blockname) TIMED_SCOPE_IF(obj, blockname, true) -#define TIMED_BLOCK(obj, blockName) for(struct { int i; el::base::type::PerformanceTrackerPtr timer; } obj = {0, \ - el::base::type::PerformanceTrackerPtr(new el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT))}; \ - obj.i < 1; ++obj.i) -/// @brief Performance tracked function. Performance gets written when goes out of scope using -/// 'performance' logger. -/// -/// @detail Please note in order to check the performance at a certain time you can use obj->checkpoint(); -/// @see el::base::PerformanceTracker -/// @see el::base::PerformanceTracker::checkpoint -#define TIMED_FUNC_IF(obj, condition) TIMED_SCOPE_IF(obj, ELPP_FUNC, condition) -#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) -#undef PERFORMANCE_CHECKPOINT -#undef PERFORMANCE_CHECKPOINT_WITH_ID -#define PERFORMANCE_CHECKPOINT(obj) obj->checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) -#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj->checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) -#undef ELPP_COUNTER -#undef ELPP_COUNTER_POS -/// @brief Gets hit counter for file/line -#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) -/// @brief Gets hit counter position for file/line, -1 if not registered yet -#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) -// Undef levels to support LOG(LEVEL) -#undef INFO -#undef WARNING -#undef DEBUG -#undef ERROR -#undef FATAL -#undef TRACE -#undef VERBOSE -// Undef existing -#undef CINFO -#undef CWARNING -#undef CDEBUG -#undef CFATAL -#undef CERROR -#undef CTRACE -#undef CVERBOSE -#undef CINFO_IF -#undef CWARNING_IF -#undef CDEBUG_IF -#undef CERROR_IF -#undef CFATAL_IF -#undef CTRACE_IF -#undef CVERBOSE_IF -#undef CINFO_EVERY_N -#undef CWARNING_EVERY_N -#undef CDEBUG_EVERY_N -#undef CERROR_EVERY_N -#undef CFATAL_EVERY_N -#undef CTRACE_EVERY_N -#undef CVERBOSE_EVERY_N -#undef CINFO_AFTER_N -#undef CWARNING_AFTER_N -#undef CDEBUG_AFTER_N -#undef CERROR_AFTER_N -#undef CFATAL_AFTER_N -#undef CTRACE_AFTER_N -#undef CVERBOSE_AFTER_N -#undef CINFO_N_TIMES -#undef CWARNING_N_TIMES -#undef CDEBUG_N_TIMES -#undef CERROR_N_TIMES -#undef CFATAL_N_TIMES -#undef CTRACE_N_TIMES -#undef CVERBOSE_N_TIMES -// Normal logs -#if ELPP_INFO_LOG -#define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -#define CINFO(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -#define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -#define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -#define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -#define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -#define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -#define CERROR(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -#define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -#define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -#define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -#define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -#define CVERBOSE(writer, vlevel, dispatchAction, ...) \ - if(VLOG_IS_ON(vlevel)) \ - writer( \ - el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel) \ - .construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -#define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// Conditional logs -#if ELPP_INFO_LOG -#define CINFO_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) -#else -#define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -#define CWARNING_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -#define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -#define CDEBUG_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -#define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -#define CERROR_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) -#else -#define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -#define CFATAL_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -#define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -#define CTRACE_IF(writer, condition_, dispatchAction, ...) \ - ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -#define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -#define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) \ - if(VLOG_IS_ON(vlevel) && (condition_)) \ - writer( \ - el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel) \ - .construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) -#else -#define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// Occasional logs -#if ELPP_INFO_LOG -#define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -#define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -#define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -#define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -#define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -#define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -#define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -#define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -#define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -#define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -#define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) \ - ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -#define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -#define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) \ - CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) -#else -#define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// After N logs -#if ELPP_INFO_LOG -#define CINFO_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -#define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -#define CWARNING_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -#define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -#define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -#define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -#define CERROR_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -#define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -#define CFATAL_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -#define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -#define CTRACE_AFTER_N(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -#define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -#define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) \ - CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -#define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// N Times logs -#if ELPP_INFO_LOG -#define CINFO_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) -#else -#define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_INFO_LOG -#if ELPP_WARNING_LOG -#define CWARNING_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) -#else -#define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_WARNING_LOG -#if ELPP_DEBUG_LOG -#define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) -#else -#define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_DEBUG_LOG -#if ELPP_ERROR_LOG -#define CERROR_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) -#else -#define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_ERROR_LOG -#if ELPP_FATAL_LOG -#define CFATAL_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) -#else -#define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_FATAL_LOG -#if ELPP_TRACE_LOG -#define CTRACE_N_TIMES(writer, n, dispatchAction, ...) \ - ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) -#else -#define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_TRACE_LOG -#if ELPP_VERBOSE_LOG -#define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) \ - CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) -#else -#define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() -#endif // ELPP_VERBOSE_LOG -// -// Custom Loggers - Requires (level, dispatchAction, loggerId/s) -// -// undef existing -#undef CLOG -#undef CLOG_VERBOSE -#undef CVLOG -#undef CLOG_IF -#undef CLOG_VERBOSE_IF -#undef CVLOG_IF -#undef CLOG_EVERY_N -#undef CVLOG_EVERY_N -#undef CLOG_AFTER_N -#undef CVLOG_AFTER_N -#undef CLOG_N_TIMES -#undef CVLOG_N_TIMES -// Normal logs -#define CLOG(LEVEL, ...) \ - C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// Conditional logs -#define CLOG_IF(condition, LEVEL, ...) \ - C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_IF(condition, vlevel, ...) \ - CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// Hit counts based logs -#define CLOG_EVERY_N(n, LEVEL, ...) \ - C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_EVERY_N(n, vlevel, ...) \ - CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_AFTER_N(n, LEVEL, ...) \ - C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_AFTER_N(n, vlevel, ...) \ - CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CLOG_N_TIMES(n, LEVEL, ...) \ - C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CVLOG_N_TIMES(n, vlevel, ...) \ - CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) -// -// Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros -// -// undef existing -#undef LOG -#undef VLOG -#undef LOG_IF -#undef VLOG_IF -#undef LOG_EVERY_N -#undef VLOG_EVERY_N -#undef LOG_AFTER_N -#undef VLOG_AFTER_N -#undef LOG_N_TIMES -#undef VLOG_N_TIMES -#undef ELPP_CURR_FILE_LOGGER_ID -#if defined(ELPP_DEFAULT_LOGGER) -#define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER -#else -#define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId -#endif -#undef ELPP_TRACE -#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) -// Normal logs -#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Conditional logs -#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Hit counts based logs -#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Generic PLOG() -#undef CPLOG -#undef CPLOG_IF -#undef PLOG -#undef PLOG_IF -#undef DCPLOG -#undef DCPLOG_IF -#undef DPLOG -#undef DPLOG_IF -#define CPLOG(LEVEL, ...) \ - C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define CPLOG_IF(condition, LEVEL, ...) \ - C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG(LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define DCPLOG_IF(condition, LEVEL, ...) \ - C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) -#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -// Generic SYSLOG() -#undef CSYSLOG -#undef CSYSLOG_IF -#undef CSYSLOG_EVERY_N -#undef CSYSLOG_AFTER_N -#undef CSYSLOG_N_TIMES -#undef SYSLOG -#undef SYSLOG_IF -#undef SYSLOG_EVERY_N -#undef SYSLOG_AFTER_N -#undef SYSLOG_N_TIMES -#undef DCSYSLOG -#undef DCSYSLOG_IF -#undef DCSYSLOG_EVERY_N -#undef DCSYSLOG_AFTER_N -#undef DCSYSLOG_N_TIMES -#undef DSYSLOG -#undef DSYSLOG_IF -#undef DSYSLOG_EVERY_N -#undef DSYSLOG_AFTER_N -#undef DSYSLOG_N_TIMES -#if defined(ELPP_SYSLOG) -#define CSYSLOG(LEVEL, ...) \ - C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define CSYSLOG_IF(condition, LEVEL, ...) \ - C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -#define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -#define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -#define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -#define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -#define DCSYSLOG(LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define DCSYSLOG_IF(condition, LEVEL, ...) \ - C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) -#define DCSYSLOG_EVERY_N(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define DCSYSLOG_AFTER_N(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define DCSYSLOG_N_TIMES(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) -#define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) -#define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) -#define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -#define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) -#define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) -#else -#define CSYSLOG(LEVEL, ...) el::base::NullWriter() -#define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -#define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -#define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -#define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -#define SYSLOG(LEVEL) el::base::NullWriter() -#define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() -#define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -#define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -#define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -#define DCSYSLOG(LEVEL, ...) el::base::NullWriter() -#define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() -#define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() -#define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() -#define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() -#define DSYSLOG(LEVEL) el::base::NullWriter() -#define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() -#define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() -#define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() -#define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() -#endif // defined(ELPP_SYSLOG) -// -// Custom Debug Only Loggers - Requires (level, loggerId/s) -// -// undef existing -#undef DCLOG -#undef DCVLOG -#undef DCLOG_IF -#undef DCVLOG_IF -#undef DCLOG_EVERY_N -#undef DCVLOG_EVERY_N -#undef DCLOG_AFTER_N -#undef DCVLOG_AFTER_N -#undef DCLOG_N_TIMES -#undef DCVLOG_N_TIMES -// Normal logs -#define DCLOG(LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG(LEVEL, __VA_ARGS__) -#define DCLOG_VERBOSE(vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG_VERBOSE(vlevel, __VA_ARGS__) -#define DCVLOG(vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CVLOG(vlevel, __VA_ARGS__) -// Conditional logs -#define DCLOG_IF(condition, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG_IF(condition, LEVEL, __VA_ARGS__) -#define DCVLOG_IF(condition, vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CVLOG_IF(condition, vlevel, __VA_ARGS__) -// Hit counts based logs -#define DCLOG_EVERY_N(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_EVERY_N(n, vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) -#define DCLOG_AFTER_N(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) -#define DCVLOG_AFTER_N(n, vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) -#define DCLOG_N_TIMES(n, LEVEL, ...) \ - if(ELPP_DEBUG_LOG) \ - CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) -#define DCVLOG_N_TIMES(n, vlevel, ...) \ - if(ELPP_DEBUG_LOG) \ - CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) -// -// Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros -// -#if !defined(ELPP_NO_DEBUG_MACROS) -// undef existing -#undef DLOG -#undef DVLOG -#undef DLOG_IF -#undef DVLOG_IF -#undef DLOG_EVERY_N -#undef DVLOG_EVERY_N -#undef DLOG_AFTER_N -#undef DVLOG_AFTER_N -#undef DLOG_N_TIMES -#undef DVLOG_N_TIMES -// Normal logs -#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Conditional logs -#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) -// Hit counts based logs -#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) -#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) -#endif // defined(ELPP_NO_DEBUG_MACROS) -#if !defined(ELPP_NO_CHECK_MACROS) -// Check macros -#undef CCHECK -#undef CPCHECK -#undef CCHECK_EQ -#undef CCHECK_NE -#undef CCHECK_LT -#undef CCHECK_GT -#undef CCHECK_LE -#undef CCHECK_GE -#undef CCHECK_BOUNDS -#undef CCHECK_NOTNULL -#undef CCHECK_STRCASEEQ -#undef CCHECK_STRCASENE -#undef CHECK -#undef PCHECK -#undef CHECK_EQ -#undef CHECK_NE -#undef CHECK_LT -#undef CHECK_GT -#undef CHECK_LE -#undef CHECK_GE -#undef CHECK_BOUNDS -#undef CHECK_NOTNULL -#undef CHECK_STRCASEEQ -#undef CHECK_STRCASENE -#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " -#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) -#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) -#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) -#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) -#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) -#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) -#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) -#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -#define CCHECK_NOTNULL(ptr, ...) CCHECK((ptr) != nullptr, __VA_ARGS__) -#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " == " << #str2 << "] " -#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ - << "Check failed: [" << #str1 << " != " << #str2 << "] " -#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#undef DCCHECK -#undef DCCHECK_EQ -#undef DCCHECK_NE -#undef DCCHECK_LT -#undef DCCHECK_GT -#undef DCCHECK_LE -#undef DCCHECK_GE -#undef DCCHECK_BOUNDS -#undef DCCHECK_NOTNULL -#undef DCCHECK_STRCASEEQ -#undef DCCHECK_STRCASENE -#undef DCPCHECK -#undef DCHECK -#undef DCHECK_EQ -#undef DCHECK_NE -#undef DCHECK_LT -#undef DCHECK_GT -#undef DCHECK_LE -#undef DCHECK_GE -#undef DCHECK_BOUNDS_ -#undef DCHECK_NOTNULL -#undef DCHECK_STRCASEEQ -#undef DCHECK_STRCASENE -#undef DPCHECK -#define DCCHECK(condition, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK(condition, __VA_ARGS__) -#define DCCHECK_EQ(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_EQ(a, b, __VA_ARGS__) -#define DCCHECK_NE(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_NE(a, b, __VA_ARGS__) -#define DCCHECK_LT(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_LT(a, b, __VA_ARGS__) -#define DCCHECK_GT(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_GT(a, b, __VA_ARGS__) -#define DCCHECK_LE(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_LE(a, b, __VA_ARGS__) -#define DCCHECK_GE(a, b, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_GE(a, b, __VA_ARGS__) -#define DCCHECK_BOUNDS(val, min, max, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_BOUNDS(val, min, max, __VA_ARGS__) -#define DCCHECK_NOTNULL(ptr, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_NOTNULL((ptr), __VA_ARGS__) -#define DCCHECK_STREQ(str1, str2, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_STREQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRNE(str1, str2, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_STRNE(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASEEQ(str1, str2, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) -#define DCCHECK_STRCASENE(str1, str2, ...) \ - if(ELPP_DEBUG_LOG) \ - CCHECK_STRCASENE(str1, str2, __VA_ARGS__) -#define DCPCHECK(condition, ...) \ - if(ELPP_DEBUG_LOG) \ - CPCHECK(condition, __VA_ARGS__) -#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL((ptr), ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) -#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) -#endif // defined(ELPP_NO_CHECK_MACROS) -#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -#define ELPP_USE_DEF_CRASH_HANDLER false -#else -#define ELPP_USE_DEF_CRASH_HANDLER true -#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) -#define ELPP_CRASH_HANDLER_INIT -#define ELPP_INIT_EASYLOGGINGPP(val) \ - namespace el \ - { \ - namespace base \ - { \ - el::base::type::StoragePointer elStorage(val); \ - } \ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ - } - -#if ELPP_ASYNC_LOGGING -#define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()), \ - new el::base::AsyncDispatchWorker())) -#else -#define INITIALIZE_EASYLOGGINGPP ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) -#endif // ELPP_ASYNC_LOGGING -#define INITIALIZE_NULL_EASYLOGGINGPP \ - namespace el \ - { \ - namespace base \ - { \ - el::base::type::StoragePointer elStorage; \ - } \ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ - } -#define SHARE_EASYLOGGINGPP(initializedStorage) \ - namespace el \ - { \ - namespace base \ - { \ - el::base::type::StoragePointer elStorage(initializedStorage); \ - } \ - el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER); \ - } - -#if defined(ELPP_UNICODE) -#define START_EASYLOGGINGPP(argc, argv) \ - el::Helpers::setArgs(argc, argv); \ - std::locale::global(std::locale("")) -#else -#define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) -#endif // defined(ELPP_UNICODE) -#endif // EASYLOGGINGPP_H diff --git a/external/unbound/configure_checks.cmake b/external/unbound/configure_checks.cmake index 2acf556d..2f1878fe 100644 --- a/external/unbound/configure_checks.cmake +++ b/external/unbound/configure_checks.cmake @@ -191,16 +191,18 @@ check_include_file(openssl/err.h HAVE_OPENSSL_ERR_H) check_include_file(openssl/rand.h HAVE_OPENSSL_RAND_H) check_include_file(openssl/ssl.h HAVE_OPENSSL_SSL_H) -set(CMAKE_REQUIRED_INCLUDES) +set(CMAKE_REQUIRED_LIBRARIES + ${OPENSSL_LIBRARIES}) + +if (WIN32 AND OPENSSL_VERSION VERSION_GREATER 1.1.0) + set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};ws2_32") +endif() check_symbol_exists(NID_secp384r1 "openssl/evp.h" HAVE_DECL_NID_SECP384R1) check_symbol_exists(NID_X9_62_prime256v1 "openssl/evp.h" HAVE_DECL_NID_X9_62_PRIME256V1) check_symbol_exists(sk_SSL_COMP_pop_free "openssl/ssl.h" HAVE_DECL_SK_SSL_COMP_POP_FREE) check_symbol_exists(SSL_COMP_get_compression_methods "openssl/ssl.h" HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS) -set(CMAKE_REQUIRED_LIBRARIES - ${OPENSSL_LIBRARIES}) - check_function_exists(EVP_MD_CTX_new HAVE_EVP_MD_CTX_NEW) check_function_exists(EVP_sha1 HAVE_EVP_SHA1) check_function_exists(EVP_sha256 HAVE_EVP_SHA256) @@ -210,6 +212,7 @@ check_function_exists(HMAC_Update HAVE_HMAC_UPDATE) check_function_exists(OPENSSL_config HAVE_OPENSSL_CONFIG) check_function_exists(SHA512_Update HAVE_SHA512_UPDATE) +set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) set(UNBOUND_CONFIGFILE "${CMAKE_INSTALL_PREFIX}/etc/unbound/unbound.conf" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8cf4832c..b0bdabc6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 diff --git a/src/address_validator/CMakeLists.txt b/src/address_validator/CMakeLists.txt index 93c9259b..5d72bebc 100644 --- a/src/address_validator/CMakeLists.txt +++ b/src/address_validator/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, ryo-currency +# Copyright (c) 2019, Ryo Currency Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details # All rights reserved. @@ -29,7 +29,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 diff --git a/src/address_validator/address_validator.cpp b/src/address_validator/address_validator.cpp index ee02cf32..192b10c6 100644 --- a/src/address_validator/address_validator.cpp +++ b/src/address_validator/address_validator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, ryo-currency +// Copyright (c) 2019, Ryo Currency Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. @@ -16,6 +16,8 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#include "common/gulps.hpp" + #include "common/command_line.h" #include "address_validator/address_validator.h" #include "string_tools.h" @@ -73,19 +75,19 @@ bool address_validator::evaluate_address_attributes(const std::string &net_type, bool valid = false; if(net_type == "mainnet") { - valid = get_account_address_from_str(attr.info, addr_str, true); + valid = get_account_address_from_str(attr.info, addr_str); attr.network = valid ? "mainnet" : ""; attr.nettype = MAINNET; } else if(net_type == "testnet") { - valid = get_account_address_from_str(attr.info, addr_str, true); + valid = get_account_address_from_str(attr.info, addr_str); attr.network = valid ? "testnet" : ""; attr.nettype = TESTNET; } else if(net_type == "stagenet") { - valid = get_account_address_from_str(attr.info, addr_str, true); + valid = get_account_address_from_str(attr.info, addr_str); attr.network = valid ? "stagenet" : ""; attr.nettype = STAGENET; } @@ -100,7 +102,11 @@ void address_validator::init_options( { namespace po = boost::program_options; - desc.add_options()("network,n", po::value(&m_network)->default_value("auto"), "network type (auto, mainnet, testnet, stagenet)")("filename,f", po::value(&m_filename), "json file name, if not set result is printed to terminal")("human", po::value(&m_human)->zero_tokens()->default_value(false)->default_value(false), "human readable output")("address", po::value>(&m_address_strs), "ryo-currency address"); + desc.add_options() + ("network,n", po::value(&m_network)->default_value("auto"), "network type (auto, mainnet, testnet, stagenet)") + ("filename,f", po::value(&m_filename), "json file name, if not set result is printed to terminal") + ("human", po::value(&m_human)->zero_tokens()->default_value(false)->default_value(false), "human readable output") + ("address", po::value>(&m_address_strs), "ryo-currency address"); pos_option.add("address", -1); } @@ -109,14 +115,14 @@ bool address_validator::validate_options() { if(m_address_strs.empty()) { - MERROR("No address given."); + GULPS_ERROR("No address given."); return 1; } std::vector networks = {"auto", "mainnet", "testnet", "stagenet"}; if(std::find(networks.begin(), networks.end(), m_network) == networks.end()) { - MERROR("Invalid/Unknown network type " << m_network); + GULPSF_ERROR("Invalid/Unknown network type {}.", m_network); return 2; } return 0; @@ -177,10 +183,18 @@ int main(int argc, char *argv[]) po::options_description desc("Validate RYO/SUMOKOIN addresses and show properties\n\n" "ryo-address-validator [OPTIONS] WALLET_ADDRESS [WALLET_ADDRESS...]\n\n" "OPTIONS"); + po::positional_options_description pos_option; desc.add_options()("help,h", "print help message and exit"); + gulps::inst().set_thread_tag("MAIN"); + + // We won't replace the custom output writer here, so just direct **our** errors to console + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.cat_major == "addr_val" && msg.lvl == gulps::LEVEL_ERROR; }); + gulps::inst().add_output(std::move(out)); + using namespace cryptonote; address_validator validator{}; diff --git a/src/address_validator/address_validator.h b/src/address_validator/address_validator.h index 198f62f3..d8b6a8d0 100644 --- a/src/address_validator/address_validator.h +++ b/src/address_validator/address_validator.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -39,6 +39,7 @@ namespace cryptonote */ class address_validator { + GULPS_CAT_MAJOR("addr_val"); public: address_validator() = default; diff --git a/src/address_validator/writer.cpp b/src/address_validator/writer.cpp index 4d591ff7..37817556 100644 --- a/src/address_validator/writer.cpp +++ b/src/address_validator/writer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/address_validator/writer.h b/src/address_validator/writer.h index e475c860..8aa16b57 100644 --- a/src/address_validator/writer.h +++ b/src/address_validator/writer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt index c27a80e5..be7c6368 100644 --- a/src/blockchain_db/CMakeLists.txt +++ b/src/blockchain_db/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -84,5 +84,6 @@ target_link_libraries(blockchain_db ${BDB_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp index 38ca44f9..d96a8ac7 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.cpp +++ b/src/blockchain_db/berkeleydb/db_bdb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. diff --git a/src/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h index 2546b583..2754bec3 100644 --- a/src/blockchain_db/berkeleydb/db_bdb.h +++ b/src/blockchain_db/berkeleydb/db_bdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 0add1e01..8c5bdf25 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -37,8 +37,7 @@ static const char *db_types[] = { #endif NULL}; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "blockchain.db" + using epee::string_tools::pod_to_hex; @@ -106,12 +105,12 @@ void BlockchainDB::add_transaction(const crypto::hash &blk_hash, const transacti { bool miner_tx = false; crypto::hash tx_hash; - + if(!tx_hash_ptr) { // should only need to compute hash for miner transactions tx_hash = get_transaction_hash(tx); - LOG_PRINT_L3("null tx_hash_ptr - needed to compute: " << tx_hash); + GULPS_LOG_L3("null tx_hash_ptr - needed to compute: ", tx_hash); } else { @@ -131,7 +130,7 @@ void BlockchainDB::add_transaction(const crypto::hash &blk_hash, const transacti } else { - LOG_PRINT_L1("Unsupported input type, removing key images and aborting transaction addition"); + GULPS_LOG_L1("Unsupported input type, removing key images and aborting transaction addition"); for(const txin_v &tx_input : tx.vin) { if(tx_input.type() == typeid(txin_to_key)) @@ -169,7 +168,7 @@ void BlockchainDB::add_transaction(const crypto::hash &blk_hash, const transacti if(tx.vout[i].amount != 0) { //Better be safe than sorry - LOG_PRINT_L1("Unsupported index type, removing key images and aborting transaction addition"); + GULPS_LOG_L1("Unsupported index type, removing key images and aborting transaction addition"); for(const txin_v &tx_input : tx.vin) { if(tx_input.type() == typeid(txin_to_key)) @@ -321,23 +320,8 @@ void BlockchainDB::reset_stats() void BlockchainDB::show_stats() { - LOG_PRINT_L1(ENDL - << "*********************************" - << ENDL - << "num_calls: " << num_calls - << ENDL - << "time_blk_hash: " << time_blk_hash << "ms" - << ENDL - << "time_tx_exists: " << time_tx_exists << "ms" - << ENDL - << "time_add_block1: " << time_add_block1 << "ms" - << ENDL - << "time_add_transaction: " << time_add_transaction << "ms" - << ENDL - << "time_commit1: " << time_commit1 << "ms" - << ENDL - << "*********************************" - << ENDL); + GULPSF_LOG_L1("\n*********************************\nnum_calls: {}\ntime_blk_hash: {}ms\ntime_tx_exists: {}ms\ntime_add_block1: {}ms\ntime_add_transaction: {}ms\ntime_commit1: {}ms\n*********************************\n", + num_calls, time_blk_hash, time_tx_exists , time_add_block1, time_add_transaction, time_commit1); } void BlockchainDB::fixup() @@ -472,14 +456,14 @@ void BlockchainDB::fixup() if(is_read_only()) { - LOG_PRINT_L1("Database is opened read only - skipping fixup check"); + GULPS_LOG_L1("Database is opened read only - skipping fixup check"); return; } set_batch_transactions(true); batch_start(); - // premine key images + // premine key images static const char* const premine_key_images[] = { "a42fa875b187e7f9e8d25ad158187458cdcce0db9582b5ccd02e9a5d99a79239", //txid 29b65a4ddd5ad2502f4a5e536651de577837fef2b62e1eeccf518806a5195d98 @@ -496,7 +480,7 @@ void BlockchainDB::fixup() epee::string_tools::hex_to_pod(kis, ki); if(!has_key_image(ki)) { - LOG_PRINT_L1("Fixup: adding missing spent key " << ki); + GULPS_LOG_L1("Fixup: adding missing spent key ", ki); add_spent_key(ki); } } diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 0ca7ab8f..a001579a 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,6 +20,7 @@ #pragma once +#include "common/gulps.hpp" #include "common/command_line.h" #include "crypto/hash.h" #include "cryptonote_basic/blobdatatype.h" @@ -330,6 +331,7 @@ class KEY_IMAGE_EXISTS : public DB_EXCEPTION */ class BlockchainDB { + GULPS_CAT_MAJOR("blockchain_db"); private: /********************************************************************* * private virtual members @@ -389,7 +391,7 @@ class BlockchainDB /** * @brief remove data about a transaction * - * The subclass implementing this will remove the transaction data + * The subclass implementing this will remove the transaction data * for the passed transaction. The data to be removed was added in * add_transaction_data(). Additionally, current subclasses have behavior * which requires the transaction itself as a parameter here. Future @@ -1090,6 +1092,7 @@ class BlockchainDB * @return true iff the transaction was found */ virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const = 0; + virtual bool get_tx_blob_indexed(const crypto::hash& h, cryptonote::blobdata& bd, std::vector& o_idx) const = 0; /** * @brief fetches the total number of transactions ever @@ -1495,7 +1498,7 @@ class BlockchainDB bool m_open; //!< Whether or not the BlockchainDB is open/ready for use mutable epee::critical_section m_synchronization_lock; //!< A lock, currently for when BlockchainLMDB needs to resize the backing db file - inline bool is_vout_bad(const cryptonote::tx_out& vout) + inline bool is_vout_bad(const cryptonote::tx_out& vout) { return vout.target.type() == typeid(txout_to_key) && bad_outpks.find(boost::get(vout.target).key) != bad_outpks.end(); } diff --git a/src/blockchain_db/db_types.h b/src/blockchain_db/db_types.h index 5cc74888..709133a8 100644 --- a/src/blockchain_db/db_types.h +++ b/src/blockchain_db/db_types.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 390a6299..8c64eebc 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. @@ -19,7 +19,6 @@ #include #include -#include #include // memcpy #include // std::unique_ptr #include @@ -31,8 +30,6 @@ #include "ringct/rctOps.h" #include "string_tools.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "blockchain.db.lmdb" #if defined(__i386) || defined(__x86_64) #define MISALIGNED_OK 1 @@ -47,6 +44,7 @@ using namespace crypto; namespace { +GULPS_CAT_MAJOR("db_lmdb"); #pragma pack(push, 1) // This MUST be identical to output_data_t, without the extra rct data at the end @@ -61,14 +59,14 @@ struct pre_rct_output_data_t template inline void throw0(const T &e) { - LOG_PRINT_L0(e.what()); + GULPS_PRINT(e.what()); throw e; } template inline void throw1(const T &e) { - LOG_PRINT_L1(e.what()); + GULPS_LOG_L1(e.what()); throw e; } @@ -310,7 +308,7 @@ mdb_txn_safe::~mdb_txn_safe() { if(!m_check) return; - LOG_PRINT_L3("mdb_txn_safe: destructor"); + GULPS_LOG_L3("mdb_txn_safe: destructor"); if(m_tinfo != nullptr) { mdb_txn_reset(m_tinfo->m_ti_rtxn); @@ -320,7 +318,7 @@ mdb_txn_safe::~mdb_txn_safe() { if(m_batch_txn) // this is a batch txn and should have been handled before this point for safety { - LOG_PRINT_L0("WARNING: mdb_txn_safe: m_txn is a batch txn and it's not NULL in destructor - calling mdb_txn_abort()"); + GULPS_PRINT("WARNING: mdb_txn_safe: m_txn is a batch txn and it's not NULL in destructor - calling mdb_txn_abort()"); } else { @@ -330,7 +328,7 @@ mdb_txn_safe::~mdb_txn_safe() // // NOTE: not sure if this is ever reached for a non-batch write // transaction, but it's probably not ideal if it did. - LOG_PRINT_L3("mdb_txn_safe: m_txn not NULL in destructor - calling mdb_txn_abort()"); + GULPS_LOG_L3("mdb_txn_safe: m_txn not NULL in destructor - calling mdb_txn_abort()"); } mdb_txn_abort(m_txn); } @@ -360,7 +358,7 @@ void mdb_txn_safe::commit(std::string message) void mdb_txn_safe::abort() { - LOG_PRINT_L3("mdb_txn_safe: abort()"); + GULPS_LOG_L3("mdb_txn_safe: abort()"); if(m_txn != nullptr) { mdb_txn_abort(m_txn); @@ -368,7 +366,7 @@ void mdb_txn_safe::abort() } else { - LOG_PRINT_L0("WARNING: mdb_txn_safe: abort() called, but m_txn is NULL"); + GULPS_PRINT("WARNING: mdb_txn_safe: abort() called, but m_txn is NULL"); } } @@ -398,7 +396,7 @@ void lmdb_resized(MDB_env *env) { mdb_txn_safe::prevent_new_txns(); - MGINFO("LMDB map resize detected."); + GULPS_GLOBAL_PRINT("LMDB map resize detected."); MDB_envinfo mei; @@ -414,9 +412,7 @@ void lmdb_resized(MDB_env *env) mdb_env_info(env, &mei); uint64_t new_mapsize = mei.me_mapsize; - MGINFO("LMDB Mapsize increased." - << " Old: " << old / (1024 * 1024) << "MiB" - << ", New: " << new_mapsize / (1024 * 1024) << "MiB"); + GULPSF_GLOBAL_PRINT("LMDB Mapsize increased. Old: {}MiB, New: {}MiB", old / (1024 * 1024), new_mapsize / (1024 * 1024)); mdb_txn_safe::allow_new_txns(); } @@ -445,7 +441,7 @@ inline int lmdb_txn_renew(MDB_txn *txn) void BlockchainLMDB::do_resize(uint64_t increase_size) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); CRITICAL_REGION_LOCAL(m_synchronization_lock); const uint64_t add_size = 1LL << 30; @@ -456,14 +452,14 @@ void BlockchainLMDB::do_resize(uint64_t increase_size) boost::filesystem::space_info si = boost::filesystem::space(path); if(si.available < add_size) { - MERROR("!! WARNING: Insufficient free space to extend database !!: " << (si.available >> 20L) << " MB available, " << (add_size >> 20L) << " MB needed"); + GULPSF_ERROR("!! WARNING: Insufficient free space to extend database !!: {} MB available, {} MB needed{}", (si.available >> 20L), (add_size >> 20L)); return; } } catch(...) { // print something but proceed. - MWARNING("Unable to query free disk space."); + GULPS_WARN("Unable to query free disk space."); } MDB_envinfo mei; @@ -505,9 +501,7 @@ void BlockchainLMDB::do_resize(uint64_t increase_size) if(result) throw0(DB_ERROR(lmdb_error("Failed to set new mapsize: ", result).c_str())); - MGINFO("LMDB Mapsize increased." - << " Old: " << mei.me_mapsize / (1024 * 1024) << "MiB" - << ", New: " << new_mapsize / (1024 * 1024) << "MiB"); + GULPSF_GLOBAL_PRINT("LMDB Mapsize increased. Old: {}MiB, New: {}MiB", mei.me_mapsize / (1024 * 1024), new_mapsize / (1024 * 1024)); mdb_txn_safe::allow_new_txns(); } @@ -515,7 +509,7 @@ void BlockchainLMDB::do_resize(uint64_t increase_size) // threshold_size is used for batch transactions bool BlockchainLMDB::need_resize(uint64_t threshold_size) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); #if defined(ENABLE_AUTO_RESIZE) MDB_envinfo mei; @@ -531,18 +525,18 @@ bool BlockchainLMDB::need_resize(uint64_t threshold_size) const // additional size needed. uint64_t size_used = mst.ms_psize * mei.me_last_pgno; - LOG_PRINT_L1("DB map size: " << mei.me_mapsize); - LOG_PRINT_L1("Space used: " << size_used); - LOG_PRINT_L1("Space remaining: " << mei.me_mapsize - size_used); - LOG_PRINT_L1("Size threshold: " << threshold_size); + GULPSF_LOG_L1("DB map size: {}", mei.me_mapsize); + GULPSF_LOG_L1("Space used: {}", size_used); + GULPSF_LOG_L1("Space remaining: {}", mei.me_mapsize - size_used); + GULPSF_LOG_L1("Size threshold: {}", threshold_size); float resize_percent_old = RESIZE_PERCENT; - LOG_PRINT_L1(boost::format("Percent used: %.04f Percent threshold: %.04f") % ((double)size_used / mei.me_mapsize) % resize_percent_old); + GULPSF_LOG_L1("Percent used: {:.04f} Percent threshold: {:.04f}", ((double)size_used / mei.me_mapsize), resize_percent_old); if(threshold_size > 0) { if(mei.me_mapsize - size_used < threshold_size) { - LOG_PRINT_L1("Threshold met (size-based)"); + GULPS_LOG_L1("Threshold met (size-based)"); return true; } else @@ -555,7 +549,7 @@ bool BlockchainLMDB::need_resize(uint64_t threshold_size) const if((double)size_used / mei.me_mapsize > resize_percent) { - LOG_PRINT_L1("Threshold met (percent-based)"); + GULPS_LOG_L1("Threshold met (percent-based)"); return true; } return false; @@ -566,16 +560,15 @@ bool BlockchainLMDB::need_resize(uint64_t threshold_size) const void BlockchainLMDB::check_and_resize_for_batch(uint64_t batch_num_blocks, uint64_t batch_bytes) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); - LOG_PRINT_L1("[" << __func__ << "] " - << "checking DB size"); + GULPS_LOG_L3("BlockchainLMDB::", __func__); + GULPSF_LOG_L1("[{}] checking DB size", __func__ ); const uint64_t min_increase_size = 512 * (1 << 20); uint64_t threshold_size = 0; uint64_t increase_size = 0; if(batch_num_blocks > 0) { threshold_size = get_estimated_batch_size(batch_num_blocks, batch_bytes); - MDEBUG("calculated batch size: " << threshold_size); + GULPSF_LOG_L1("calculated batch size: {}" , threshold_size); // The increased DB size could be a multiple of threshold_size, a fixed // size increase (> threshold_size), or other variations. @@ -584,7 +577,7 @@ void BlockchainLMDB::check_and_resize_for_batch(uint64_t batch_num_blocks, uint6 // minimum size increase is used to avoid frequent resizes when the batch // size is set to a very small numbers of blocks. increase_size = (threshold_size > min_increase_size) ? threshold_size : min_increase_size; - MDEBUG("increase size: " << increase_size); + GULPSF_LOG_L1("increase size: {}" , increase_size); } // if threshold_size is 0 (i.e. number of blocks for batch not passed in), it @@ -592,14 +585,14 @@ void BlockchainLMDB::check_and_resize_for_batch(uint64_t batch_num_blocks, uint6 // size-based check if(need_resize(threshold_size)) { - MGINFO("[batch] DB resize needed"); + GULPS_GLOBAL_PRINT("[batch] DB resize needed"); do_resize(increase_size); } } uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uint64_t batch_bytes) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); uint64_t threshold_size = 0; // batch size estimate * batch safety factor = final size estimate @@ -622,8 +615,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin block_start = block_stop - num_prev_blocks + 1; uint32_t num_blocks_used = 0; uint64_t total_block_size = 0; - MDEBUG("[" << __func__ << "] " - << "m_height: " << m_height << " block_start: " << block_start << " block_stop: " << block_stop); + GULPSF_LOG_L1("[{}] m_height: {} block_start: {} block_stop: {}",__func__ , m_height, block_start, block_stop); size_t avg_block_size = 0; if(batch_bytes) { @@ -632,12 +624,12 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin } if(m_height == 0) { - MDEBUG("No existing blocks to check for average block size"); + GULPS_LOG_L1("No existing blocks to check for average block size"); } else if(m_cum_count >= num_prev_blocks) { avg_block_size = m_cum_size / m_cum_count; - MDEBUG("average block size across recent " << m_cum_count << " blocks: " << avg_block_size); + GULPSF_LOG_L1("average block size across recent {} blocks: {}", m_cum_count , avg_block_size); m_cum_size = 0; m_cum_count = 0; } @@ -656,12 +648,12 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin } block_rtxn_stop(); avg_block_size = total_block_size / num_blocks_used; - MDEBUG("average block size across recent " << num_blocks_used << " blocks: " << avg_block_size); + GULPSF_LOG_L1("average block size across recent {} blocks: {}", num_blocks_used , avg_block_size); } estim: if(avg_block_size < min_block_size) avg_block_size = min_block_size; - MDEBUG("estimated average block size for batch: " << avg_block_size); + GULPSF_LOG_L1("estimated average block size for batch: {}" , avg_block_size); // bigger safety margin on smaller block sizes if(batch_fudge_factor < 5000.0) @@ -673,7 +665,7 @@ uint64_t BlockchainLMDB::get_estimated_batch_size(uint64_t batch_num_blocks, uin void BlockchainLMDB::add_block(const block &blk, const size_t &block_size, const difficulty_type &cumulative_difficulty, const uint64_t &coins_generated, const crypto::hash &blk_hash) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; uint64_t m_height = height(); @@ -690,8 +682,8 @@ void BlockchainLMDB::add_block(const block &blk, const size_t &block_size, const int result = mdb_cursor_get(m_cur_block_heights, (MDB_val *)&zerokval, &parent_key, MDB_GET_BOTH); if(result) { - LOG_PRINT_L3("m_height: " << m_height); - LOG_PRINT_L3("parent_key: " << blk.prev_id); + GULPSF_LOG_L3("m_height: {}", m_height); + GULPSF_LOG_L3("parent_key: {}", blk.prev_id); throw0(DB_ERROR(lmdb_error("Failed to get top block hash to check for new block's parent: ", result).c_str())); } blk_height *prev = (blk_height *)parent_key.mv_data; @@ -737,7 +729,7 @@ void BlockchainLMDB::remove_block() { int result; - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); uint64_t m_height = height(); @@ -774,7 +766,7 @@ void BlockchainLMDB::remove_block() uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash &blk_hash, const transaction &tx, const crypto::hash &tx_hash) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; uint64_t m_height = height(); @@ -825,7 +817,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash &tx_hash, const { int result; - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -850,7 +842,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash &tx_hash, const result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET); if(result == MDB_NOTFOUND) - LOG_PRINT_L1("tx has no outputs to remove: " << tx_hash); + GULPSF_LOG_L1("tx has no outputs to remove: {}", tx_hash); else if(result) throw1(DB_ERROR(lmdb_error("Failed to locate tx outputs for removal: ", result).c_str())); if(!result) @@ -871,7 +863,7 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash &tx_hash, const uint64_t unlock_time, const rct::key *commitment) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; uint64_t m_height = height(); @@ -929,7 +921,7 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash &tx_hash, void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id, const std::vector &amount_output_indices) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; CURSOR(tx_outputs) @@ -942,7 +934,7 @@ void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id, const st MDB_val v; v.mv_data = (void *)amount_output_indices.data(); v.mv_size = sizeof(uint64_t) * num_outputs; - // LOG_PRINT_L1("tx_outputs[tx_hash] size: " << v.mv_size); + // GULPSF_LOG_L1("tx_outputs[tx_hash] size: {}", v.mv_size); result = mdb_cursor_put(m_cur_tx_outputs, &k_tx_id, &v, MDB_APPEND); if(result) @@ -951,14 +943,14 @@ void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id, const st void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction &tx) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); std::vector amount_output_indices = get_tx_amount_output_indices(tx_id); if(amount_output_indices.empty()) { if(tx.vout.empty()) - LOG_PRINT_L2("tx has no outputs, so no output indices"); + GULPS_LOG_L2("tx has no outputs, so no output indices"); else throw0(DB_ERROR("tx has outputs, but no output indices found")); } @@ -973,7 +965,7 @@ void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction & void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t &out_index) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; CURSOR(output_amounts); @@ -1011,7 +1003,7 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t &out_in void BlockchainLMDB::add_spent_key(const crypto::key_image &k_image) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -1029,7 +1021,7 @@ void BlockchainLMDB::add_spent_key(const crypto::key_image &k_image) void BlockchainLMDB::remove_spent_key(const crypto::key_image &k_image) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -1049,7 +1041,7 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image &k_image) blobdata BlockchainLMDB::output_to_blob(const tx_out &output) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); blobdata b; if(!t_serializable_object_to_blob(output, b)) throw1(DB_ERROR("Error serializing output to blob")); @@ -1058,7 +1050,7 @@ blobdata BlockchainLMDB::output_to_blob(const tx_out &output) const tx_out BlockchainLMDB::output_from_blob(const blobdata &blob) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); std::stringstream ss; ss << blob; binary_archive ba(ss); @@ -1072,14 +1064,14 @@ tx_out BlockchainLMDB::output_from_blob(const blobdata &blob) const void BlockchainLMDB::check_open() const { - // LOG_PRINT_L3("BlockchainLMDB::" << __func__); + // GULPS_LOG_L3("BlockchainLMDB::", __func__); if(!m_open) throw0(DB_ERROR("DB operation attempted on a not-open DB instance")); } BlockchainLMDB::~BlockchainLMDB() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); // batch transaction shouldn't be active at this point. If it is, consider it aborted. if(m_batch_active) @@ -1090,7 +1082,7 @@ BlockchainLMDB::~BlockchainLMDB() BlockchainLMDB::BlockchainLMDB(bool batch_transactions) : BlockchainDB() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); // initialize folder to something "safe" just in case // someone accidentally misuses this class... m_folder = "thishsouldnotexistbecauseitisgibberish"; @@ -1110,7 +1102,7 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) int result; int mdb_flags = MDB_NORDAHEAD; - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(m_open) throw0(DB_OPEN_FAILURE("Attempted to open db, but it's already open")); @@ -1131,8 +1123,8 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) boost::filesystem::path old_files = direc.parent_path(); if(boost::filesystem::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_FILENAME) || boost::filesystem::exists(old_files / CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME)) { - LOG_PRINT_L0("Found existing LMDB files in " << old_files.string()); - LOG_PRINT_L0("Move " << CRYPTONOTE_BLOCKCHAINDATA_FILENAME << " and/or " << CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME << " to " << filename << ", or delete them, and then restart"); + GULPS_PRINT("Found existing LMDB files in ", old_files.string()); + GULPSF_PRINT("Move {} and/or {} to {}, or delete them, and then restart", CRYPTONOTE_BLOCKCHAINDATA_FILENAME, CRYPTONOTE_BLOCKCHAINDATA_LOCK_FILENAME, filename); throw DB_ERROR("Database could not be opened"); } @@ -1180,12 +1172,12 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) throw0(DB_ERROR(lmdb_error("Failed to set max memory map size: ", result).c_str())); mdb_env_info(m_env, &mei); cur_mapsize = (double)mei.me_mapsize; - LOG_PRINT_L1("LMDB memory map size: " << cur_mapsize); + GULPSF_LOG_L1("LMDB memory map size: {}", cur_mapsize); } if(need_resize()) { - LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now."); + GULPS_PRINT("LMDB memory map needs to be resized, doing that now."); do_resize(); } @@ -1249,7 +1241,7 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) MDB_stat db_stats; if((result = mdb_stat(txn, m_blocks, &db_stats))) throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str())); - LOG_PRINT_L2("Setting m_height to: " << db_stats.ms_entries); + GULPSF_LOG_L2("Setting m_height to: {}", db_stats.ms_entries); uint64_t m_height = db_stats.ms_entries; bool compatible = true; @@ -1261,7 +1253,7 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) { if(*(const uint32_t *)v.mv_data > VERSION) { - MWARNING("Existing lmdb database was made by a later version. We don't know how it will change yet."); + GULPS_WARN("Existing lmdb database was made by a later version. We don't know how it will change yet."); compatible = false; } #if VERSION > 0 @@ -1291,8 +1283,8 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) txn.abort(); mdb_env_close(m_env); m_open = false; - MFATAL("Existing lmdb database is incompatible with this version."); - MFATAL("Please delete the existing database and resync."); + GULPS_ERROR("Existing lmdb database is incompatible with this version."); + GULPS_ERROR("Please delete the existing database and resync."); return; } @@ -1309,7 +1301,7 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) txn.abort(); mdb_env_close(m_env); m_open = false; - MERROR("Failed to write version to database."); + GULPS_ERROR("Failed to write version to database."); return; } } @@ -1324,10 +1316,10 @@ void BlockchainLMDB::open(const std::string &filename, const int db_flags) void BlockchainLMDB::close() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(m_batch_active) { - LOG_PRINT_L3("close() first calling batch_abort() due to active batch transaction"); + GULPS_LOG_L3("close() first calling batch_abort() due to active batch transaction"); batch_abort(); } this->sync(); @@ -1340,7 +1332,7 @@ void BlockchainLMDB::close() void BlockchainLMDB::sync() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); // Does nothing unless LMDB environment was opened with MDB_NOSYNC or in part @@ -1353,13 +1345,13 @@ void BlockchainLMDB::sync() void BlockchainLMDB::safesyncmode(const bool onoff) { - MINFO("switching safe mode " << (onoff ? "on" : "off")); + GULPSF_INFO("switching safe mode {}", (onoff ? "on" :"off")); mdb_env_set_flags(m_env, MDB_NOSYNC | MDB_MAPASYNC, !onoff); } void BlockchainLMDB::reset() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_safe txn; @@ -1403,7 +1395,7 @@ void BlockchainLMDB::reset() std::vector BlockchainLMDB::get_filenames() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); std::vector filenames; boost::filesystem::path datafile(m_folder); @@ -1419,7 +1411,7 @@ std::vector BlockchainLMDB::get_filenames() const std::string BlockchainLMDB::get_db_name() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); return std::string("lmdb02"); } @@ -1427,7 +1419,7 @@ std::string BlockchainLMDB::get_db_name() const // TODO: this? bool BlockchainLMDB::lock() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); return false; } @@ -1435,7 +1427,7 @@ bool BlockchainLMDB::lock() // TODO: this? void BlockchainLMDB::unlock() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); } @@ -1498,7 +1490,7 @@ void BlockchainLMDB::unlock() void BlockchainLMDB::add_txpool_tx(const transaction &tx, const txpool_tx_meta_t &meta) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -1528,7 +1520,7 @@ void BlockchainLMDB::add_txpool_tx(const transaction &tx, const txpool_tx_meta_t void BlockchainLMDB::update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -1555,7 +1547,7 @@ void BlockchainLMDB::update_txpool_tx(const crypto::hash &txid, const txpool_tx_ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); int result; @@ -1600,7 +1592,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const bool BlockchainLMDB::txpool_has_tx(const crypto::hash &txid) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -1616,7 +1608,7 @@ bool BlockchainLMDB::txpool_has_tx(const crypto::hash &txid) const void BlockchainLMDB::remove_txpool_tx(const crypto::hash &txid) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; @@ -1646,7 +1638,7 @@ void BlockchainLMDB::remove_txpool_tx(const crypto::hash &txid) bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta_t &meta) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -1667,7 +1659,7 @@ bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash &txid, txpool_tx_meta bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash &txid, cryptonote::blobdata &bd) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -1696,7 +1688,7 @@ cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash &txid bool BlockchainLMDB::for_all_txpool_txes(std::function f, bool include_blob, bool include_unrelayed_txes) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -1749,7 +1741,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function BlockchainLMDB::get_blocks_range(const uint64_t &h1, const uint64_t &h2) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); std::vector v; @@ -2005,7 +1997,7 @@ std::vector BlockchainLMDB::get_blocks_range(const uint64_t &h1, const ui std::vector BlockchainLMDB::get_hashes_range(const uint64_t &h1, const uint64_t &h2) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); std::vector v; @@ -2019,7 +2011,7 @@ std::vector BlockchainLMDB::get_hashes_range(const uint64_t &h1, c crypto::hash BlockchainLMDB::top_block_hash() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); uint64_t m_height = height(); if(m_height != 0) @@ -2032,7 +2024,7 @@ crypto::hash BlockchainLMDB::top_block_hash() const block BlockchainLMDB::get_top_block() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); uint64_t m_height = height(); @@ -2047,7 +2039,7 @@ block BlockchainLMDB::get_top_block() const uint64_t BlockchainLMDB::height() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); int result; @@ -2061,7 +2053,7 @@ uint64_t BlockchainLMDB::height() const uint64_t BlockchainLMDB::num_outputs() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); int result; @@ -2075,7 +2067,7 @@ uint64_t BlockchainLMDB::num_outputs() const bool BlockchainLMDB::tx_exists(const crypto::hash &h) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2101,7 +2093,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash &h) const if(!tx_found) { - LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db"); + GULPSF_LOG_L1("transaction with hash {} not found in db", epee::string_tools::pod_to_hex(h) ); return false; } @@ -2115,7 +2107,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash &h) const bool BlockchainLMDB::tx_exists(const crypto::hash &h, uint64_t &tx_id) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2138,7 +2130,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash &h, uint64_t &tx_id) const bool ret = false; if(get_result == MDB_NOTFOUND) { - LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db"); + GULPSF_LOG_L1("transaction with hash {} not found in db", epee::string_tools::pod_to_hex(h) ); } else if(get_result) throw0(DB_ERROR(lmdb_error("DB error attempting to fetch transaction from hash", get_result).c_str())); @@ -2150,7 +2142,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash &h, uint64_t &tx_id) const uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash &h) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2171,7 +2163,7 @@ uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash &h) const bool BlockchainLMDB::get_tx_blob(const crypto::hash &h, cryptonote::blobdata &bd) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2199,9 +2191,59 @@ bool BlockchainLMDB::get_tx_blob(const crypto::hash &h, cryptonote::blobdata &bd return true; } +bool BlockchainLMDB::get_tx_blob_indexed(const crypto::hash& h, cryptonote::blobdata& bd, std::vector& o_idx) const +{ + GULPS_LOG_L3("BlockchainLMDB::", __func__); + check_open(); + + TXN_PREFIX_RDONLY(); + RCURSOR(tx_indices); + RCURSOR(txs); + + MDB_val_set(v, h); + MDB_val result; + auto get_result = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + uint64_t db_tx_id; + if(get_result == 0) + { + txindex *tip = (txindex *)v.mv_data; + db_tx_id = tip->data.tx_id; + MDB_val_set(val_tx_id, tip->data.tx_id); + get_result = mdb_cursor_get(m_cur_txs, &val_tx_id, &result, MDB_SET); + } + if(get_result == MDB_NOTFOUND) + return false; + else if(get_result) + throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str())); + + bd.assign(reinterpret_cast(result.mv_data), result.mv_size); + + RCURSOR(tx_outputs); + int out_result = 0; + MDB_val_set(k_tx_id, db_tx_id); + MDB_val out_v; + + out_result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_id, &out_v, MDB_SET); + if(out_result == MDB_NOTFOUND) + GULPS_PRINT("WARNING: Unexpected: tx has no amount indices stored in ", + "tx_outputs, but it should have an empty entry even if it's a tx without ", + "outputs"); + else if(out_result) + throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", out_result).c_str())); + + const uint64_t *indices = (const uint64_t *)out_v.mv_data; + int num_outputs = out_v.mv_size / sizeof(uint64_t); + + o_idx.resize(num_outputs); + memcpy(o_idx.data(), indices, out_v.mv_size); + + TXN_POSTFIX_RDONLY(); + return true; +} + uint64_t BlockchainLMDB::get_tx_count() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2218,7 +2260,7 @@ uint64_t BlockchainLMDB::get_tx_count() const std::vector BlockchainLMDB::get_tx_list(const std::vector &hlist) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); std::vector v; @@ -2232,7 +2274,7 @@ std::vector BlockchainLMDB::get_tx_list(const std::vector offsets; std::vector indices; offsets.push_back(index); @@ -2398,7 +2440,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index(const uint64_t &amount, con std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_t tx_id) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); @@ -2412,8 +2454,8 @@ std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_ result = mdb_cursor_get(m_cur_tx_outputs, &k_tx_id, &v, MDB_SET); if(result == MDB_NOTFOUND) - LOG_PRINT_L0("WARNING: Unexpected: tx has no amount indices stored in " - "tx_outputs, but it should have an empty entry even if it's a tx without " + GULPS_PRINT("WARNING: Unexpected: tx has no amount indices stored in ", + "tx_outputs, but it should have an empty entry even if it's a tx without ", "outputs"); else if(result) throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", result).c_str())); @@ -2424,7 +2466,7 @@ std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_ amount_output_indices.reserve(num_outputs); for(int i = 0; i < num_outputs; ++i) { - // LOG_PRINT_L0("amount output index[" << 2*i << "]" << ": " << paired_indices[2*i] << " global output index: " << paired_indices[2*i+1]); + // GULPS_PRINT("amount output index[" << 2*i << "]" << ": " << paired_indices[2*i] << " global output index: " << paired_indices[2*i+1]); amount_output_indices.push_back(indices[i]); } indices = nullptr; @@ -2435,7 +2477,7 @@ std::vector BlockchainLMDB::get_tx_amount_output_indices(const uint64_ bool BlockchainLMDB::has_key_image(const crypto::key_image &img) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); bool ret; @@ -2452,7 +2494,7 @@ bool BlockchainLMDB::has_key_image(const crypto::key_image &img) const bool BlockchainLMDB::for_all_key_images(std::function f) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2486,7 +2528,7 @@ bool BlockchainLMDB::for_all_key_images(std::function f) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2539,7 +2581,7 @@ bool BlockchainLMDB::for_blocks_range(const uint64_t &h1, const uint64_t &h2, st bool BlockchainLMDB::for_all_transactions(std::function f) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2588,7 +2630,7 @@ bool BlockchainLMDB::for_all_transactions(std::function f) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2624,7 +2666,7 @@ bool BlockchainLMDB::for_all_outputs(std::function &f) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2646,7 +2688,7 @@ bool BlockchainLMDB::for_all_outputs(uint64_t amount, const std::functionm_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags)); } - LOG_PRINT_L3("batch transaction: begin"); + GULPS_LOG_L3("batch transaction: begin"); return true; } void BlockchainLMDB::batch_commit() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(!m_batch_transactions) throw0(DB_ERROR("batch transactions not enabled")); if(!m_batch_active) @@ -2721,12 +2763,12 @@ void BlockchainLMDB::batch_commit() check_open(); - LOG_PRINT_L3("batch transaction: committing..."); + GULPS_LOG_L3("batch transaction: committing..."); TIME_MEASURE_START(time1); m_write_txn->commit(); TIME_MEASURE_FINISH(time1); time_commit1 += time1; - LOG_PRINT_L3("batch transaction: committed"); + GULPS_LOG_L3("batch transaction: committed"); m_write_txn = nullptr; delete m_write_batch_txn; @@ -2746,7 +2788,7 @@ void BlockchainLMDB::cleanup_batch() void BlockchainLMDB::batch_stop() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(!m_batch_transactions) throw0(DB_ERROR("batch transactions not enabled")); if(!m_batch_active) @@ -2756,7 +2798,7 @@ void BlockchainLMDB::batch_stop() if(m_writer != boost::this_thread::get_id()) throw1(DB_ERROR("batch transaction owned by other thread")); check_open(); - LOG_PRINT_L3("batch transaction: committing..."); + GULPS_LOG_L3("batch transaction: committing..."); TIME_MEASURE_START(time1); try { @@ -2770,12 +2812,12 @@ void BlockchainLMDB::batch_stop() cleanup_batch(); throw; } - LOG_PRINT_L3("batch transaction: end"); + GULPS_LOG_L3("batch transaction: end"); } void BlockchainLMDB::batch_abort() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(!m_batch_transactions) throw0(DB_ERROR("batch transactions not enabled")); if(!m_batch_active) @@ -2793,18 +2835,18 @@ void BlockchainLMDB::batch_abort() m_write_batch_txn = nullptr; m_batch_active = false; memset(&m_wcursors, 0, sizeof(m_wcursors)); - LOG_PRINT_L3("batch transaction: aborted"); + GULPS_LOG_L3("batch transaction: aborted"); } void BlockchainLMDB::set_batch_transactions(bool batch_transactions) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if((batch_transactions) && (m_batch_transactions)) { - LOG_PRINT_L0("WARNING: batch transaction mode already enabled, but asked to enable batch mode"); + GULPS_PRINT("WARNING: batch transaction mode already enabled, but asked to enable batch mode"); } m_batch_transactions = batch_transactions; - LOG_PRINT_L3("batch transactions " << (m_batch_transactions ? "enabled" : "disabled")); + GULPS_LOG_L3("batch transactions ", (m_batch_transactions ? "enabled" : "disabled")); } // return true if we started the txn, false if already started @@ -2843,13 +2885,13 @@ bool BlockchainLMDB::block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) co *mcur = &tinfo->m_ti_rcursors; if(ret) - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); return ret; } void BlockchainLMDB::block_rtxn_stop() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); mdb_txn_reset(m_tinfo->m_ti_rtxn); memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags)); } @@ -2864,7 +2906,7 @@ void BlockchainLMDB::block_txn_start(bool readonly) return; } - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); // Distinguish the exceptions here from exceptions that would be thrown while // using the txn and committing it. // @@ -2898,7 +2940,7 @@ void BlockchainLMDB::block_txn_start(bool readonly) void BlockchainLMDB::block_txn_stop() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(m_write_txn && m_writer == boost::this_thread::get_id()) { if(!m_batch_active) @@ -2922,7 +2964,7 @@ void BlockchainLMDB::block_txn_stop() void BlockchainLMDB::block_txn_abort() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); if(m_write_txn && m_writer == boost::this_thread::get_id()) { if(!m_batch_active) @@ -2950,7 +2992,7 @@ void BlockchainLMDB::block_txn_abort() uint64_t BlockchainLMDB::add_block(const block &blk, const size_t &block_size, const difficulty_type &cumulative_difficulty, const uint64_t &coins_generated, const std::vector &txs) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); uint64_t m_height = height(); @@ -2959,7 +3001,7 @@ uint64_t BlockchainLMDB::add_block(const block &blk, const size_t &block_size, c // for batch mode, DB resize check is done at start of batch transaction if(!m_batch_active && need_resize()) { - LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now."); + GULPS_PRINT("LMDB memory map needs to be resized, doing that now."); do_resize(); } } @@ -2983,7 +3025,7 @@ uint64_t BlockchainLMDB::add_block(const block &blk, const size_t &block_size, c void BlockchainLMDB::pop_block(block &blk, std::vector &txs) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); block_txn_start(false); @@ -3003,7 +3045,7 @@ void BlockchainLMDB::pop_block(block &blk, std::vector &txs) void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector &global_indices, std::vector &tx_out_indices) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); tx_out_indices.clear(); @@ -3030,7 +3072,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector &offsets, std::vector &outputs, bool allow_partial) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); TIME_MEASURE_START(db3); check_open(); outputs.clear(); @@ -3049,7 +3091,7 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector(amount) + ", index " + boost::lexical_cast(index) + ", count " + boost::lexical_cast(get_num_outputs(amount)) + "), but key does not exist (current height " + boost::lexical_cast(height()) + ")").c_str())); @@ -3075,12 +3117,12 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector &offsets, std::vector &indices) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); indices.clear(); @@ -3110,12 +3152,12 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t &amount, const std:: get_output_tx_and_index_from_global(tx_indices, indices); } TIME_MEASURE_FINISH(db3); - LOG_PRINT_L3("db3: " << db3); + GULPSF_LOG_L3("db3: {}", db3); } std::map> BlockchainLMDB::get_output_histogram(const std::vector &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -3212,7 +3254,7 @@ std::map> BlockchainLMDB::get bool BlockchainLMDB::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector &distribution, uint64_t &base) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -3257,7 +3299,7 @@ void BlockchainLMDB::check_hard_fork_info() void BlockchainLMDB::drop_hard_fork_info() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX(0); @@ -3274,7 +3316,7 @@ void BlockchainLMDB::drop_hard_fork_info() void BlockchainLMDB::set_hard_fork_version(uint64_t height, uint8_t version) { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_BLOCK_PREFIX(0); @@ -3293,7 +3335,7 @@ void BlockchainLMDB::set_hard_fork_version(uint64_t height, uint8_t version) uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -3325,7 +3367,7 @@ bool BlockchainLMDB::is_read_only() const void BlockchainLMDB::fixup() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); // Always call parent as well BlockchainDB::fixup(); } @@ -3342,19 +3384,17 @@ void BlockchainLMDB::fixup() ptr = (char *)k.mv_data; \ ptr[sizeof(name) - 2] = 's' -#define LOGIF(y) if(ELPP->vRegistry()->allowed(y, RYO_DEFAULT_LOG_CATEGORY)) - void BlockchainLMDB::migrate_0_1() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); uint64_t i, z, m_height; int result; mdb_txn_safe txn(false); MDB_val k, v; char *ptr; - MLOG_YELLOW(el::Level::Info, "Migrating blockchain from DB version 0 to 1 - this may take a while:"); - MINFO("updating blocks, hf_versions, outputs, txs, and spent_keys tables..."); + GULPS_INFO_CLR(gulps::COLOR_YELLOW, "Migrating blockchain from DB version 0 to 1 - this may take a while:"); + GULPS_INFO("updating blocks, hf_versions, outputs, txs, and spent_keys tables..."); do { @@ -3366,10 +3406,10 @@ void BlockchainLMDB::migrate_0_1() if((result = mdb_stat(txn, m_blocks, &db_stats))) throw0(DB_ERROR(lmdb_error("Failed to query m_blocks: ", result).c_str())); m_height = db_stats.ms_entries; - MINFO("Total number of blocks: " << m_height); - MINFO("block migration will update block_heights, block_info, and hf_versions..."); + GULPSF_INFO("Total number of blocks: {}", m_height); + GULPS_INFO("block migration will update block_heights, block_info, and hf_versions..."); - MINFO("migrating block_heights:"); + GULPS_INFO("migrating block_heights:"); MDB_dbi o_heights; unsigned int flags; @@ -3380,7 +3420,7 @@ void BlockchainLMDB::migrate_0_1() if((flags & (MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED)) == (MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED)) { txn.abort(); - LOG_PRINT_L1(" block_heights already migrated"); + GULPS_LOG_L1(" block_heights already migrated"); break; } @@ -3408,10 +3448,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPSF_LOG_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3476,7 +3514,7 @@ void BlockchainLMDB::migrate_0_1() */ do { - LOG_PRINT_L1("migrating block info:"); + GULPS_LOG_L1("migrating block info:"); MDB_dbi coins; result = mdb_txn_begin(m_env, NULL, 0, txn); @@ -3486,7 +3524,7 @@ void BlockchainLMDB::migrate_0_1() if(result == MDB_NOTFOUND) { txn.abort(); - LOG_PRINT_L1(" block_info already migrated"); + GULPS_LOG_L1(" block_info already migrated"); break; } MDB_dbi diffs, hashes, sizes, timestamps; @@ -3507,10 +3545,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPSF_LOG_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3614,7 +3650,7 @@ void BlockchainLMDB::migrate_0_1() do { - LOG_PRINT_L1("migrating hf_versions:"); + GULPS_LOG_L1("migrating hf_versions:"); MDB_dbi o_hfv; unsigned int flags; @@ -3628,7 +3664,7 @@ void BlockchainLMDB::migrate_0_1() if(flags & MDB_INTEGERKEY) { txn.abort(); - LOG_PRINT_L1(" hf_versions already migrated"); + GULPS_LOG_L1(" hf_versions already migrated"); break; } @@ -3648,10 +3684,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPSF_LOG_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3703,7 +3737,7 @@ void BlockchainLMDB::migrate_0_1() do { - LOG_PRINT_L1("deleting old indices:"); + GULPS_LOG_L1("deleting old indices:"); /* Delete all other tables, we're just going to recreate them */ MDB_dbi dbi; @@ -3715,7 +3749,7 @@ void BlockchainLMDB::migrate_0_1() if(result == MDB_NOTFOUND) { txn.abort(); - LOG_PRINT_L1(" old indices already deleted"); + GULPS_LOG_L1(" old indices already deleted"); break; } txn.abort(); @@ -3723,7 +3757,7 @@ void BlockchainLMDB::migrate_0_1() #define DELETE_DB(x) \ do \ { \ - LOG_PRINT_L1(" " x ":"); \ + GULPSF_LOG_L1(" {}:", x); \ result = mdb_txn_begin(m_env, NULL, 0, txn); \ if(result) \ throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", result).c_str())); \ @@ -3762,7 +3796,7 @@ void BlockchainLMDB::migrate_0_1() do { - LOG_PRINT_L1("migrating txs and outputs:"); + GULPS_LOG_L1("migrating txs and outputs:"); unsigned int flags; result = mdb_txn_begin(m_env, NULL, 0, txn); @@ -3775,7 +3809,7 @@ void BlockchainLMDB::migrate_0_1() if(flags & MDB_INTEGERKEY) { txn.abort(); - LOG_PRINT_L1(" txs already migrated"); + GULPS_LOG_L1(" txs already migrated"); break; } @@ -3806,10 +3840,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPSF_LOG_L0("{}/{}\r",i, z); + MDB_val_set(pk, "txblk"); MDB_val_set(pv, m_height); result = mdb_cursor_put(c_props, &pk, &pv, 0); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index f1c26e9d..c0b86e0e 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. @@ -18,6 +18,7 @@ #include +#include "common/gulps.hpp" #include "blockchain_db/blockchain_db.h" #include "cryptonote_basic/blobdatatype.h" // for type blobdata #include "ringct/rctTypes.h" @@ -145,6 +146,7 @@ struct mdb_txn_safe // write for block and tx data, so no write transaction is open at the time. class BlockchainLMDB : public BlockchainDB { + GULPS_CAT_MAJOR("db_lmdb"); public: BlockchainLMDB(bool batch_transactions = false); ~BlockchainLMDB(); @@ -207,6 +209,7 @@ class BlockchainLMDB : public BlockchainDB virtual uint64_t get_tx_unlock_time(const crypto::hash &h) const; virtual bool get_tx_blob(const crypto::hash &h, cryptonote::blobdata &tx) const; + virtual bool get_tx_blob_indexed(const crypto::hash& h, cryptonote::blobdata& bd, std::vector& o_idx) const; virtual uint64_t get_tx_count() const; diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 602f75f4..f16103ba 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -124,7 +124,8 @@ target_link_libraries(blockchain_import ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) if(ARCH_WIDTH) target_compile_definitions(blockchain_import @@ -152,7 +153,8 @@ target_link_libraries(blockchain_export ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) set_property(TARGET blockchain_export PROPERTY @@ -177,7 +179,8 @@ target_link_libraries(blockchain_blackball ${Boost_THREAD_LIBRARY} ${Boost_LOCALE_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) set_property(TARGET blockchain_blackball PROPERTY @@ -201,7 +204,8 @@ target_link_libraries(blockchain_usage ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) set_property(TARGET blockchain_usage PROPERTY diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index 1c62a3f3..6568e49a 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 "cryptonote_core/blockchain.h" #include "blockchain_db/blockchain_db.h" #include "blockchain_db/db_types.h" @@ -28,8 +29,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blockch_blackball"); namespace po = boost::program_options; using namespace epee; @@ -122,7 +124,7 @@ static bool for_all_transactions(const std::string &filename, const std::functio ss << bd; binary_archive ba(ss); bool r = do_serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); if(!f(tx)) { @@ -139,6 +141,8 @@ static bool for_all_transactions(const std::string &filename, const std::functio return fret; } +gulps_log_level log_scr; + int main(int argc, char *argv[]) { #ifdef WIN32 @@ -151,7 +155,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -206,20 +210,53 @@ int main(int argc, char *argv[]) if(!r) return 1; + gulps::inst().set_thread_tag("BLOCKCH_BLACKBALL"); + + //Temp error output + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.lvl >= gulps::LEVEL_ERROR; }); + auto temp_handle = gulps::inst().add_output(std::move(out)); + + if(!command_line::is_arg_defaulted(vm, arg_log_level)) + { + if(!log_scr.parse_cat_string(command_line::get_arg(vm, arg_log_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, arg_log_level).c_str()); + return 1; + } + } + else + { + if(!log_scr.parse_cat_string(std::to_string(log_level).c_str())) + { + GULPSF_ERROR("Failed to parse filter string {}", log_level); + return 1; + } + } + + gulps::inst().remove_output(temp_handle); + + if(log_scr.is_active()) + { + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(msg.out != gulps::OUT_LOG_0 && msg.out != gulps::OUT_USER_0) + return false; + if(printed) + return false; + return log_scr.match_msg(msg); + }); + gulps::inst().add_output(std::move(out)); + } + if(command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; + GULPS_PRINT("Ryo '", RYO_RELEASE_NAME, "' (", RYO_VERSION_FULL, ")\n)"); + GULPS_PRINT(desc_options); return 0; } - mlog_configure(mlog_get_default_log_path("ryo-blockchain-blackball.log"), true); - if(!command_line::is_arg_defaulted(vm, arg_log_level)) - mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); - else - mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); - - LOG_PRINT_L0("Starting..."); + GULPS_PRINT("Starting..."); bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); @@ -230,7 +267,7 @@ int main(int argc, char *argv[]) std::string db_type = command_line::get_arg(vm, arg_database); if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cerr << "Invalid database type: " << db_type << std::endl; + GULPS_ERROR("Invalid database type: ", db_type); return 1; } @@ -245,11 +282,11 @@ int main(int argc, char *argv[]) // Blockchain* core_storage = new Blockchain(NULL); // because unlike blockchain_storage constructor, which takes a pointer to // tx_memory_pool, Blockchain's constructor takes tx_memory_pool object. - LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); + GULPS_PRINT("Initializing source blockchain (BlockchainDB)"); const std::vector inputs = command_line::get_arg(vm, arg_inputs); if(inputs.empty()) { - LOG_PRINT_L0("No inputs given"); + GULPS_ERROR("No inputs given"); return 1; } std::vector> core_storage(inputs.size()); @@ -262,15 +299,15 @@ int main(int argc, char *argv[]) BlockchainDB *db = new_db(db_type); if(db == NULL) { - LOG_ERROR("Attempted to use non-existent database type: " << db_type); + GULPS_ERROR("Attempted to use non-existent database type: ", db_type); throw std::runtime_error("Attempting to use non-existent database type"); } - LOG_PRINT_L0("database: " << db_type); + GULPS_PRINT("database: " , db_type); std::string filename = inputs[n]; while(boost::ends_with(filename, "/") || boost::ends_with(filename, "\\")) filename.pop_back(); - LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); + GULPSF_PRINT("Loading blockchain from folder {} ..." , filename); try { @@ -278,13 +315,13 @@ int main(int argc, char *argv[]) } catch(const std::exception &e) { - LOG_PRINT_L0("Error opening database: " << e.what()); + GULPS_PRINT("Error opening database: " , e.what()); return 1; } r = core_storage[n]->init(db, net_type); - CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); - LOG_PRINT_L0("Source blockchain storage initialized OK"); + GULPS_CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); + GULPS_PRINT("Source blockchain storage initialized OK"); } boost::filesystem::path direc(output_file_path.string()); @@ -292,7 +329,7 @@ int main(int argc, char *argv[]) { if(!boost::filesystem::is_directory(direc)) { - MERROR("LMDB needs a directory path, but a file was passed: " << output_file_path.string()); + GULPS_ERROR("LMDB needs a directory path, but a file was passed: " , output_file_path.string()); return 1; } } @@ -300,12 +337,12 @@ int main(int argc, char *argv[]) { if(!boost::filesystem::create_directories(direc)) { - MERROR("Failed to create directory: " << output_file_path.string()); + GULPS_ERROR("Failed to create directory: " , output_file_path.string()); return 1; } } - LOG_PRINT_L0("Scanning for blackballable outputs..."); + GULPS_PRINT("Scanning for blackballable outputs..."); size_t done = 0; std::unordered_map> relative_rings; @@ -317,7 +354,7 @@ int main(int argc, char *argv[]) for(size_t n = 0; n < inputs.size(); ++n) { - LOG_PRINT_L0("Reading blockchain from " << inputs[n]); + GULPS_PRINT("Reading blockchain from " , inputs[n]); for_all_transactions(inputs[n], [&](const cryptonote::transaction_prefix &tx) -> bool { for(const auto &in : tx.vin) { @@ -337,17 +374,18 @@ int main(int argc, char *argv[]) if(ring_size == 1) { const crypto::public_key pkey = core_storage[n]->get_output_key(txin.amount, txin.key_offsets[0]); - MINFO("Blackballing output " << pkey << ", due to being used in a 1-ring"); + GULPSF_INFO("Blackballing output {}, due to being used in a 1-ring", pkey); ringdb.blackball(pkey); newly_spent.insert(output_data(txin.amount, txin.key_offsets[0])); spent.insert(output_data(txin.amount, txin.key_offsets[0])); } else if(relative_rings.find(txin.k_image) != relative_rings.end()) { - MINFO("Key image " << txin.k_image << " already seen: rings " << boost::join(relative_rings[txin.k_image] | boost::adaptors::transformed([](uint64_t out) { return std::to_string(out); }), " ") << ", " << boost::join(txin.key_offsets | boost::adaptors::transformed([](uint64_t out) { return std::to_string(out); }), " ")); + GULPS_INFO("Key image ", txin.k_image, " already seen: rings ", boost::join(relative_rings[txin.k_image] | boost::adaptors::transformed([](uint64_t out) { return std::to_string(out); }), " "), ", ", boost::join(txin.key_offsets | boost::adaptors::transformed([](uint64_t out) { return std::to_string(out); }), " ")); + if(relative_rings[txin.k_image] != txin.key_offsets) { - MINFO("Rings are different"); + GULPS_INFO("Rings are different"); const std::vector r0 = cryptonote::relative_output_offsets_to_absolute(relative_rings[txin.k_image]); const std::vector r1 = cryptonote::relative_output_offsets_to_absolute(txin.key_offsets); std::vector common; @@ -358,19 +396,19 @@ int main(int argc, char *argv[]) } if(common.empty()) { - MERROR("Rings for the same key image are disjoint"); + GULPS_ERROR("Rings for the same key image are disjoint"); } else if(common.size() == 1) { const crypto::public_key pkey = core_storage[n]->get_output_key(txin.amount, common[0]); - MINFO("Blackballing output " << pkey << ", due to being used in rings with a single common element"); + GULPSF_INFO("Blackballing output {}, due to being used in rings with a single common element" , pkey); ringdb.blackball(pkey); newly_spent.insert(output_data(txin.amount, common[0])); spent.insert(output_data(txin.amount, common[0])); } else { - MINFO("The intersection has more than one element, it's still ok"); + GULPS_INFO("The intersection has more than one element, it's still ok"); for(const auto &out : r0) if(std::find(common.begin(), common.end(), out) != common.end()) new_ring.push_back(out); @@ -386,7 +424,7 @@ int main(int argc, char *argv[]) while(!newly_spent.empty()) { - LOG_PRINT_L0("Secondary pass due to " << newly_spent.size() << " newly found spent outputs"); + GULPSF_PRINT("Secondary pass due to {} newly found spent outputs" , newly_spent.size()); std::unordered_set work_spent = std::move(newly_spent); newly_spent.clear(); @@ -408,7 +446,7 @@ int main(int argc, char *argv[]) if(known == absolute.size() - 1) { const crypto::public_key pkey = core_storage[0]->get_output_key(od.amount, last_unknown); - MINFO("Blackballing output " << pkey << ", due to being used in a " << absolute.size() << "-ring where all other outputs are known to be spent"); + GULPSF_INFO("Blackballing output {}, due to being used in a {}-ring where all other outputs are known to be spent", pkey, absolute.size()); ringdb.blackball(pkey); newly_spent.insert(output_data(od.amount, last_unknown)); spent.insert(output_data(od.amount, last_unknown)); @@ -417,8 +455,8 @@ int main(int argc, char *argv[]) } } - LOG_PRINT_L0("Blockchain blackball data exported OK"); + GULPS_PRINT("Blockchain blackball data exported OK"); return 0; - CATCH_ENTRY("Export error", 1); + GULPS_CATCH_ENTRY("Export error", 1); } diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index 0c79997f..eac5d795 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 "blockchain_db/blockchain_db.h" #include "blockchain_db/db_types.h" #include "blocksdat_file.h" @@ -25,12 +26,15 @@ #include "cryptonote_core/tx_pool.h" #include "version.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blockch_export"); namespace po = boost::program_options; using namespace epee; +gulps_log_level log_scr; + int main(int argc, char *argv[]) { #ifdef WIN32 @@ -43,7 +47,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -92,27 +96,61 @@ int main(int argc, char *argv[]) if(!r) return 1; - if(command_line::get_arg(vm, command_line::arg_help)) - { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; - return 0; - } + gulps::inst().set_thread_tag("BLOCKCH_EXPORT"); + + //Temp error output + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.lvl >= gulps::LEVEL_ERROR; }); + auto temp_handle = gulps::inst().add_output(std::move(out)); - mlog_configure(mlog_get_default_log_path("ryo-blockchain-export.log"), true); if(!command_line::is_arg_defaulted(vm, arg_log_level)) - mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); + { + if(!log_scr.parse_cat_string(command_line::get_arg(vm, arg_log_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, arg_log_level).c_str()); + return 1; + } + } else - mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); + { + if(!log_scr.parse_cat_string(std::to_string(log_level).c_str())) + { + GULPSF_ERROR("Failed to parse filter string {}", log_level); + return 1; + } + } + block_stop = command_line::get_arg(vm, arg_block_stop); - LOG_PRINT_L0("Starting..."); + gulps::inst().remove_output(temp_handle); + + if(log_scr.is_active()) + { + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(msg.out != gulps::OUT_LOG_0 && msg.out != gulps::OUT_USER_0) + return false; + if(printed) + return false; + return log_scr.match_msg(msg); + }); + gulps::inst().add_output(std::move(out)); + } + + if(command_line::get_arg(vm, command_line::arg_help)) + { + GULPSF_PRINT("Ryo '{}' ({})\n", RYO_RELEASE_NAME, RYO_VERSION_FULL); + GULPS_PRINT(desc_options); + return 0; + } + + GULPS_PRINT("Starting..."); bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); if(opt_testnet && opt_stagenet) { - std::cerr << "Can't specify more than one of --testnet and --stagenet" << std::endl; + GULPS_ERROR("Can't specify more than one of --testnet and --stagenet"); return 1; } bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat); @@ -124,7 +162,7 @@ int main(int argc, char *argv[]) std::string db_type = command_line::get_arg(vm, arg_database); if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cerr << "Invalid database type: " << db_type << std::endl; + GULPS_ERROR("Invalid database type: ", db_type); return 1; } @@ -132,7 +170,7 @@ int main(int argc, char *argv[]) output_file_path = boost::filesystem::path(command_line::get_arg(vm, arg_output_file)); else output_file_path = boost::filesystem::path(m_config_folder) / "export" / BLOCKCHAIN_RAW; - LOG_PRINT_L0("Export output file: " << output_file_path.string()); + GULPS_PRINT("Export output file: " , output_file_path.string()); // If we wanted to use the memory pool, we would set up a fake_core. @@ -145,7 +183,7 @@ int main(int argc, char *argv[]) // Blockchain* core_storage = new Blockchain(NULL); // because unlike blockchain_storage constructor, which takes a pointer to // tx_memory_pool, Blockchain's constructor takes tx_memory_pool object. - LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); + GULPS_PRINT("Initializing source blockchain (BlockchainDB)"); Blockchain *core_storage = NULL; tx_memory_pool m_mempool(*core_storage); core_storage = new Blockchain(m_mempool); @@ -153,30 +191,30 @@ int main(int argc, char *argv[]) BlockchainDB *db = new_db(db_type); if(db == NULL) { - LOG_ERROR("Attempted to use non-existent database type: " << db_type); + GULPS_ERROR("Attempted to use non-existent database type: ", db_type); throw std::runtime_error("Attempting to use non-existent database type"); } - LOG_PRINT_L0("database: " << db_type); + GULPS_PRINT("database: " , db_type); boost::filesystem::path folder(m_config_folder); folder /= db->get_db_name(); const std::string filename = folder.string(); - LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); + GULPSF_PRINT("Loading blockchain from folder {} ...", filename); try { db->open(filename, DBF_RDONLY); } catch(const std::exception &e) { - LOG_PRINT_L0("Error opening database: " << e.what()); + GULPS_ERROR("Error opening database: " , e.what()); return 1; } r = core_storage->init(db, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET); - CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); - LOG_PRINT_L0("Source blockchain storage initialized OK"); - LOG_PRINT_L0("Exporting blockchain raw data..."); + GULPS_CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); + GULPS_PRINT("Source blockchain storage initialized OK"); + GULPS_PRINT("Exporting blockchain raw data..."); if(opt_blocks_dat) { @@ -188,9 +226,9 @@ int main(int argc, char *argv[]) BootstrapFile bootstrap; r = bootstrap.store_blockchain_raw(core_storage, NULL, output_file_path, block_stop); } - CHECK_AND_ASSERT_MES(r, 1, "Failed to export blockchain raw data"); - LOG_PRINT_L0("Blockchain raw data exported OK"); + GULPS_CHECK_AND_ASSERT_MES(r, 1, "Failed to export blockchain raw data"); + GULPS_PRINT("Blockchain raw data exported OK"); return 0; - CATCH_ENTRY("Export error", 1); + GULPS_CATCH_ENTRY("Export error", 1); } diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 068de493..d8d11d3d 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 #include #include @@ -27,14 +28,14 @@ #include "cryptonote_basic/cryptonote_format_utils.h" #include "cryptonote_core/cryptonote_core.h" #include "include_base_utils.h" -#include "misc_log_ex.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blockch_import"); namespace { @@ -92,7 +93,7 @@ int parse_db_arguments(const std::string &db_arg_str, std::string &db_type, int } else if(db_args.size() > 2) { - std::cerr << "unrecognized database argument format: " << db_arg_str << ENDL; + GULPS_ERROR( "unrecognized database argument format: " , db_arg_str ); return 1; } @@ -168,8 +169,8 @@ int check_flush(cryptonote::core &core, std::list &blocks, cryptonote::block block; if(!parse_and_validate_block_from_blob(b.block, block)) { - MERROR("Failed to parse block: " - << epee::string_tools::pod_to_hex(get_blob_hash(b.block))); + GULPS_ERROR("Failed to parse block: ", + epee::string_tools::pod_to_hex(get_blob_hash(b.block))); core.cleanup_handle_incoming_blocks(); return 1; } @@ -188,8 +189,8 @@ int check_flush(cryptonote::core &core, std::list &blocks, core.handle_incoming_tx(tx_blob, tvc, true, true, false); if(tvc.m_verifivation_failed) { - MERROR("transaction verification failed, tx_id = " - << epee::string_tools::pod_to_hex(get_blob_hash(tx_blob))); + GULPS_ERROR("transaction verification failed, tx_id = ", + epee::string_tools::pod_to_hex(get_blob_hash(tx_blob))); core.cleanup_handle_incoming_blocks(); return 1; } @@ -203,14 +204,14 @@ int check_flush(cryptonote::core &core, std::list &blocks, if(bvc.m_verifivation_failed) { - MERROR("Block verification failed, id = " - << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))); + GULPS_ERROR("Block verification failed, id = ", + epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))); core.cleanup_handle_incoming_blocks(); return 1; } if(bvc.m_marked_as_orphaned) { - MERROR("Block received at sync phase was marked as orphaned"); + GULPS_ERROR("Block received at sync phase was marked as orphaned"); core.cleanup_handle_incoming_blocks(); return 1; } @@ -234,7 +235,7 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path boost::system::error_code ec; if(!boost::filesystem::exists(fs_import_file_path, ec)) { - MFATAL("bootstrap file not found: " << fs_import_file_path); + GULPS_ERROR("bootstrap file not found: ", fs_import_file_path); return false; } @@ -247,16 +248,14 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path std::streampos pos; // BootstrapFile bootstrap(import_file_path); uint64_t total_source_blocks = bootstrap.count_blocks(import_file_path, pos, seek_height); - MINFO("bootstrap file last block number: " << total_source_blocks - 1 << " (zero-based height) total blocks: " << total_source_blocks); + GULPSF_INFO("bootstrap file last block number: {} (zero-based height) total blocks:{}", std::to_string(total_source_blocks - 1), std::to_string(total_source_blocks)); if(total_source_blocks - 1 <= start_height) { return false; } - std::cout << ENDL; - std::cout << "Preparing to read blocks..." << ENDL; - std::cout << ENDL; + GULPS_PRINT( "\nPreparing to read blocks...\n" ); std::ifstream import_file; import_file.open(import_file_path, std::ios_base::binary | std::ifstream::in); @@ -265,7 +264,7 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path uint64_t num_imported = 0; if(import_file.fail()) { - MFATAL("import_file.open() fail"); + GULPS_ERROR("import_file.open() fail"); return false; } @@ -290,12 +289,11 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path // These are what we'll try to use, and they don't have to be a determination // from source and destination blockchains, but those are the defaults. - MINFO("start block: " << start_height << " stop block: " << block_stop); + GULPS_INFO("start block: {} stop block: {}" , std::to_string(start_height), std::to_string(block_stop)); bool use_batch = opt_batch && !opt_verify; - MINFO("Reading blockchain from bootstrap file..."); - std::cout << ENDL; + GULPS_INFO("Reading blockchain from bootstrap file...\n"); std::list blocks; @@ -330,8 +328,8 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path // TODO: bootstrap.read_chunk(); if(!import_file) { - std::cout << refresh_string; - MINFO("End of file reached"); + GULPS_PRINT( refresh_string); + GULPS_INFO("End of file reached"); quit = 1; break; } @@ -342,20 +340,20 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path { throw std::runtime_error("Error in deserialization of chunk size"); } - MDEBUG("chunk_size: " << chunk_size); + GULPSF_LOG_L1("chunk_size: {}" , chunk_size); if(chunk_size > BUFFER_SIZE) { - MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE); + GULPSF_WARN("WARNING: chunk_size {} > BUFFER_SIZE {}", chunk_size, BUFFER_SIZE); throw std::runtime_error("Aborting: chunk size exceeds buffer size"); } if(chunk_size > CHUNK_SIZE_WARNING_THRESHOLD) { - MINFO("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD); + GULPSF_INFO("NOTE: chunk_size {} > {}", chunk_size, CHUNK_SIZE_WARNING_THRESHOLD); } else if(chunk_size == 0) { - MFATAL("ERROR: chunk_size == 0"); + GULPS_ERROR("ERROR: chunk_size == 0"); return 2; } import_file.read(buffer_block, chunk_size); @@ -363,28 +361,25 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path { if(import_file.eof()) { - std::cout << refresh_string; - MINFO("End of file reached - file was truncated"); + GULPS_PRINT( refresh_string); + GULPS_INFO("End of file reached - file was truncated"); quit = 1; break; } else { - MFATAL("ERROR: unexpected end of file: bytes read before error: " - << import_file.gcount() << " of chunk_size " << chunk_size); + GULPSF_ERROR("ERROR: unexpected end of file: bytes read before error: {} of chunk_size {}", + import_file.gcount(), chunk_size); return 2; } } bytes_read += chunk_size; - MDEBUG("Total bytes read: " << bytes_read); + GULPSF_LOG_L1("Total bytes read: {}" , bytes_read); if(h > block_stop) { - std::cout << refresh_string << "block " << h - 1 - << " / " << block_stop - << std::flush; - std::cout << ENDL << ENDL; - MINFO("Specified block number reached - stopping. block: " << h - 1 << " total blocks: " << h); + GULPSF_PRINT(refresh_string, "block {} / {}\n\n", h - 1, block_stop); + GULPSF_INFO("Specified block number reached - stopping. block: {} total blocks: {}", h - 1, h); quit = 1; break; } @@ -404,21 +399,19 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path ++h; if((h - 1) % display_interval == 0) { - std::cout << refresh_string; - MDEBUG("loading block number " << h - 1); + GULPS_PRINT( refresh_string); + GULPSF_LOG_L1("loading block number {}" , h - 1); } else { - MDEBUG("loading block number " << h - 1); + GULPSF_LOG_L1("loading block number {}" , h - 1); } b = bp.block; - MDEBUG("block prev_id: " << b.prev_id << ENDL); + GULPSF_LOG_L1("block prev_id: {}", b.prev_id); if((h - 1) % progress_interval == 0) { - std::cout << refresh_string << "block " << h - 1 - << " / " << block_stop - << std::flush; + GULPSF_PRINT("{}block {} / {}\r", refresh_string, h - 1, block_stop); } if(opt_verify) @@ -475,8 +468,8 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path } catch(const std::exception &e) { - std::cout << refresh_string; - MFATAL("Error adding block to blockchain: " << e.what()); + GULPS_PRINT( refresh_string); + GULPS_ERROR("Error adding block to blockchain: ", e.what()); quit = 2; // make sure we don't commit partial block data break; } @@ -487,15 +480,15 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path { uint64_t bytes, h2; bool q2; - std::cout << refresh_string; + GULPS_PRINT( refresh_string); // zero-based height - std::cout << ENDL << "[- batch commit at height " << h - 1 << " -]" << ENDL; + GULPSF_PRINT("\n[- batch commit at height {} -]\n", h - 1); core.get_blockchain_storage().get_db().batch_stop(); pos = import_file.tellg(); bytes = bootstrap.count_bytes(import_file, db_batch_size, h2, q2); import_file.seekg(pos); core.get_blockchain_storage().get_db().batch_start(db_batch_size, bytes); - std::cout << ENDL; + GULPS_PRINT( "\n"); core.get_blockchain_storage().get_db().show_stats(); } } @@ -505,8 +498,8 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path } catch(const std::exception &e) { - std::cout << refresh_string; - MFATAL("exception while reading from file, height=" << h << ": " << e.what()); + GULPS_PRINT( refresh_string); + GULPSF_ERROR("exception while reading from file, height={}: {}", h, e.what()); return 2; } } // while @@ -535,15 +528,17 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path } core.get_blockchain_storage().get_db().show_stats(); - MINFO("Number of blocks imported: " << num_imported); + GULPSF_INFO("Number of blocks imported: {}" , num_imported); if(h > 0) // TODO: if there was an error, the last added block is probably at zero-based height h-2 - MINFO("Finished at block: " << h - 1 << " total blocks: " << h); + GULPSF_INFO("Finished at block: {} total blocks: {}", h - 1, h); - std::cout << ENDL; + GULPS_PRINT( "\n"); return 0; } +gulps_log_level log_scr; + int main(int argc, char *argv[]) { #ifdef WIN32 @@ -556,7 +551,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -628,21 +623,63 @@ int main(int argc, char *argv[]) block_stop = command_line::get_arg(vm, arg_block_stop); db_batch_size = command_line::get_arg(vm, arg_batch_size); + m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); + db_arg_str = command_line::get_arg(vm, arg_database); + + gulps::inst().set_thread_tag("BLOCKCH_IMPORT"); + + //Temp error output + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.lvl >= gulps::LEVEL_ERROR; }); + auto temp_handle = gulps::inst().add_output(std::move(out)); + + if(!command_line::is_arg_defaulted(vm, arg_log_level)) + { + if(!log_scr.parse_cat_string(command_line::get_arg(vm, arg_log_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, arg_log_level).c_str()); + return 1; + } + } + else + { + if(!log_scr.parse_cat_string(std::to_string(log_level).c_str())) + { + GULPSF_ERROR("Failed to parse filter string {}", log_level); + return 1; + } + } + + gulps::inst().remove_output(temp_handle); + + if(log_scr.is_active()) + { + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(msg.out != gulps::OUT_LOG_0 && msg.out != gulps::OUT_USER_0) + return false; + if(printed) + return false; + return log_scr.match_msg(msg); + }); + gulps::inst().add_output(std::move(out)); + } + if(command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; + GULPS_PRINT("Ryo '", RYO_RELEASE_NAME, "' (", RYO_VERSION_FULL, ")\n\n"); + GULPS_PRINT( desc_options ); return 0; } if(!opt_batch && !command_line::is_arg_defaulted(vm, arg_batch_size)) { - std::cerr << "Error: batch-size set, but batch option not enabled" << ENDL; + GULPS_ERROR( "Error: batch-size set, but batch option not enabled" ); return 1; } if(!db_batch_size) { - std::cerr << "Error: batch-size must be > 0" << ENDL; + GULPS_ERROR( "Error: batch-size must be > 0" ); return 1; } if(opt_verify && command_line::is_arg_defaulted(vm, arg_batch_size)) @@ -657,24 +694,15 @@ int main(int argc, char *argv[]) db_batch_size = db_batch_size_verify; } } - opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); if(opt_testnet && opt_stagenet) { - std::cerr << "Error: Can't specify more than one of --testnet and --stagenet" << ENDL; + GULPS_ERROR( "Error: Can't specify more than one of --testnet and --stagenet" ); return 1; } - m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); - db_arg_str = command_line::get_arg(vm, arg_database); - - mlog_configure(mlog_get_default_log_path("ryo-blockchain-import.log"), true); - if(!command_line::is_arg_defaulted(vm, arg_log_level)) - mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); - else - mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); - MINFO("Starting..."); + GULPS_INFO("Starting..."); boost::filesystem::path fs_import_file_path; @@ -698,33 +726,32 @@ int main(int argc, char *argv[]) res = parse_db_arguments(db_arg_str, db_type, db_flags); if(res) { - std::cerr << "Error parsing database argument(s)" << ENDL; + GULPS_ERROR( "Error parsing database argument(s)" ); return 1; } if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cerr << "Invalid database type: " << db_type << std::endl; + GULPS_ERROR( "Invalid database type: " , db_type ); return 1; } - MINFO("database: " << db_type); - MINFO("database flags: " << db_flags); - MINFO("verify: " << std::boolalpha << opt_verify << std::noboolalpha); + GULPS_INFO("database: " , db_type); + GULPSF_INFO("database flags: {}" , db_flags); + GULPS_INFO("verify: " , std::boolalpha , opt_verify , std::noboolalpha); if(opt_batch) { - MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha - << " batch size: " << db_batch_size); + GULPS_INFO("batch: ", std::boolalpha, opt_batch, std::noboolalpha, " batch size: ", db_batch_size); } else { - MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha); + GULPS_INFO("batch: " , std::boolalpha , opt_batch , std::noboolalpha); } - MINFO("resume: " << std::boolalpha << opt_resume << std::noboolalpha); - MINFO("nettype: " << (opt_testnet ? "testnet" : opt_stagenet ? "stagenet" : "mainnet")); + GULPS_INFO("resume: " , std::boolalpha , opt_resume , std::noboolalpha); + GULPS_INFO("nettype: ", (opt_testnet ? "testnet" : opt_stagenet ? "stagenet" : "mainnet")); - MINFO("bootstrap file path: " << import_file_path); - MINFO("database path: " << m_config_folder); + GULPS_INFO("bootstrap file path: " , import_file_path); + GULPS_INFO("database path: " , m_config_folder); cryptonote::cryptonote_protocol_stub pr; //TODO: stub only for this kind of test, make real validation of relayed objects cryptonote::core core(&pr); @@ -735,7 +762,7 @@ int main(int argc, char *argv[]) core.disable_dns_checkpoints(true); if(!core.init(vm, NULL)) { - std::cerr << "Failed to initialize core" << ENDL; + GULPS_ERROR( "Failed to initialize core" ); return 1; } core.get_blockchain_storage().get_db().set_batch_transactions(true); @@ -743,15 +770,15 @@ int main(int argc, char *argv[]) if(!command_line::is_arg_defaulted(vm, arg_pop_blocks)) { num_blocks = command_line::get_arg(vm, arg_pop_blocks); - MINFO("height: " << core.get_blockchain_storage().get_current_blockchain_height()); + GULPSF_INFO("height: {}" , core.get_blockchain_storage().get_current_blockchain_height()); pop_blocks(core, num_blocks); - MINFO("height: " << core.get_blockchain_storage().get_current_blockchain_height()); + GULPSF_INFO("height: {}" , core.get_blockchain_storage().get_current_blockchain_height()); return 0; } if(!command_line::is_arg_defaulted(vm, arg_drop_hf)) { - MINFO("Dropping hard fork tables..."); + GULPS_INFO("Dropping hard fork tables..."); core.get_blockchain_storage().get_db().drop_hard_fork_info(); core.deinit(); return 0; @@ -767,12 +794,12 @@ int main(int argc, char *argv[]) } catch(const DB_ERROR &e) { - std::cout << std::string("Error loading blockchain db: ") + e.what() + " -- shutting down now" << ENDL; + GULPS_PRINT("Error loading blockchain db: ", e.what(), " -- shutting down now" ); core.deinit(); return 1; } return 0; - CATCH_ENTRY("Import error", 1); + GULPS_CATCH_ENTRY("Import error", 1); } diff --git a/src/blockchain_utilities/blockchain_usage.cpp b/src/blockchain_utilities/blockchain_usage.cpp index 55090996..73cc8a3a 100644 --- a/src/blockchain_utilities/blockchain_usage.cpp +++ b/src/blockchain_utilities/blockchain_usage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -27,8 +27,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blockch_usage"); namespace po = boost::program_options; using namespace epee; @@ -71,6 +72,8 @@ struct reference reference(uint64_t h, uint64_t rs, uint64_t p) : height(h), ring_size(rs), position(p) {} }; +gulps_log_level log_scr; + int main(int argc, char *argv[]) { #ifdef WIN32 @@ -83,7 +86,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -130,20 +133,53 @@ int main(int argc, char *argv[]) if(!r) return 1; + gulps::inst().set_thread_tag("BLOCKCH_USAGE"); + + //Temp error output + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.lvl >= gulps::LEVEL_ERROR; }); + auto temp_handle = gulps::inst().add_output(std::move(out)); + + if(!command_line::is_arg_defaulted(vm, arg_log_level)) + { + if(!log_scr.parse_cat_string(command_line::get_arg(vm, arg_log_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, arg_log_level).c_str()); + return 1; + } + } + else + { + if(!log_scr.parse_cat_string(std::to_string(log_level).c_str())) + { + GULPSF_ERROR("Failed to parse filter string {}", log_level); + return 1; + } + } + + gulps::inst().remove_output(temp_handle); + + if(log_scr.is_active()) + { + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(msg.out != gulps::OUT_LOG_0 && msg.out != gulps::OUT_USER_0) + return false; + if(printed) + return false; + return log_scr.match_msg(msg); + }); + gulps::inst().add_output(std::move(out)); + } + if(command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; + GULPS_PRINT("Ryo '", RYO_RELEASE_NAME, "' (", RYO_VERSION_FULL, ")"); + GULPS_PRINT(desc_options); return 0; } - mlog_configure(mlog_get_default_log_path("ryo-blockchain-usage.log"), true); - if(!command_line::is_arg_defaulted(vm, arg_log_level)) - mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str()); - else - mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str()); - - LOG_PRINT_L0("Starting..."); + GULPS_PRINT("Starting..."); bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on); bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); @@ -153,7 +189,7 @@ int main(int argc, char *argv[]) std::string db_type = command_line::get_arg(vm, arg_database); if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cerr << "Invalid database type: " << db_type << std::endl; + GULPS_ERROR("Invalid database type: ", db_type); return 1; } @@ -168,7 +204,7 @@ int main(int argc, char *argv[]) // Blockchain* core_storage = new Blockchain(NULL); // because unlike blockchain_storage constructor, which takes a pointer to // tx_memory_pool, Blockchain's constructor takes tx_memory_pool object. - LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)"); + GULPS_PRINT("Initializing source blockchain (BlockchainDB)"); const std::string input = command_line::get_arg(vm, arg_input); std::unique_ptr core_storage; tx_memory_pool m_mempool(*core_storage); @@ -176,13 +212,13 @@ int main(int argc, char *argv[]) BlockchainDB *db = new_db(db_type); if(db == NULL) { - LOG_ERROR("Attempted to use non-existent database type: " << db_type); + GULPS_LOG_ERROR("Attempted to use non-existent database type: ", db_type); throw std::runtime_error("Attempting to use non-existent database type"); } - LOG_PRINT_L0("database: " << db_type); + GULPS_PRINT("database: " , db_type); const std::string filename = input; - LOG_PRINT_L0("Loading blockchain from folder " << filename << " ..."); + GULPS_PRINT("Loading blockchain from folder " , filename , " ..."); try { @@ -190,21 +226,21 @@ int main(int argc, char *argv[]) } catch(const std::exception &e) { - LOG_PRINT_L0("Error opening database: " << e.what()); + GULPS_ERROR("Error opening database: " , e.what()); return 1; } r = core_storage->init(db, net_type); - CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); - LOG_PRINT_L0("Source blockchain storage initialized OK"); + GULPS_CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage"); + GULPS_PRINT("Source blockchain storage initialized OK"); - LOG_PRINT_L0("Building usage patterns..."); + GULPS_PRINT("Building usage patterns..."); size_t done = 0; std::unordered_map> outputs; std::unordered_map indices; - LOG_PRINT_L0("Reading blockchain from " << input); + GULPS_PRINT("Reading blockchain from " , input); core_storage->for_all_transactions([&](const crypto::hash &hash, const cryptonote::transaction &tx) -> bool { const bool coinbase = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen); const uint64_t height = core_storage->get_db().get_tx_block_height(hash); @@ -248,11 +284,11 @@ int main(int argc, char *argv[]) for(const auto &c : counts) { float percent = 100.f * c.second / total; - MINFO(std::to_string(c.second) << " outputs used " << c.first << " times (" << percent << "%)"); + GULPSF_INFO("{} outputs used {} times ({}%)", c.second, c.first, percent); } - LOG_PRINT_L0("Blockchain usage exported OK"); + GULPS_PRINT("Blockchain usage exported OK"); return 0; - CATCH_ENTRY("Export error", 1); + GULPS_CATCH_ENTRY("Export error", 1); } diff --git a/src/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index 37bea5e9..2f44930b 100644 --- a/src/blockchain_utilities/blockchain_utilities.h +++ b/src/blockchain_utilities/blockchain_utilities.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blockchain_utilities/blocksdat_file.cpp b/src/blockchain_utilities/blocksdat_file.cpp index 98d2dbd7..e5a3b3f4 100644 --- a/src/blockchain_utilities/blocksdat_file.cpp +++ b/src/blockchain_utilities/blocksdat_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,8 +18,9 @@ #include "blocksdat_file.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blocksdat_file"); namespace po = boost::program_options; @@ -40,7 +41,7 @@ bool BlocksdatFile::open_writer(const boost::filesystem::path &file_path, uint64 { if(!boost::filesystem::is_directory(dir_path)) { - MFATAL("export directory path is a file: " << dir_path); + GULPS_ERROR("export directory path is a file: " , dir_path); return false; } } @@ -48,7 +49,7 @@ bool BlocksdatFile::open_writer(const boost::filesystem::path &file_path, uint64 { if(!boost::filesystem::create_directory(dir_path)) { - MFATAL("Failed to create directory " << dir_path); + GULPS_ERROR("Failed to create directory " , dir_path); return false; } } @@ -56,7 +57,7 @@ bool BlocksdatFile::open_writer(const boost::filesystem::path &file_path, uint64 m_raw_data_file = new std::ofstream(); - MINFO("creating file"); + GULPS_INFO("creating file"); m_raw_data_file->open(file_path.string(), std::ios_base::binary | std::ios_base::out | std::ios::trunc); if(m_raw_data_file->fail()) @@ -119,21 +120,21 @@ bool BlocksdatFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem uint64_t block_start = 0; uint64_t block_stop = 0; - MINFO("source blockchain height: " << m_blockchain_storage->get_current_blockchain_height() - 1); + GULPSF_INFO("source blockchain height: {}", m_blockchain_storage->get_current_blockchain_height() - 1); if((requested_block_stop > 0) && (requested_block_stop < m_blockchain_storage->get_current_blockchain_height())) { - MINFO("Using requested block height: " << requested_block_stop); + GULPSF_INFO("Using requested block height: {}" , requested_block_stop); block_stop = requested_block_stop; } else { block_stop = m_blockchain_storage->get_current_blockchain_height() - 1; - MINFO("Using block height of source blockchain: " << block_stop); + GULPSF_INFO("Using block height of source blockchain: {}" , block_stop); } - MINFO("Storing blocks raw data..."); + GULPS_INFO("Storing blocks raw data..."); if(!BlocksdatFile::open_writer(output_file, block_stop)) { - MFATAL("failed to open raw file for write"); + GULPS_ERROR("failed to open raw file for write"); return false; } for(m_cur_height = block_start; m_cur_height <= block_stop; ++m_cur_height) @@ -147,15 +148,15 @@ bool BlocksdatFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem } if(m_cur_height % progress_interval == 0) { - std::cout << refresh_string; - std::cout << "block " << m_cur_height << "/" << block_stop << std::flush; + GULPS_PRINT( refresh_string); + GULPSF_PRINT("block {}/{}", m_cur_height, block_stop); } } // print message for last block, which may not have been printed yet due to progress_interval - std::cout << refresh_string; - std::cout << "block " << m_cur_height - 1 << "/" << block_stop << ENDL; + GULPS_PRINT( refresh_string); + GULPSF_PRINT("block {}/{}", m_cur_height - 1, block_stop); - MINFO("Number of blocks exported: " << num_blocks_written); + GULPSF_INFO("Number of blocks exported: {}" , num_blocks_written); return BlocksdatFile::close(); } diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h index 770063b0..d71e0e33 100644 --- a/src/blockchain_utilities/blocksdat_file.h +++ b/src/blockchain_utilities/blocksdat_file.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index 07ae5ec1..93aeb0e4 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -22,8 +22,9 @@ #include "bootstrap_file.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("bootstr_file"); namespace po = boost::program_options; @@ -49,7 +50,7 @@ bool BootstrapFile::open_writer(const boost::filesystem::path &file_path) { if(!boost::filesystem::is_directory(dir_path)) { - MFATAL("export directory path is a file: " << dir_path); + GULPS_ERROR("export directory path is a file: " , dir_path); return false; } } @@ -57,7 +58,7 @@ bool BootstrapFile::open_writer(const boost::filesystem::path &file_path) { if(!boost::filesystem::create_directory(dir_path)) { - MFATAL("Failed to create directory " << dir_path); + GULPS_ERROR("Failed to create directory " , dir_path); return false; } } @@ -70,14 +71,14 @@ bool BootstrapFile::open_writer(const boost::filesystem::path &file_path) if(!boost::filesystem::exists(file_path)) { - MDEBUG("creating file"); + GULPS_LOG_L1("creating file"); do_initialize_file = true; num_blocks = 0; } else { num_blocks = count_blocks(file_path.string()); - MDEBUG("appending to existing file with height: " << num_blocks - 1 << " total blocks: " << num_blocks); + GULPSF_LOG_L1("appending to existing file with height: {} total blocks: {}", num_blocks - 1, num_blocks); } m_height = num_blocks; @@ -126,7 +127,7 @@ bool BootstrapFile::initialize_file() uint32_t bd_size = 0; blobdata bd = t_serializable_object_to_blob(bfi); - MDEBUG("bootstrap::file_info size: " << bd.size()); + GULPSF_LOG_L1("bootstrap::file_info size: {}", bd.size()); bd_size = bd.size(); if(!::serialization::dump_binary(bd_size, blob)) @@ -137,7 +138,7 @@ bool BootstrapFile::initialize_file() output_stream_header << bd; bd = t_serializable_object_to_blob(bbi); - MDEBUG("bootstrap::blocks_info size: " << bd.size()); + GULPSF_LOG_L1("bootstrap::blocks_info size: {}", bd.size()); bd_size = bd.size(); if(!::serialization::dump_binary(bd_size, blob)) @@ -163,7 +164,7 @@ void BootstrapFile::flush_chunk() // MTRACE("chunk_size " << chunk_size); if(chunk_size > BUFFER_SIZE) { - MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE); + GULPSF_WARN("WARNING: chunk_size {} > BUFFER_SIZE {}", chunk_size, BUFFER_SIZE); } std::string blob; @@ -184,14 +185,14 @@ void BootstrapFile::flush_chunk() long num_chars_written = pos_after - pos_before; if(static_cast(num_chars_written) != chunk_size) { - MFATAL("Error writing chunk: height: " << m_cur_height << " chunk_size: " << chunk_size << " num chars written: " << num_chars_written); + GULPSF_ERROR("Error writing chunk: height: {} chunk_size: {} num chars written: {}", m_cur_height, chunk_size, num_chars_written); throw std::runtime_error("Error writing chunk"); } m_buffer.clear(); delete m_output_stream; m_output_stream = new boost::iostreams::stream>(m_buffer); - MDEBUG("flushed chunk: chunk_size: " << chunk_size); + GULPSF_LOG_L1("flushed chunk: chunk_size: {}", chunk_size); } void BootstrapFile::write_block(block &block) @@ -253,10 +254,10 @@ bool BootstrapFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem m_blockchain_storage = _blockchain_storage; m_tx_pool = _tx_pool; uint64_t progress_interval = 100; - MINFO("Storing blocks raw data..."); + GULPS_INFO("Storing blocks raw data..."); if(!BootstrapFile::open_writer(output_file)) { - MFATAL("failed to open raw file for write"); + GULPS_ERROR("failed to open raw file for write"); return false; } block b; @@ -266,16 +267,16 @@ bool BootstrapFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem // height. uint64_t block_start = m_height; uint64_t block_stop = 0; - MINFO("source blockchain height: " << m_blockchain_storage->get_current_blockchain_height() - 1); + GULPSF_INFO("source blockchain height: {}", m_blockchain_storage->get_current_blockchain_height() - 1); if((requested_block_stop > 0) && (requested_block_stop < m_blockchain_storage->get_current_blockchain_height())) { - MINFO("Using requested block height: " << requested_block_stop); + GULPSF_INFO("Using requested block height: {}", requested_block_stop); block_stop = requested_block_stop; } else { block_stop = m_blockchain_storage->get_current_blockchain_height() - 1; - MINFO("Using block height of source blockchain: " << block_stop); + GULPSF_INFO("Using block height of source blockchain: {}", block_stop); } for(m_cur_height = block_start; m_cur_height <= block_stop; ++m_cur_height) { @@ -290,8 +291,8 @@ bool BootstrapFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem } if(m_cur_height % progress_interval == 0) { - std::cout << refresh_string; - std::cout << "block " << m_cur_height << "/" << block_stop << std::flush; + GULPS_PRINT(refresh_string); + GULPSF_PRINT("block {}/{}\r", m_cur_height, block_stop ); } } // NOTE: use of NUM_BLOCKS_PER_CHUNK is a placeholder in case multi-block chunks are later supported. @@ -300,12 +301,12 @@ bool BootstrapFile::store_blockchain_raw(Blockchain *_blockchain_storage, tx_mem flush_chunk(); } // print message for last block, which may not have been printed yet due to progress_interval - std::cout << refresh_string; - std::cout << "block " << m_cur_height - 1 << "/" << block_stop << ENDL; + GULPS_PRINT( refresh_string); + GULPSF_PRINT( "block {}/{}" , m_cur_height - 1, block_stop ); - MINFO("Number of blocks exported: " << num_blocks_written); + GULPSF_INFO("Number of blocks exported: {}", num_blocks_written); if(num_blocks_written > 0) - MINFO("Largest chunk: " << m_max_chunk << " bytes"); + GULPSF_INFO("Largest chunk: {} bytes", m_max_chunk); return BootstrapFile::close(); } @@ -326,11 +327,11 @@ uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream &import_file) if(file_magic != blockchain_raw_magic) { - MFATAL("bootstrap file not recognized"); + GULPS_ERROR("bootstrap file not recognized"); throw std::runtime_error("Aborting"); } else - MINFO("bootstrap file recognized"); + GULPS_INFO("bootstrap file recognized"); uint32_t buflen_file_info; @@ -340,7 +341,7 @@ uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream &import_file) throw std::runtime_error("Error reading expected number of bytes"); if(!::serialization::parse_binary(str1, buflen_file_info)) throw std::runtime_error("Error in deserialization of buflen_file_info"); - MINFO("bootstrap::file_info size: " << buflen_file_info); + GULPSF_INFO("bootstrap::file_info size: {}", buflen_file_info); if(buflen_file_info > sizeof(buf1)) throw std::runtime_error("Error: bootstrap::file_info size exceeds buffer size"); @@ -351,9 +352,9 @@ uint64_t BootstrapFile::seek_to_first_chunk(std::ifstream &import_file) bootstrap::file_info bfi; if(!::serialization::parse_binary(str1, bfi)) throw std::runtime_error("Error in deserialization of bootstrap::file_info"); - MINFO("bootstrap file v" << unsigned(bfi.major_version) << "." << unsigned(bfi.minor_version)); - MINFO("bootstrap magic size: " << sizeof(file_magic)); - MINFO("bootstrap header size: " << bfi.header_size); + GULPSF_INFO("bootstrap file v {}.{}", unsigned(bfi.major_version), unsigned(bfi.minor_version)); + GULPSF_INFO("bootstrap magic size: {}", sizeof(file_magic)); + GULPSF_INFO("bootstrap header size: {}", bfi.header_size); uint64_t full_header_size = sizeof(file_magic) + bfi.header_size; import_file.seekg(full_header_size); @@ -373,8 +374,8 @@ uint64_t BootstrapFile::count_bytes(std::ifstream &import_file, uint64_t blocks, import_file.read(buf1, sizeof(chunk_size)); if(!import_file) { - std::cout << refresh_string; - MDEBUG("End of file reached"); + GULPS_PRINT( refresh_string); + GULPS_LOG_L1("End of file reached"); quit = true; break; } @@ -382,35 +383,31 @@ uint64_t BootstrapFile::count_bytes(std::ifstream &import_file, uint64_t blocks, str1.assign(buf1, sizeof(chunk_size)); if(!::serialization::parse_binary(str1, chunk_size)) throw std::runtime_error("Error in deserialization of chunk_size"); - MDEBUG("chunk_size: " << chunk_size); + GULPSF_LOG_L1("chunk_size: {}", chunk_size); if(chunk_size > BUFFER_SIZE) { - std::cout << refresh_string; - MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE - << " height: " << h - 1); + GULPS_PRINT( refresh_string); + GULPSF_WARN("WARNING: chunk_size {} > BUFFER_SIZE {} height: {}", chunk_size, BUFFER_SIZE, h - 1); throw std::runtime_error("Aborting: chunk size exceeds buffer size"); } if(chunk_size > CHUNK_SIZE_WARNING_THRESHOLD) { - std::cout << refresh_string; - MDEBUG("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD << " << height: " - << h - 1); + GULPS_PRINT( refresh_string); + GULPSF_LOG_L1("NOTE: chunk_size {} > {} << height: {}", chunk_size, CHUNK_SIZE_WARNING_THRESHOLD, h - 1); } else if(chunk_size <= 0) { - std::cout << refresh_string; - MDEBUG("ERROR: chunk_size " << chunk_size << " <= 0" - << " height: " << h - 1); + GULPS_PRINT( refresh_string); + GULPSF_LOG_L1("ERROR: chunk_size {} <= 0 height: {}", chunk_size, h - 1); throw std::runtime_error("Aborting"); } // skip to next expected block size value import_file.seekg(chunk_size, std::ios_base::cur); if(!import_file) { - std::cout << refresh_string; - MFATAL("ERROR: unexpected end of file: bytes read before error: " - << import_file.gcount() << " of chunk_size " << chunk_size); + GULPS_PRINT( refresh_string); + GULPSF_ERROR("ERROR: unexpected end of file: bytes read before error: {} of chunk_size {}", import_file.gcount(), chunk_size); throw std::runtime_error("Aborting"); } bytes_read += chunk_size; @@ -437,7 +434,7 @@ uint64_t BootstrapFile::count_blocks(const std::string &import_file_path, std::s boost::system::error_code ec; if(!boost::filesystem::exists(raw_file_path, ec)) { - MFATAL("bootstrap file not found: " << raw_file_path); + GULPS_ERROR("bootstrap file not found: " , raw_file_path); throw std::runtime_error("Aborting"); } std::ifstream import_file; @@ -447,14 +444,14 @@ uint64_t BootstrapFile::count_blocks(const std::string &import_file_path, std::s uint64_t h = 0; if(import_file.fail()) { - MFATAL("import_file.open() fail"); + GULPS_ERROR("import_file.open() fail"); throw std::runtime_error("Aborting"); } uint64_t full_header_size; // 4 byte magic + length of header structures full_header_size = seek_to_first_chunk(import_file); - MINFO("Scanning blockchain from bootstrap file..."); + GULPS_INFO("Scanning blockchain from bootstrap file..."); bool quit = false; uint64_t bytes_read = 0, blocks; int progress_interval = 10; @@ -469,22 +466,21 @@ uint64_t BootstrapFile::count_blocks(const std::string &import_file_path, std::s } bytes_read += count_bytes(import_file, progress_interval, blocks, quit); h += blocks; - std::cout << "\r" - << "block height: " << h - 1 << " " << std::flush; + GULPSF_PRINT("\rblock height: {} \r", h - 1); - // std::cout << refresh_string; - MDEBUG("Number bytes scanned: " << bytes_read); + // GULPS_PRINT( refresh_string); + GULPSF_LOG_L1("Number bytes scanned: {}", bytes_read); } import_file.close(); - std::cout << ENDL; - std::cout << "Done scanning bootstrap file" << ENDL; - std::cout << "Full header length: " << full_header_size << " bytes" << ENDL; - std::cout << "Scanned for blocks: " << bytes_read << " bytes" << ENDL; - std::cout << "Total: " << full_header_size + bytes_read << " bytes" << ENDL; - std::cout << "Number of blocks: " << h << ENDL; - std::cout << ENDL; + GULPS_PRINT( "\n"); + GULPS_PRINT( "Done scanning bootstrap file"); + GULPSF_PRINT( "Full header length: {} bytes", full_header_size); + GULPSF_PRINT( "Scanned for blocks: {} bytes", bytes_read); + GULPSF_PRINT( "Total: {} bytes", full_header_size + bytes_read); + GULPSF_PRINT("Number of blocks: {}", h); + GULPS_PRINT( "\n"); // NOTE: h is the number of blocks. // Note that a block's stored height is zero-based, but parts of the code use diff --git a/src/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h index fb6aca27..938fe30e 100644 --- a/src/blockchain_utilities/bootstrap_file.h +++ b/src/blockchain_utilities/bootstrap_file.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blockchain_utilities/bootstrap_serialization.h b/src/blockchain_utilities/bootstrap_serialization.h index 7c6d0c5a..cf33c486 100644 --- a/src/blockchain_utilities/bootstrap_serialization.h +++ b/src/blockchain_utilities/bootstrap_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt index 69e60894..7e3314c2 100644 --- a/src/blocks/CMakeLists.txt +++ b/src/blocks/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt index b8be9bf6..c35bd529 100644 --- a/src/checkpoints/CMakeLists.txt +++ b/src/checkpoints/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -72,5 +72,6 @@ target_link_libraries(checkpoints ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index 007e4e8a..b1713018 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,8 +20,6 @@ #include "include_base_utils.h" -using namespace epee; - #include "checkpoints.h" #include "common/dns_utils.h" @@ -30,8 +28,9 @@ using namespace epee; #include "storages/portable_storage_template_helper.h" // epee json include #include "string_tools.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "checkpoints" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("checkpoints"); namespace cryptonote { @@ -42,7 +41,7 @@ struct t_hashline { uint64_t height; //!< the height of the checkpoint std::string hash; //!< the hash for the checkpoint - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(t_hashline) KV_SERIALIZE(height) KV_SERIALIZE(hash) END_KV_SERIALIZE_MAP() @@ -54,7 +53,7 @@ struct t_hashline struct t_hash_json { std::vector hashlines; //!< the checkpoint lines from the file - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(t_hash_json) KV_SERIALIZE(hashlines) END_KV_SERIALIZE_MAP() }; @@ -68,12 +67,12 @@ bool checkpoints::add_checkpoint(uint64_t height, const std::string &hash_str) { crypto::hash h = crypto::null_hash; bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); // return false if adding at a height we already have AND the hash is different if(m_points.count(height)) { - CHECK_AND_ASSERT_MES(h == m_points[height], false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); + GULPS_CHECK_AND_ASSERT_MES(h == m_points[height], false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); } m_points[height] = h; return true; @@ -93,12 +92,12 @@ bool checkpoints::check_block(uint64_t height, const crypto::hash &h, bool &is_a if(it->second == h) { - MINFO("CHECKPOINT PASSED FOR HEIGHT " << height << " " << h); + GULPSF_INFO("CHECKPOINT PASSED FOR HEIGHT {} {}", height, h); return true; } else { - MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h); + GULPSF_WARN("CHECKPOINT FAILED FOR HEIGHT {}. EXPECTED HASH: {}, FETCHED HASH: {}", height, it->second, h); return false; } } @@ -145,7 +144,7 @@ bool checkpoints::check_for_conflicts(const checkpoints &other) const { if(m_points.count(pt.first)) { - CHECK_AND_ASSERT_MES(pt.second == m_points.at(pt.first), false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); + GULPS_CHECK_AND_ASSERT_MES(pt.second == m_points.at(pt.first), false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); } } return true; @@ -195,18 +194,18 @@ bool checkpoints::load_checkpoints_from_json(const std::string &json_hashfile_fu boost::system::error_code errcode; if(!(boost::filesystem::exists(json_hashfile_fullpath, errcode))) { - LOG_PRINT_L1("Blockchain checkpoints file not found"); + GULPS_LOG_L1("Blockchain checkpoints file not found"); return true; } - LOG_PRINT_L1("Adding checkpoints from blockchain hashfile"); + GULPS_LOG_L1("Adding checkpoints from blockchain hashfile"); uint64_t prev_max_height = get_max_height(); - LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height); + GULPSF_LOG_L1("Hard-coded max checkpoint height is {}", prev_max_height); t_hash_json hashes; if(!epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath)) { - MERROR("Error loading checkpoints from " << json_hashfile_fullpath); + GULPS_ERROR("Error loading checkpoints from ", json_hashfile_fullpath); return false; } for(std::vector::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end();) @@ -215,12 +214,12 @@ bool checkpoints::load_checkpoints_from_json(const std::string &json_hashfile_fu height = it->height; if(height <= prev_max_height) { - LOG_PRINT_L1("ignoring checkpoint height " << height); + GULPSF_LOG_L1("ignoring checkpoint height {}", height); } else { std::string blockhash = it->hash; - LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); + GULPSF_LOG_L1("Adding checkpoint height {}, hash={}", height, blockhash); ADD_CHECKPOINT(height, blockhash); } ++it; diff --git a/src/checkpoints/checkpoints.h b/src/checkpoints/checkpoints.h index beef2e87..e8bb27a5 100644 --- a/src/checkpoints/checkpoints.h +++ b/src/checkpoints/checkpoints.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -21,11 +21,11 @@ #pragma once #include "crypto/hash.h" #include "cryptonote_config.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include #include -#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false); +#define ADD_CHECKPOINT(h, hash) GULPS_CHECK_AND_ASSERT(add_checkpoint(h, hash), false); #define JSON_HASH_FILE_NAME "checkpoints.json" namespace cryptonote diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b9b1f648..c902e813 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -55,7 +55,8 @@ set(common_sources perf_timer.cpp threadpool.cpp updates.cpp - boost_locale.cpp) + boost_locale.cpp + string.cpp) if (STACK_TRACE) list(APPEND common_sources stack_trace.cpp) @@ -64,6 +65,8 @@ endif() set(common_headers) set(common_private_headers + gulps.hpp + string.hpp apply_permutation.h base58.h boost_serialization_helper.h @@ -105,11 +108,15 @@ target_link_libraries(common ${Boost_THREAD_LIBRARY} ${Boost_REGEX_LIBRARY} ${Boost_CHRONO_LIBRARY} + fmt::fmt-header-only PRIVATE ${Boost_LOCALE_LIBRARY} ${OPENSSL_LIBRARIES} ${ICU_LIBRARIES} ${EXTRA_LIBRARIES}) +# activate extended color output for fmt +target_compile_definitions(common PUBLIC -DFMT_EXTENDED_COLORS) + #monero_install_headers(common # ${common_headers}) diff --git a/src/common/apply_permutation.h b/src/common/apply_permutation.h index c5436a9f..3403d539 100644 --- a/src/common/apply_permutation.h +++ b/src/common/apply_permutation.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -21,20 +21,19 @@ // https://blogs.msdn.microsoft.com/oldnewthing/20170109-00/?p=95145 #pragma once - -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include #include namespace tools { - +GULPS_CAT_MAJOR("common_tools"); template void apply_permutation(std::vector permutation, const F &swap) { //sanity check for(size_t n = 0; n < permutation.size(); ++n) - CHECK_AND_ASSERT_THROW_MES(std::find(permutation.begin(), permutation.end(), n) != permutation.end(), "Bad permutation"); + GULPS_CHECK_AND_ASSERT_THROW_MES(std::find(permutation.begin(), permutation.end(), n) != permutation.end(), "Bad permutation"); for(size_t i = 0; i < permutation.size(); ++i) { @@ -53,7 +52,7 @@ void apply_permutation(std::vector permutation, const F &swap) template void apply_permutation(const std::vector &permutation, std::vector &v) { - CHECK_AND_ASSERT_THROW_MES(permutation.size() == v.size(), "Mismatched vector sizes"); + GULPS_CHECK_AND_ASSERT_THROW_MES(permutation.size() == v.size(), "Mismatched vector sizes"); apply_permutation(permutation, [&v](size_t i0, size_t i1) { std::swap(v[i0], v[i1]); }); } } diff --git a/src/common/base58.cpp b/src/common/base58.cpp index 3601ce52..53cbf60e 100644 --- a/src/common/base58.cpp +++ b/src/common/base58.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/base58.h b/src/common/base58.h index b3be6053..d20d90b8 100644 --- a/src/common/base58.h +++ b/src/common/base58.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/bloom_filter.hpp b/src/common/bloom_filter.hpp new file mode 100644 index 00000000..cb734501 --- /dev/null +++ b/src/common/bloom_filter.hpp @@ -0,0 +1,117 @@ +// Copyright (c) 2019, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +#include +#include + +#include "crypto/hash.h" + +class bloom_filter +{ +public: + bloom_filter() {} + + inline void init(size_t num_of_elements) + { + bits_number = num_of_elements * 16; + hash_number = 11; + bytes.resize(bits_number/8, 0); + } + + inline void add_element(const void* data, size_t data_len) + { + crypto::hash h = crypto::cn_fast_hash(data, data_len); + + uint64_t seed; + memcpy(&seed, h.data, sizeof(seed)); + + std::mt19937_64 mtgen(seed); + std::uniform_int_distribution dist(0, bits_number-1); + + for(size_t i=0; i < hash_number; i++) + set_bit(dist(mtgen)); + } + + inline bool not_present(const void* data, size_t data_len) + { + crypto::hash h = crypto::cn_fast_hash(data, data_len); + + uint64_t seed; + memcpy(&seed, h.data, sizeof(seed)); + + std::mt19937_64 mtgen(seed); + std::uniform_int_distribution dist(0, bits_number-1); + + for(size_t i=0; i < hash_number; i++) + { + if(!read_bit(dist(mtgen))) + return true; + } + return false; + } + +private: + size_t hash_number; + size_t bits_number; + std::vector bytes; + + inline bool read_bit(size_t pos) + { + size_t byte = pos / 8; + size_t bit = pos % 8; + + if(byte >= bytes.size()) + return false; + + return bytes[byte] & (1< #include #include -#include "misc_log_ex.h" +#include "common/gulps.hpp" namespace tools { template bool serialize_obj_to_file(t_object &obj, const std::string &file_path) { - TRY_ENTRY(); + GULPS_CAT_MAJOR("serialization_helper"); + GULPS_TRY_ENTRY(); #if defined(_MSC_VER) // Need to know HANDLE of file to call FlushFileBuffers HANDLE data_file_handle = ::CreateFile(file_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -79,13 +80,14 @@ bool serialize_obj_to_file(t_object &obj, const std::string &file_path) #endif return true; - CATCH_ENTRY_L0("serialize_obj_to_file", false); + GULPS_CATCH_ENTRY_L0("serialize_obj_to_file", false); } template bool unserialize_obj_from_file(t_object &obj, const std::string &file_path) { - TRY_ENTRY(); + GULPS_CAT_MAJOR("serialization_helper"); + GULPS_TRY_ENTRY(); std::ifstream data_file; data_file.open(file_path, std::ios_base::binary | std::ios_base::in); @@ -109,6 +111,6 @@ bool unserialize_obj_from_file(t_object &obj, const std::string &file_path) a >> obj; } return !data_file.fail(); - CATCH_ENTRY_L0("unserialize_obj_from_file", false); + GULPS_CATCH_ENTRY_L0("unserialize_obj_from_file", false); } } diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index 64fb3910..7d4945aa 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/command_line.h b/src/common/command_line.h index 9ed7e3a8..d96c2e1c 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -31,9 +31,14 @@ #include #include +#include "common/gulps.hpp" + + namespace command_line { +GULPS_CAT_MAJOR("cmd_line"); + //! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`. bool is_yes(const std::string &str); //! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`. @@ -180,7 +185,7 @@ void add_arg(boost::program_options::options_description &description, const arg { if(0 != description.find_nothrow(arg.name, false)) { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); + GULPS_CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " , arg.name); return; } @@ -192,7 +197,7 @@ void add_arg(boost::program_options::options_description &description, const arg { if(0 != description.find_nothrow(arg.name, false)) { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); + GULPS_CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " , arg.name); return; } @@ -204,7 +209,7 @@ inline void add_arg(boost::program_options::options_description &description, co { if(0 != description.find_nothrow(arg.name, false)) { - CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name); + GULPS_CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " , arg.name); return; } @@ -233,14 +238,14 @@ bool handle_error_helper(const boost::program_options::options_description &desc } catch(const std::exception &e) { - std::cerr << "Failed to parse arguments: " << e.what() << std::endl; - std::cerr << desc << std::endl; + GULPSF_ERROR("Failed to parse arguments: {}", e.what()); + GULPS_PRINT(desc); return false; } catch(...) { - std::cerr << "Failed to parse arguments: unknown exception" << std::endl; - std::cerr << desc << std::endl; + GULPS_ERROR("Failed to parse arguments: unknown exception"); + GULPS_PRINT(desc); return false; } } diff --git a/src/common/common_fwd.h b/src/common/common_fwd.h index edf9aed1..ce0ea82d 100644 --- a/src/common/common_fwd.h +++ b/src/common/common_fwd.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 4f77a49a..3f6e75a2 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -27,11 +27,11 @@ #include #include #include -using namespace epee; namespace bf = boost::filesystem; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.dns" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("dns_utils"); static const char *DEFAULT_DNS_PUBLIC_ADDR[] = { @@ -62,27 +62,27 @@ get_builtin_cert(void) { return // The ICANN CA fetched at 24 Sep 2010. Valid to 2028 -"-----BEGIN CERTIFICATE-----\n" -"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n" -"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n" -"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX\n" -"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O\n" -"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB\n" -"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb\n" -"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S\n" -"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg\n" -"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2\n" -"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7\n" -"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29\n" -"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n" -"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3\n" -"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH\n" -"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD\n" -"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h\n" -"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n" -"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n" -"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n" -"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----" +"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO" +"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV" +"BAMTDUlDQU5OIFJvb3QgQ0ExCzAJBgNVBAYTAlVTMB4XDTA5MTIyMzA0MTkxMloX" +"DTI5MTIxODA0MTkxMlowXTEOMAwGA1UEChMFSUNBTk4xJjAkBgNVBAsTHUlDQU5O" +"IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRYwFAYDVQQDEw1JQ0FOTiBSb290IENB" +"MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKDb" +"cLhPNNqc1NB+u+oVvOnJESofYS9qub0/PXagmgr37pNublVThIzyLPGCJ8gPms9S" +"G1TaKNIsMI7d+5IgMy3WyPEOECGIcfqEIktdR1YWfJufXcMReZwU4v/AdKzdOdfg" +"ONiwc6r70duEr1IiqPbVm5T05l1e6D+HkAvHGnf1LtOPGs4CHQdpIUcy2kauAEy2" +"paKcOcHASvbTHK7TbbvHGPB+7faAztABLoneErruEcumetcNfPMIjXKdv1V1E3C7" +"MSJKy+jAqqQJqjZoQGB0necZgUMiUv7JK1IPQRM2CXJllcyJrm9WFxY0c1KjBO29" +"iIKK69fcglKcBuFShUECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B" +"Af8EBAMCAf4wHQYDVR0OBBYEFLpS6UmDJIZSL8eZzfyNa2kITcBQMA0GCSqGSIb3" +"DQEBCwUAA4IBAQAP8emCogqHny2UYFqywEuhLys7R9UKmYY4suzGO4nkbgfPFMfH" +"6M+Zj6owwxlwueZt1j/IaCayoKU3QsrYYoDRolpILh+FPwx7wseUEV8ZKpWsoDoD" +"2JFbLg2cfB8u/OlE4RYmcxxFSmXBg0yQ8/IoQt/bxOcEEhhiQ168H2yE5rxJMt9h" +"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF" +"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg" +"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk" +"-----END CERTIFICATE-----" ; } */ @@ -210,12 +210,12 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData()) dns_public_addr = tools::dns_utils::parse_dns_public(res); if(!dns_public_addr.empty()) { - MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)"); + GULPSF_INFO("Using public DNS server(s): {} (TCP)", boost::join(dns_public_addr, ", ")); use_dns_public = 1; } else { - MERROR("Failed to parse DNS_PUBLIC"); + GULPS_ERROR("Failed to parse DNS_PUBLIC"); } } @@ -239,7 +239,7 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData()) const char * const *ds = ::get_builtin_ds(); while (*ds) { - MINFO("adding trust anchor: " << *ds); + GULPSF_INFO("adding trust anchor: {}", *ds); ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++)); } } @@ -400,12 +400,12 @@ bool load_txt_records_from_dns(std::vector &good_records, const std if(!avail[cur_index]) { records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping."); + GULPSF_LOG_L2("DNSSEC not available for checkpoint update at URL: {}, skipping.", url); } if(!valid[cur_index]) { records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping."); + GULPSF_LOG_L2("DNSSEC validation failed for checkpoint update at URL: {}, skipping.", url); } cur_index++; @@ -427,7 +427,7 @@ bool load_txt_records_from_dns(std::vector &good_records, const std if(num_valid_records < 2) { - //LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received"); + //GULPS_LOG_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received"); return false; } @@ -451,7 +451,7 @@ bool load_txt_records_from_dns(std::vector &good_records, const std if(good_records_index < 0) { - //LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched"); + //GULPS_LOG_L0("WARNING: no two MoneroPulse DNS checkpoint records matched"); return false; } @@ -468,13 +468,13 @@ std::vector parse_dns_public(const char *s) { for(size_t i = 0; i < sizeof(DEFAULT_DNS_PUBLIC_ADDR) / sizeof(DEFAULT_DNS_PUBLIC_ADDR[0]); ++i) dns_public_addr.push_back(DEFAULT_DNS_PUBLIC_ADDR[i]); - LOG_PRINT_L0("Using default public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)"); + GULPSF_LOG_L0("Using default public DNS server(s):{} (TCP)", boost::join(dns_public_addr, ", ")); } else if(sscanf(s, "tcp://%u.%u.%u.%u%c", &ip0, &ip1, &ip2, &ip3, &c) == 4) { if(ip0 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255) { - MERROR("Invalid IP: " << s << ", using default"); + GULPSF_ERROR("Invalid IP: {}, using default", s); } else { @@ -483,7 +483,7 @@ std::vector parse_dns_public(const char *s) } else { - MERROR("Invalid DNS_PUBLIC contents, ignored"); + GULPS_ERROR("Invalid DNS_PUBLIC contents, ignored"); } return dns_public_addr; } diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index cc3ab099..0cb3d83d 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/download.cpp b/src/common/download.cpp index 87a1049b..c6029ad3 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -27,11 +27,15 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.dl" +#include "common/gulps.hpp" + + namespace tools { + +GULPS_CAT_MAJOR("download"); + struct download_thread_control { const std::string path; @@ -56,7 +60,7 @@ static void download_thread(download_async_handle control) { static std::atomic thread_id(0); - MLOG_SET_THREAD_NAME("DL" + std::to_string(thread_id++)); + GULPS_SET_THREAD_NAME("DL" + std::to_string(thread_id++)); struct stopped_setter { @@ -72,19 +76,19 @@ static void download_thread(download_async_handle control) uint64_t existing_size = 0; if(epee::file_io_utils::get_file_size(control->path, existing_size) && existing_size > 0) { - MINFO("Resuming downloading " << control->uri << " to " << control->path << " from " << existing_size); + GULPSF_INFO("Resuming downloading {} to {} from {}", control->uri , control->path , existing_size); mode |= std::ios_base::app; } else { - MINFO("Downloading " << control->uri << " to " << control->path); + GULPSF_INFO("Downloading {} to {}", control->uri , control->path); mode |= std::ios_base::trunc; } std::ofstream f; f.open(control->path, mode); if(!f.good()) { - MERROR("Failed to open file " << control->path); + GULPSF_ERROR("Failed to open file {}", control->path); control->result_cb(control->path, control->uri, control->success); return; } @@ -96,18 +100,18 @@ static void download_thread(download_async_handle control) virtual bool on_header(const epee::net_utils::http::http_response_info &headers) { for(const auto &kv : headers.m_header_info.m_etc_fields) - MDEBUG("Header: " << kv.first << ": " << kv.second); + GULPSF_LOG_L1("Header: {}: {}", kv.first , kv.second); ssize_t length = 0u; if(epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0) { - MINFO("Content-Length: " << length); + GULPSF_INFO("Content-Length: {}", length); content_length = length; boost::filesystem::path path(control->path); boost::filesystem::space_info si = boost::filesystem::space(path); if(si.available < (size_t)content_length) { const uint64_t avail = (si.available + 1023) / 1024, needed = (content_length + 1023) / 1024; - MERROR("Not enough space to download " << needed << " kB to " << path << " (" << avail << " kB available)"); + GULPSF_ERROR("Not enough space to download {} kB to {} ({} kB available)", needed, path.string(), avail); return false; } } @@ -126,7 +130,7 @@ static void download_thread(download_async_handle control) } if(!got_range) { - MWARNING("We did not get the requested range, downloading from start"); + GULPS_WARN("We did not get the requested range, downloading from start"); f.close(); f.open(control->path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); } @@ -148,7 +152,7 @@ static void download_thread(download_async_handle control) } catch(const std::exception &e) { - MERROR("Error writing data: " << e.what()); + GULPSF_ERROR("Error writing data: {}", e.what()); return false; } } @@ -163,13 +167,13 @@ static void download_thread(download_async_handle control) epee::net_utils::http::url_content u_c; if(!epee::net_utils::parse_url(control->uri, u_c)) { - MERROR("Failed to parse URL " << control->uri); + GULPSF_ERROR("Failed to parse URL {}", control->uri); control->result_cb(control->path, control->uri, control->success); return; } if(u_c.host.empty()) { - MERROR("Failed to determine address from URL " << control->uri); + GULPSF_ERROR("Failed to determine address from URL {}", control->uri); control->result_cb(control->path, control->uri, control->success); return; } @@ -178,28 +182,28 @@ static void download_thread(download_async_handle control) bool ssl = u_c.schema == "https"; uint16_t port = u_c.port ? u_c.port : ssl ? 443 : 80; - MDEBUG("Connecting to " << u_c.host << ":" << port); + GULPSF_LOG_L1("Connecting to {}:{}", u_c.host , port); client.set_server(u_c.host, std::to_string(port), boost::none, ssl); if(!client.connect(std::chrono::seconds(30))) { boost::lock_guard lock(control->mutex); - MERROR("Failed to connect to " << control->uri); + GULPSF_ERROR("Failed to connect to {}", control->uri); control->result_cb(control->path, control->uri, control->success); return; } - MDEBUG("GETting " << u_c.uri); + GULPSF_LOG_L1("GETting {}", u_c.uri); const epee::net_utils::http::http_response_info *info = NULL; epee::net_utils::http::fields_list fields; if(existing_size > 0) { const std::string range = "bytes=" + std::to_string(existing_size) + "-"; - MDEBUG("Asking for range: " << range); + GULPSF_LOG_L1("Asking for range: {}", range); fields.push_back(std::make_pair("Range", range)); } if(!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info, fields)) { boost::lock_guard lock(control->mutex); - MERROR("Failed to connect to " << control->uri); + GULPSF_ERROR("Failed to connect to {}", control->uri); client.disconnect(); control->result_cb(control->path, control->uri, control->success); return; @@ -207,7 +211,7 @@ static void download_thread(download_async_handle control) if(control->stop) { boost::lock_guard lock(control->mutex); - MDEBUG("Download cancelled"); + GULPS_LOG_L1("Download cancelled"); client.disconnect(); control->result_cb(control->path, control->uri, control->success); return; @@ -215,28 +219,28 @@ static void download_thread(download_async_handle control) if(!info) { boost::lock_guard lock(control->mutex); - MERROR("Failed invoking GET command to " << control->uri << ", no status info returned"); + GULPSF_ERROR("Failed invoking GET command to {}, no status info returned", control->uri ); client.disconnect(); control->result_cb(control->path, control->uri, control->success); return; } - MDEBUG("response code: " << info->m_response_code); - MDEBUG("response length: " << info->m_header_info.m_content_length); - MDEBUG("response comment: " << info->m_response_comment); - MDEBUG("response body: " << info->m_body); + GULPSF_LOG_L1("response code: {}", info->m_response_code); + GULPSF_LOG_L1("response length: {}", info->m_header_info.m_content_length); + GULPSF_LOG_L1("response comment: {}", info->m_response_comment); + GULPSF_LOG_L1("response body: {}", info->m_body); for(const auto &f : info->m_additional_fields) - MDEBUG("additional field: " << f.first << ": " << f.second); + GULPSF_LOG_L1("additional field: {}: {}", f.first , f.second); if(info->m_response_code != 200 && info->m_response_code != 206) { boost::lock_guard lock(control->mutex); - MERROR("Status code " << info->m_response_code); + GULPSF_ERROR("Status code {}", info->m_response_code); client.disconnect(); control->result_cb(control->path, control->uri, control->success); return; } client.disconnect(); f.close(); - MDEBUG("Download complete"); + GULPS_LOG_L1("Download complete"); lock.lock(); control->success = true; control->result_cb(control->path, control->uri, control->success); @@ -244,7 +248,7 @@ static void download_thread(download_async_handle control) } catch(const std::exception &e) { - MERROR("Exception in download thread: " << e.what()); + GULPSF_ERROR("Exception in download thread: {}", e.what()); // fall through and call result_cb not from the catch block to avoid another exception } boost::lock_guard lock(control->mutex); @@ -268,21 +272,21 @@ download_async_handle download_async(const std::string &path, const std::string bool download_finished(const download_async_handle &control) { - CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + GULPS_CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); boost::lock_guard lock(control->mutex); return control->stopped; } bool download_error(const download_async_handle &control) { - CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + GULPS_CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); boost::lock_guard lock(control->mutex); return !control->success; } bool download_wait(const download_async_handle &control) { - CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + GULPS_CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); { boost::lock_guard lock(control->mutex); if(control->stopped) @@ -294,7 +298,7 @@ bool download_wait(const download_async_handle &control) bool download_cancel(const download_async_handle &control) { - CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); + GULPS_CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle"); { boost::lock_guard lock(control->mutex); if(control->stopped) diff --git a/src/common/download.h b/src/common/download.h index e7f616f4..03c963ed 100644 --- a/src/common/download.h +++ b/src/common/download.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/gulps.hpp b/src/common/gulps.hpp new file mode 100644 index 00000000..cdcc2dd3 --- /dev/null +++ b/src/common/gulps.hpp @@ -0,0 +1,965 @@ +// Copyright (c) 2018, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +#pragma once + +#include "inttypes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "thdq.hpp" +#include "string.hpp" +#include +#include +#include +#include "../cryptonote_config.h" + +#if defined(WIN32) +#include +#include +#else +#include +#endif + +// Some syntatic sugar to ease macro work +// stream_writer::write(a,b,c) is equivarent to +// strigstream ss; ss << a << b << c; return ss.str(); +class stream_writer +{ +public: + template + static inline std::string write(const T& v, Args... args) + { + std::stringstream ss; + ss << v; + do_op(ss, args...); + return ss.str(); + } + + //Optimise trivial strings + static inline std::string write(const char* arg) + { + return arg; + } + +private: + static inline void do_op(std::stringstream& ss) { } + + template + static inline void do_op(std::stringstream& ss, const T& v, Args... args) + { + ss << v; + do_op(ss, args...); + } +}; + +class gulps +{ +public: + enum output_mode : uint32_t + { + TEXT_ONLY, + TIMESTAMP_ONLY, + TIMESTAMP_LOG + }; + + enum level : uint32_t + { + LEVEL_PRINT = 0, + LEVEL_ERROR, + LEVEL_WARN, + LEVEL_INFO, + LEVEL_DEBUG, + LEVEL_TRACE, + LEVEL_TRACE2 + }; + + static inline const char* level_to_str(level lvl) + { + switch(lvl) + { + case LEVEL_PRINT: return "PRINT"; + case LEVEL_ERROR: return "ERROR"; + case LEVEL_WARN: return "WARN"; + case LEVEL_INFO: return "INFO"; + case LEVEL_DEBUG: return "DEBUG"; + case LEVEL_TRACE: return "TRACE"; + case LEVEL_TRACE2: return "TRACE2"; + default: return "UNKNOWN"; + } + } + + // Those are output channels. First question is are we directing the message at + // the screen (USER) or disk (LOG). However the lines can get blurry - in an RPC command + // do we direct the output at the RPC app screen, or the user on the other side? Hence 3 + // separate the the end user application can direct separately + enum output : uint32_t + { + OUT_USER_0, + OUT_USER_1, + OUT_USER_2, + OUT_LOG_0, + OUT_LOG_1, + OUT_LOG_2 + }; + + static inline const char* out_to_str(output out) + { + switch(out) + { + case OUT_USER_0: return "OUTPUT0"; + case OUT_USER_1: return "OUTPUT1"; + case OUT_USER_2: return "OUTPUT2"; + case OUT_LOG_0: return "LOG0"; + case OUT_LOG_1: return "LOG1"; + case OUT_LOG_2: return "LOG2"; + default: return "UNKNOWN"; + } + } + + enum color : uint32_t + { + COLOR_WHITE = 1, + COLOR_RED = 2, + COLOR_GREEN = 3, + COLOR_BLUE = 4, + COLOR_CYAN = 5, + COLOR_MAGENTA = 6, + COLOR_YELLOW = 7, + COLOR_BOLD_WHITE = 9, + COLOR_BOLD_RED = 10, + COLOR_BOLD_GREEN = 11, + COLOR_BOLD_BLUE = 12, + COLOR_BOLD_CYAN = 13, + COLOR_BOLD_MAGENTA = 14, + COLOR_BOLD_YELLOW = 15, + COLOR_MASK = 7, // Masks color from brightness + COLOR_BOLD = 8 + }; + + //Object handling a single long message + class message + { + public: + std::time_t time; + level lvl; + output out; + std::string cat_major; + std::string cat_minor; + std::string src_path; + int64_t src_line; + std::string thread_id; + std::string text; + color clr; + bool printed = false; + bool logged = false; + + message(output out, level lvl, const char* major, const char* minor, const char* path, int64_t line, std::string&& txt, color clr = COLOR_WHITE, bool add_newline = true) : + time(std::time(nullptr)), lvl(lvl), out(out), cat_major(major), cat_minor(minor), src_path(path), src_line(line), + thread_id(gulps::inst().get_thread_tag()), text(std::move(txt)), clr(clr) + { + const std::string& pre = gulps::inst().get_path_prefix(); + + if(src_path.find(pre) == 0) + src_path.erase(0, pre.size()); + + if(add_newline && text.back() != '\n') + text += '\n'; + } + + const std::string& print_message(std::string& header, output_mode mode = TIMESTAMP_ONLY) const + { + switch(mode) + { + case TIMESTAMP_LOG: + header = fmt::format("{:%Y-%m-%d %H:%M:%S} [{}/{}] {} {}.{} {}:{} ", + fmt::localtime(time), level_to_str(lvl), out_to_str(out), thread_id, cat_major, cat_minor, src_path, src_line); + break; + + case TIMESTAMP_ONLY: + header = fmt::format("{:%Y-%m-%d %H:%M:%S} ", fmt::localtime(time)); + break; + + case TEXT_ONLY: + header = ""; + break; + } + + return text; + } + + message(message&& ) = default; + message& operator=(message&& ) = default; + message(const message& ) = default; + message& operator=(const message& ) = default; + }; + + // Function pointers are mariginally more efficient than functors here + // NB Lambdas must not capture to be convertible to a function ptr + typedef bool (*filter_fun)(const message&, bool printed, bool logged); + + class gulps_output + { + protected: + enum output_stream + { + STREAM_PRINT, + STREAM_FILE, + STREAM_NONE + }; + + public: + gulps_output() = default; + virtual ~gulps_output() = default; + virtual void log_message(const message& msg) = 0; + virtual output_stream get_stream() = 0; + + // This is filtered call + bool log(const message& msg, bool& printed, bool& logged) + { + bool result = false; + for(filter_fun filter : filters) + { + if(filter(msg, printed, logged)) + { + result = true; + break; + } + } + + if(result) + { + log_message(msg); + + switch(get_stream()) + { + case STREAM_PRINT: + printed = true; + break; + case STREAM_FILE: + logged = true; + break; + default: + break; + } + } + + return result; + } + + void add_filter(filter_fun filter) { filters.push_back(filter); }; + + private: + gulps_output(gulps_output&& ) = delete; + gulps_output& operator=(gulps_output&& ) = delete; + gulps_output(gulps_output& ) = delete; + gulps_output& operator=(gulps_output& ) = delete; + + std::vector filters; + }; + + class gulps_print_output : public gulps_output + { + public: + gulps_print_output(color hdr_color, output_mode mode = TIMESTAMP_ONLY) : hdr_color(hdr_color), mode(mode) {} + + output_stream get_stream() override { return STREAM_PRINT; } + + void log_message(const message& msg) override + { + std::string header; + const std::string& text = msg.print_message(header, mode); + if(mode != TEXT_ONLY) + print(header, hdr_color); + print(text, msg.clr); + } + + private: + output_mode mode; + + static void print(const std::string& txt, color clr) + { + set_console_color(clr); + std::fputs(txt.c_str(), stdout); + reset_console_color(); + +#if defined(WIN32) + std::cout.flush(); +#endif + } + + static bool is_stdout_a_tty() + { +#if defined(WIN32) + static std::atomic is_a_tty(_isatty(_fileno(stdout)) != 0); +#else + static std::atomic is_a_tty(isatty(fileno(stdout)) != 0); +#endif + return is_a_tty; + } + + static void set_console_color(color clr) + { + if(!is_stdout_a_tty()) + return; + +#ifdef WIN32 + WORD bright = (clr & COLOR_BOLD) ? FOREGROUND_INTENSITY : 0; +#else + bool bright = (clr & COLOR_BOLD) != 0; +#endif + switch(clr & COLOR_MASK) + { + default: + case COLOR_WHITE: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | bright); +#else + std::cout << (bright ? "\033[1;97m" : "\033[0;97m"); + std::cout.flush(); +#endif + break; + case COLOR_RED: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | bright); +#else + std::cout << (bright ? "\033[1;31m" : "\033[0;31m"); + std::cout.flush(); +#endif + break; + case COLOR_GREEN: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | bright); +#else + std::cout << (bright ? "\033[1;32m" : "\033[0;32m"); + std::cout.flush(); +#endif + break; + case COLOR_BLUE: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | bright); +#else + std::cout << (bright ? "\033[1;34m" : "\033[0;34m"); + std::cout.flush(); +#endif + break; + case COLOR_CYAN: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | bright); +#else + std::cout << (bright ? "\033[1;36m" : "\033[0;36m"); + std::cout.flush(); +#endif + break; + case COLOR_MAGENTA: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_RED | bright); +#else + std::cout << (bright ? "\033[1;35m" : "\033[0;35m"); + std::cout.flush(); +#endif + break; + case COLOR_YELLOW: +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | bright); +#else + std::cout << (bright ? "\033[1;33m" : "\033[0;33m"); + std::cout.flush(); +#endif + break; + } + } + + static void reset_console_color() + { + if(!is_stdout_a_tty()) + return; + +#ifdef WIN32 + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); +#else + std::cout << "\033[0m"; + std::cout.flush(); +#endif + } + + protected: + color hdr_color; + }; + + //Store messages to, for example, send them over the network + class gulps_mem_output : public gulps_output + { + public: + gulps_mem_output() {} + + output_stream get_stream() override { return STREAM_NONE; } + + void log_message(const message& msg) override + { + log.push_back(msg); + } + + const std::vector& get_log() + { + return log; + } + + protected: + std::vector log; + }; + + //Class handling synchronous file logging. + class gulps_file_output : public gulps_output + { + public: + gulps_file_output(const std::string& name) : fname(name) + { + output_file.exceptions(std::ofstream::failbit | std::ofstream::badbit); + output_file.open(fname, std::ios::out | std::ios::app | std::ios::binary); // may throw + } + + output_stream get_stream() override { return STREAM_FILE; } + + void log_message(const message& msg) override + { + write_output(msg); + } + + ~gulps_file_output() + { + log_message(message(OUT_LOG_2, LEVEL_TRACE, "log_shutdown", fname.c_str(), __FILE__, __LINE__, "Log file shutting down.")); + output_file.close(); + } + + protected: + inline void write_output(const message& msg) + { + try + { + std::string header; + const std::string text = msg.print_message(header, TIMESTAMP_LOG); + output_file << header << text; + output_file.flush(); + } + catch(const std::exception& ex) + { + std::cout << "!!! PANIC, error writing to a log file! Your disk is probably full! " << ex.what() << std::endl; + } + } + + std::string fname; + std::ofstream output_file; + }; + + //Class handling async logging. Async logging is thread-safe and preserves temporal order + class gulps_async_file_output : public gulps_file_output + { + public: + gulps_async_file_output(const std::string& name) : + gulps_file_output(name), thd(&gulps_async_file_output::output_main, this) + { + } + + void log_message(const message& msg) override + { + msg_q.push(msg); + } + + void output_main() + { + std::unique_lock lck = msg_q.get_lock(); + while(msg_q.wait_for_pop(lck)) + { + message msg = msg_q.pop(lck); + write_output(msg); + } + } + + ~gulps_async_file_output() + { + log_message(message(OUT_LOG_2, LEVEL_TRACE, "log_shutdown", fname.c_str(), __FILE__, __LINE__, "Log thread shutting down.")); + if(thd.joinable()) + { + msg_q.set_finish_flag(); + thd.join(); + } + } + + private: + inline void write_output(const message& msg) + { + try + { + std::string header; + const std::string text = msg.print_message(header, TIMESTAMP_LOG); + output_file << header << text; + output_file.flush(); + } + catch(const std::exception& ex) + { + std::cerr << "!!! PANIC, error writing to a log file! Your disk is probably full! " << ex.what() << std::endl; + } + } + + thdq msg_q; + std::thread thd; + }; + inline const std::string& get_thread_tag() { return thread_tag(); } + inline void set_thread_tag(const std::string& tag) { thread_tag() = tag; } + + inline static gulps& inst() + { + static gulps inst; + return inst; + } + + inline static const gulps& cinst() + { + static const gulps& inst = gulps::inst(); + return inst; + } + + //Returned value is a handle unique to that output. It can be used to remove it. + uint64_t add_output(std::unique_ptr output) + { + std::unique_lock lck(gulps_global); + outputs.insert(std::make_pair(next_handle, std::move(output))); + return next_handle++; + } + + void remove_output(uint64_t handle) + { + std::unique_lock lck(gulps_global); + outputs.erase(handle); + } + + void log(message&& in_msg) + { + std::unique_lock lck(gulps_global); + message msg = std::move(in_msg); + bool printed = false, logged = false; + + for(const auto& it : outputs) + it.second->log(msg, printed, logged); + } + + inline const std::string& get_path_prefix() + { + return path_prefix; + } + +private: + gulps() + { + path_prefix = __FILE__; + size_t pos; + if((pos = path_prefix.find("src/common/gulps.hpp")) != std::string::npos) + path_prefix.erase(pos); + else if((pos = path_prefix.find("src\\common\\gulps.hpp")) != std::string::npos) + path_prefix.erase(pos); + else + assert(false); + } + + inline std::string& thread_tag() + { + static thread_local std::string thread_tag; + return thread_tag; + } + + std::string path_prefix; + uint64_t next_handle = 0; + std::mutex gulps_global; + std::map> outputs; +}; + +class gulps_log_level +{ +private: + struct cat_pair + { + cat_pair(std::string&& cat, gulps::level lvl) : cat(std::move(cat)), level(lvl) {} + + cat_pair(cat_pair&& ) = default; + cat_pair& operator=(cat_pair&& ) = default; + cat_pair(const cat_pair& ) = default; + cat_pair& operator=(const cat_pair& ) = default; + + std::string cat; + gulps::level level; + }; + + std::mutex cat_mutex; + std::vector log_cats; + gulps::level wildcard_level; + std::string current_cat_str; + bool active = false; + +public: + gulps_log_level() {} + + static const char* get_default_log_level() + { + return "*:WARN"; + } + + const std::string& get_current_cat_str() const + { + return current_cat_str; + } + + bool parse_cat_string(const char* str) + { + std::unique_lock lck(cat_mutex); + + if(strlen(str) == 0) + str = get_default_log_level(); + current_cat_str = str; + + static const std::unordered_map str_to_level = { + {"PRINT", gulps::LEVEL_PRINT}, + {"ERROR", gulps::LEVEL_ERROR}, + {"WARN", gulps::LEVEL_WARN}, + {"INFO", gulps::LEVEL_INFO}, + {"DEBUG", gulps::LEVEL_DEBUG}, + {"TRACE", gulps::LEVEL_TRACE}, + {"TRACE2", gulps::LEVEL_TRACE2} + }; + + static const std::unordered_map aliased_levels = { + {"0", "*:PRINT"}, + {"1", "*:WARN"}, + {"2", "*:INFO"}, + {"3", "*:DEBUG"}, + {"4", "*:TRACE2"} + }; + + std::vector vcats, vcat; + boost::split(vcats, str, boost::is_any_of(","), boost::token_compress_on); + + std::vector log_cats_tmp; + + for(const std::string& scat : vcats) + { + vcat.clear(); + + auto it1 = aliased_levels.find(scat); + if(it1 != aliased_levels.end()) + boost::split(vcat, it1->second, boost::is_any_of(":"), boost::token_compress_on); + else + boost::split(vcat, scat, boost::is_any_of(":"), boost::token_compress_on); + + if(vcat.size() != 2) + return false; + + auto it = str_to_level.find(vcat[1]); + if(it == str_to_level.end()) + return false; + + gulps::level level = it->second; + if(vcat[0] != "*") + log_cats_tmp.emplace_back(std::move(vcat[0]), level); + else + wildcard_level = level; + } + + // replace old log lvl with new levels + log_cats.swap(log_cats_tmp); + active = true; + return true; + } + + bool is_active() const { return active; } + + bool match_msg(const gulps::message& msg) + { + std::unique_lock lck(cat_mutex); + + for(const cat_pair& p : log_cats) + { + if(msg.cat_minor == p.cat || msg.cat_major == p.cat) + return msg.lvl <= p.level; + } + + return msg.lvl <= wildcard_level; + } +}; + +namespace debug +{ + inline bool get_set_enable_assert(bool set = false, bool v = false) + { + static bool e = true; + if(set) + e = v; + return e; + }; +}; + + +#define GULPS_CSTR_TYPE(...) \ + union { static constexpr auto c_str() -> decltype(__VA_ARGS__) { return __VA_ARGS__; } } +#define GULPS_CSTR(...) \ + [] { using Cat = GULPS_CSTR_TYPE(__VA_ARGS__); return Cat{}.c_str(); }() + +#define GULPS_CAT_MAJOR(...) using gulps_major_cat = GULPS_CSTR_TYPE(__VA_ARGS__) +#define GULPS_CAT_MINOR(...) using gulps_minor_cat = GULPS_CSTR_TYPE(__VA_ARGS__) + +GULPS_CAT_MINOR(""); + +#define GULPS_OUTPUT(out, lvl, maj, min, clr, ...) gulps::inst().log(gulps::message(out, lvl, maj, min, __FILE__, __LINE__, stream_writer::write(__VA_ARGS__), clr)) +#define GULPS_OUTPUTF(out, lvl, maj, min, clr, ...) gulps::inst().log(gulps::message(out, lvl, maj, min, __FILE__, __LINE__, fmt::format(__VA_ARGS__), clr)) + +#define GULPS_PRINT_NOLF(...) gulps::inst().log(gulps::message(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), "input_line", \ + __FILE__, __LINE__, stream_writer::write(__VA_ARGS__), gulps::COLOR_WHITE, false)); + +#define GULPS_PRINT(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_PRINT_CLR(clr, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), clr, __VA_ARGS__) +#define GULPS_ERROR(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_WARN(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_INFO(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_INFO_CLR(clr, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), clr, __VA_ARGS__) + + +#define GULPS_DEBUG_PRINT(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_ERROR(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_WARN(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L0(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L1(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L2(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L3(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPSF_PRINT(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_PRINT_CLR(clr, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), clr, __VA_ARGS__) +#define GULPSF_ERROR(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPSF_WARN(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPSF_INFO(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_INFO_CLR(clr, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), clr, __VA_ARGS__) + + +#define GULPSF_DEBUG_PRINT(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_ERROR(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_WARN(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_L0(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_L1(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_L2(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_LOG_L3(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPS_CAT_PRINT(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_PRINT_CLR(clr, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), min, clr, __VA_ARGS__) +#define GULPS_CAT_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), min, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_CAT_WARN(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), min, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_CAT_INFO(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_INFO_CLR(clr, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), min, clr, __VA_ARGS__) + +#define GULPS_CAT_DEBUG_PRINT(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_WARN(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L0(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L1(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L2(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L3(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPSF_CAT_PRINT(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_CAT_PRINT_CLR(clr, min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), min, clr, __VA_ARGS__) +#define GULPSF_CAT_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), min, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPSF_CAT_WARN(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_WARN, gulps_major_cat::c_str(), min, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPSF_CAT_INFO(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_CAT_INFO_CLR(clr, min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, gulps_major_cat::c_str(), min, clr, __VA_ARGS__) + +#define GULPSF_CAT_LOG_L1(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, gulps_major_cat::c_str(), min, gulps::COLOR_WHITE, __VA_ARGS__) + + +#define GULPS_CAT2_PRINT(maj, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_PRINT_CLR(clr, maj, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, maj, min, clr, __VA_ARGS__) +#define GULPS_CAT2_ERROR(maj, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, maj, min, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_CAT2_WARN(maj, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_WARN, maj, min, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_CAT2_INFO(maj, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPS_CAT2_DEBUG_PRINT(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_ERROR(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_WARN(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_WARN, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_L0(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_INFO, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_L1(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_L2(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT2_LOG_L3(maj, min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, maj, min, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPSF_CAT2_LOG_ERROR(maj, min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_ERROR, maj, min, gulps::COLOR_BOLD_RED, __VA_ARGS__) + +#define GULPS_VERIFY_ERR_TX(...) GULPS_CAT2_LOG_ERROR("verify", "tx", __VA_ARGS__) +#define GULPS_VERIFY_ERR_BLK(...) GULPS_CAT2_LOG_ERROR("verify", "block", __VA_ARGS__) + +#define GULPSF_VERIFY_ERR_TX(...) GULPSF_CAT2_LOG_ERROR("verify", "tx", __VA_ARGS__) +#define GULPSF_VERIFY_ERR_BLK(...) GULPSF_CAT2_LOG_ERROR("verify", "block", __VA_ARGS__) + +#define GULPS_GLOBAL_PRINT(...) GULPS_CAT_PRINT_CLR(gulps::COLOR_CYAN, "global", __VA_ARGS__) +#define GULPSF_GLOBAL_PRINT(...) GULPSF_CAT_PRINT_CLR(gulps::COLOR_CYAN, "global", __VA_ARGS__) + +#define GULPS_GLOBAL_PRINT_CLR(clr, ...) GULPS_CAT_PRINT_CLR(clr, "global", __VA_ARGS__) +#define GULPSF_GLOBAL_PRINT_CLR(clr, ...) GULPSF_CAT_PRINT_CLR(clr, "global", __VA_ARGS__) + +/* +#define GULPS_ERROR(...) GULPS_OUTPUT(gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::red, __VA_ARGS__) +#define GULPS_WARN(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_WARN, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::orange, fstr, __VA_ARGS__) +#define GULPS_INFO(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_INFO, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG0(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_LOG_0, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG1(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_DEBUG_1, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG2(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_DEBUG_2, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_PRINT(clr, fstr, ...) GULPS_OUTPUT(gulps::LEVEL_OUTPUT_0, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), clr, fstr, __VA_ARGS__)*/ + +#define GULPS_SET_THREAD_NAME(x) gulps::inst().set_thread_tag(x) + +#ifndef GULPS_LOCAL_ASSERT +#include +#if(defined _MSC_VER) +#define GULPS_LOCAL_ASSERT(expr) \ + { \ + if(debug::get_set_enable_assert()) \ + { \ + _ASSERTE(expr); \ + } \ + } +#else +#define GULPS_LOCAL_ASSERT(expr) +#endif +#endif + +#define GULPS_TRY_ENTRY() \ + try \ + { +#define GULPS_CATCH_ENTRY(location, return_val) \ + } \ + catch(const std::exception &ex) \ + { \ + (void)(ex); \ + GULPS_LOG_ERROR("Exception at [", location, "], what=", ex.what()); \ + return return_val; \ + } \ + catch(...) \ + { \ + GULPS_LOG_ERROR("Exception at [", location, "], generic exception \"...\""); \ + return return_val; \ + } + +#define GULPS_CATCH_ENTRY_L0(lacation, return_val) GULPS_CATCH_ENTRY(lacation, return_val) +#define GULPS_CATCH_ENTRY_L1(lacation, return_val) GULPS_CATCH_ENTRY(lacation, return_val) +#define GULPS_CATCH_ENTRY_L2(lacation, return_val) GULPS_CATCH_ENTRY(lacation, return_val) +#define GULPS_CATCH_ENTRY_L3(lacation, return_val) GULPS_CATCH_ENTRY(lacation, return_val) +#define GULPS_CATCH_ENTRY_L4(lacation, return_val) GULPS_CATCH_ENTRY(lacation, return_val) + +#define GULPS_ASSERT_MES_AND_THROW(...) \ +{ \ + std::string str; \ + str = stream_writer::write(__VA_ARGS__); \ + GULPS_LOG_ERROR(__VA_ARGS__); \ + throw std::runtime_error(str); \ +} + +#define GULPS_CHECK_AND_ASSERT_THROW_MES(expr, ...) \ +do \ +{ \ + if(!(expr)) \ + GULPS_ASSERT_MES_AND_THROW(__VA_ARGS__); \ +} while(0) + +#define GULPS_CHECK_AND_ASSERT(expr, fail_ret_val) \ +do \ +{ \ + if(!(expr)) \ + { \ + GULPS_LOCAL_ASSERT(expr); \ + return fail_ret_val; \ + }; \ +} while(0) + +#define GULPS_CHECK_AND_ASSERT_MES(expr, fail_ret_val, ...) \ +do \ +{ \ + if(!(expr)) \ + { \ + GULPS_LOG_ERROR(__VA_ARGS__); \ + return fail_ret_val; \ + }; \ +} while(0) + +#define GULPS_CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, l, ...) \ +do \ +{ \ + if(!(expr)) \ + { \ + GULPS_LOG_L##l(__VA_ARGS__); /*LOCAL_ASSERT(expr);*/ \ + return fail_ret_val; \ + }; \ +} while(0) + +#define GULPS_CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, ...) GULPS_CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 0, __VA_ARGS__) + +#define GULPS_CHECK_AND_NO_ASSERT_MES_L1(expr, fail_ret_val, ... ) GULPS_CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 1, __VA_ARGS__) + +#define GULPS_CHECK_AND_ASSERT_MES_NO_RET(expr, ...) \ +do \ +{ \ + if(!(expr)) \ + { \ + GULPS_LOG_ERROR(__VA_ARGS__); \ + return; \ + }; \ +} while(0) + +#define GULPS_CHECK_AND_ASSERT_MES2(expr, ...)) \ + do \ + { \ + if(!(expr)) \ + { \ + GULPS_LOG_ERROR(__VA_ARGS__); \ + }; \ + } while(0) + +#define GULPS_CHECK_AND_ASSERT_MES_CONTEXT(condition, return_val, ...) GULPS_CHECK_AND_ASSERT_MES(condition, return_val, "[", epee::net_utils::print_connection_context_short(context), "] ", __VA_ARGS__) diff --git a/src/common/http_connection.h b/src/common/http_connection.h index 1c93ba56..551601a5 100644 --- a/src/common/http_connection.h +++ b/src/common/http_connection.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/i18n.cpp b/src/common/i18n.cpp index 9b8ded12..f5972ac1 100644 --- a/src/common/i18n.cpp +++ b/src/common/i18n.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 "common/i18n.h" #include "common/util.h" #include "file_io_utils.h" @@ -27,8 +28,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "i18n" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("i18n"); static const unsigned char qm_magic[16] = {0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95, 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd}; @@ -36,7 +38,7 @@ static std::map i18n_entries; /* Logging isn't initialized yet when this is run */ /* add std::flush, because std::endl doesn't seem to flush, contrary to expected */ -// #define i18n_log(x) do { std::cout << __FILE__ << ":" << __LINE__ << ": " << x << std::endl; std::cout << std::flush; } while(0) +// #define i18n_log(x) do { GULPSF_LOG_0("{}:{}:{}", __FILE__, __LINE__, x); } while(0) #define i18n_log(x) ((void)0) std::string i18n_get_language() diff --git a/src/common/i18n.h b/src/common/i18n.h index 9afa1a03..9d979caf 100644 --- a/src/common/i18n.h +++ b/src/common/i18n.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/int-util.h b/src/common/int-util.h index 4e5509de..f8ac4712 100644 --- a/src/common/int-util.h +++ b/src/common/int-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/json_util.h b/src/common/json_util.h index 23800401..f4cda531 100644 --- a/src/common/json_util.h +++ b/src/common/json_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -15,7 +15,6 @@ // 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. - #pragma once #define GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, name, type, jtype, mandatory, def) \ @@ -32,13 +31,13 @@ } \ else \ { \ - LOG_ERROR("Field " << #name << " found in JSON, but not " << #jtype); \ + GULPSF_LOG_ERROR("Field {} found in JSON, but not {}", #name, #jtype); \ return false; \ } \ } \ else if(mandatory) \ { \ - LOG_ERROR("Field " << #name << " not found in JSON"); \ + GULPSF_LOG_ERROR("Field {} not found in JSON", #name); \ return false; \ } \ while(0) diff --git a/src/common/password.cpp b/src/common/password.cpp index c1ca40cf..8bcf3d2b 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -34,8 +34,12 @@ #include "memwipe.h" +#include "common/gulps.hpp" + #define EOT 0x4 +GULPS_CAT_MAJOR("password"); + namespace { #if defined(_WIN32) @@ -69,7 +73,7 @@ bool read_from_tty(epee::wipeable_string &pass) } else if(ch == '\n' || ch == '\r') { - std::cout << std::endl; + GULPS_PRINT("\n"); break; } else if(ch == BACKSPACE) @@ -128,7 +132,7 @@ bool read_from_tty(epee::wipeable_string &aPass) } else if(ch == '\n' || ch == '\r') { - std::cout << std::endl; + GULPS_PRINT("\n"); break; } else if(ch == BACKSPACE) @@ -154,17 +158,17 @@ bool read_from_tty(const bool verify, const char *message, epee::wipeable_string while(true) { if(message) - std::cout << message << ": "; + GULPS_PRINT_NOLF(message, ": "); if(!read_from_tty(pass1)) return false; if(verify) { - std::cout << "Confirm password: "; + GULPS_PRINT_NOLF("Confirm password: "); if(!read_from_tty(pass2)) return false; if(pass1 != pass2) { - std::cout << "Passwords do not match! Please try again." << std::endl; + GULPS_PRINT("Passwords do not match! Please try again."); pass1.clear(); pass2.clear(); } diff --git a/src/common/password.h b/src/common/password.h index 1a487537..f4c6fad3 100644 --- a/src/common/password.h +++ b/src/common/password.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/perf_timer.cpp b/src/common/perf_timer.cpp index b747ba45..a46a5826 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,11 +20,11 @@ #include "misc_os_dependent.h" #include -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "perf" +#include "common/gulps.hpp" namespace tools { +GULPS_CAT_MAJOR("perf_timer"); uint64_t get_tick_count() { #if defined(__x86_64__) @@ -73,16 +73,16 @@ uint64_t ticks_to_ns(uint64_t ticks) namespace tools { -el::Level performance_timer_log_level = el::Level::Debug; +gulps::level performance_timer_log_level = gulps::LEVEL_DEBUG; static __thread std::vector *performance_timers = NULL; -void set_performance_timer_log_level(el::Level level) +void set_performance_timer_log_level(gulps::level level) { - if(level != el::Level::Debug && level != el::Level::Trace && level != el::Level::Info && level != el::Level::Warning && level != el::Level::Error && level != el::Level::Fatal) + if(level != gulps::LEVEL_DEBUG && level != gulps::LEVEL_TRACE && level != gulps::LEVEL_INFO && level != gulps::LEVEL_WARN && level != gulps::LEVEL_ERROR) { - MERROR("Wrong log level: " << el::LevelHelper::convertToString(level) << ", using Debug"); - level = el::Level::Debug; + GULPSF_ERROR("Wrong log level: {}, using Debug", gulps::level_to_str(level)); + level = gulps::LEVEL_DEBUG; } performance_timer_log_level = level; } @@ -95,11 +95,12 @@ PerformanceTimer::PerformanceTimer(bool paused) : started(true), paused(paused) ticks = get_tick_count(); } -LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l) : PerformanceTimer(), name(s), cat(cat), unit(unit), level(l) +LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, gulps::level l) : PerformanceTimer(), name(s), cat(cat), unit(unit) { if(!performance_timers) { - MCLOG(level, cat.c_str(), "PERF ----------"); + //TODO LOG BASED ON GIVEN LEVEL "level" + GULPS_CAT_LOG_L1(cat.c_str(), "PERF ----------"); performance_timers = new std::vector(); performance_timers->reserve(16); // how deep before realloc } @@ -112,7 +113,7 @@ LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std for(const auto *tmp : *performance_timers) if(!tmp->paused) ++size; - MCLOG(pt->level, cat.c_str(), "PERF " << std::string((size - 1) * 2, ' ') << " " << pt->name); + GULPS_CAT_LOG_L1(cat.c_str(), "PERF ", std::string((size - 1) * 2, ' '), " ", pt->name); pt->started = true; } } @@ -135,7 +136,8 @@ LoggingPerformanceTimer::~LoggingPerformanceTimer() for(const auto *tmp : *performance_timers) if(!tmp->paused || tmp == this) ++size; - MCLOG(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name); + //TODO LOG BASED ON GIVEN LEVEL "level" + GULPS_CAT_LOG_L1(cat.c_str(), "PERF ", s, std::string(size * 2, ' '), " ", name); if(performance_timers->empty()) { delete performance_timers; diff --git a/src/common/perf_timer.h b/src/common/perf_timer.h index cf84f94c..77e85817 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,7 +18,7 @@ #pragma once -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include #include #include @@ -28,7 +28,7 @@ namespace tools class PerformanceTimer; -extern el::Level performance_timer_log_level; +extern gulps::level performance_timer_log_level; uint64_t get_tick_count(); uint64_t get_ticks_per_ns(); @@ -53,23 +53,22 @@ class PerformanceTimer class LoggingPerformanceTimer : public PerformanceTimer { public: - LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Debug); + LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, gulps::level l = gulps::LEVEL_DEBUG); ~LoggingPerformanceTimer(); private: std::string name; std::string cat; uint64_t unit; - el::Level level; }; -void set_performance_timer_log_level(el::Level level); +void set_performance_timer_log_level(gulps::level level); #define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer pt_##name(#name, "perf.oldlog", unit, tools::performance_timer_log_level) #define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer pt_##name(#name, "perf.oldlog", unit, l) #define PERF_TIMER(name) PERF_TIMER_UNIT(name, 1000000) #define PERF_TIMER_L(name, l) PERF_TIMER_UNIT_L(name, 1000000, l) -#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr pt_##name(new tools::LoggingPerformanceTimer(#name, "perf.oldlog", unit, el::Level::Info)) +#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr pt_##name(new tools::LoggingPerformanceTimer(#name, "perf.oldlog", unit, gulps::LEVEL_INFO)) #define PERF_TIMER_START(name) PERF_TIMER_START_UNIT(name, 1000000) #define PERF_TIMER_STOP(name) \ do \ diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h index f36120b7..1d84f200 100644 --- a/src/common/rpc_client.h +++ b/src/common/rpc_client.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -28,8 +28,11 @@ #include "storages/http_abstract_invoke.h" #include "string_tools.h" +#include "common/gulps.hpp" + namespace tools { +GULPS_CAT_MAJOR("perf_timer"); class t_rpc_client final { private: @@ -53,13 +56,13 @@ class t_rpc_client final bool ok = connection.is_open(); if(!ok) { - fail_msg_writer() << "Couldn't connect to daemon: " << m_http_client.get_host() << ":" << m_http_client.get_port(); + GULPSF_ERROR("Couldn't connect to daemon: {}:{}", m_http_client.get_host(), m_http_client.get_port()); return false; } ok = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT()); if(!ok) { - fail_msg_writer() << "basic_json_rpc_request: Daemon request failed"; + GULPS_ERROR("basic_json_rpc_request: Daemon request failed"); return false; } else @@ -77,13 +80,13 @@ class t_rpc_client final bool ok = connection.is_open(); if(!ok) { - fail_msg_writer() << "Couldn't connect to daemon: " << m_http_client.get_host() << ":" << m_http_client.get_port(); + GULPSF_ERROR("Couldn't connect to daemon: {}:{}", m_http_client.get_host(), m_http_client.get_port()); return false; } ok = epee::net_utils::invoke_http_json_rpc("/json_rpc", method_name, req, res, m_http_client, t_http_connection::TIMEOUT()); if(!ok || res.status != CORE_RPC_STATUS_OK) // TODO - handle CORE_RPC_STATUS_BUSY ? { - fail_msg_writer() << fail_msg << " -- json_rpc_request: " << res.status; + GULPSF_ERROR("{} -- json_rpc_request: ", fail_msg, res.status); return false; } else @@ -101,13 +104,13 @@ class t_rpc_client final bool ok = connection.is_open(); if(!ok) { - fail_msg_writer() << "Couldn't connect to daemon: " << m_http_client.get_host() << ":" << m_http_client.get_port(); + GULPSF_ERROR("Couldn't connect to daemon: {}:{}", m_http_client.get_host(), m_http_client.get_port()); return false; } ok = epee::net_utils::invoke_http_json(relative_url, req, res, m_http_client, t_http_connection::TIMEOUT()); if(!ok || res.status != CORE_RPC_STATUS_OK) // TODO - handle CORE_RPC_STATUS_BUSY ? { - fail_msg_writer() << fail_msg << "-- rpc_request: " << res.status; + GULPSF_ERROR("{}-- rpc_request: {}", fail_msg, res.status); return false; } else diff --git a/src/common/scoped_message_writer.h b/src/common/scoped_message_writer.h index bd902ecf..a6652908 100644 --- a/src/common/scoped_message_writer.h +++ b/src/common/scoped_message_writer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,16 +18,10 @@ #pragma once -#include "misc_log_ex.h" +#include "readline_buffer.h" #include -#ifdef HAVE_READLINE -#include "readline_buffer.h" -#define PAUSE_READLINE() \ - rdln::suspend_readline pause_readline; -#else -#define PAUSE_READLINE() -#endif +#include "common/gulps.hpp" namespace tools { @@ -37,17 +31,17 @@ namespace tools /************************************************************************/ class scoped_message_writer { + GULPS_CAT_MAJOR("scpd_msg_wrt"); private: bool m_flush; std::stringstream m_oss; - epee::console_colors m_color; - bool m_bright; - el::Level m_log_level; + gulps::color m_color; + gulps::level m_log_level; public: scoped_message_writer( - epee::console_colors color = epee::console_color_default, bool bright = false, std::string &&prefix = std::string(), el::Level log_level = el::Level::Info) - : m_flush(true), m_color(color), m_bright(bright), m_log_level(log_level) + gulps::color color = gulps::COLOR_WHITE, std::string &&prefix = std::string(), gulps::level log_level = gulps::LEVEL_INFO) + : m_flush(true), m_color(color), m_log_level(log_level) { m_oss << prefix; } @@ -85,37 +79,25 @@ class scoped_message_writer { m_flush = false; - MCLOG_FILE(m_log_level, "msgwriter", m_oss.str()); - - if(epee::console_color_default == m_color) - { - std::cout << m_oss.str(); - } - else - { - PAUSE_READLINE(); - set_console_color(m_color, m_bright); - std::cout << m_oss.str(); - epee::reset_console_color(); - } - std::cout << std::endl; + GULPS_OUTPUT(gulps::OUT_LOG_0, m_log_level, gulps_major_cat::c_str(), "msgwriter", m_color, m_oss.str()); + GULPS_PRINT_CLR(m_color, m_oss.str()); } } }; inline scoped_message_writer success_msg_writer(bool color = true) { - return scoped_message_writer(color ? epee::console_color_green : epee::console_color_default, false, std::string(), el::Level::Info); + return scoped_message_writer(color ? gulps::COLOR_GREEN : gulps::COLOR_WHITE, std::string(), gulps::LEVEL_PRINT); } -inline scoped_message_writer msg_writer(epee::console_colors color = epee::console_color_default) +inline scoped_message_writer msg_writer(gulps::color color = gulps::COLOR_WHITE) { - return scoped_message_writer(color, false, std::string(), el::Level::Info); + return scoped_message_writer(color, std::string(), gulps::LEVEL_PRINT); } inline scoped_message_writer fail_msg_writer() { - return scoped_message_writer(epee::console_color_red, true, "Error: ", el::Level::Error); + return scoped_message_writer(gulps::COLOR_RED, "Error: ", gulps::LEVEL_ERROR); } } // namespace tools diff --git a/src/common/sfinae_helpers.h b/src/common/sfinae_helpers.h index 9c8a2aac..b5812445 100644 --- a/src/common/sfinae_helpers.h +++ b/src/common/sfinae_helpers.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/stack_trace.cpp b/src/common/stack_trace.cpp index 9de04517..c04730cc 100644 --- a/src/common/stack_trace.cpp +++ b/src/common/stack_trace.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,12 +16,12 @@ // 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. + #if !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__ #define USE_UNWIND #else #define ELPP_FEATURE_CRASH_LOG 1 #endif -#include "easylogging++/easylogging++.h" #include #ifdef USE_UNWIND @@ -33,13 +33,11 @@ #include #endif #include "common/stack_trace.h" -#include "misc_log_ex.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "stacktrace" +#include "common/gulps.hpp" -#define ST_LOG(x) CINFO(el::base::Writer, el::base::DispatchAction::FileOnlyLog, RYO_DEFAULT_LOG_CATEGORY) << x +GULPS_CAT_MAJOR("stk_trace"); // from http://stackoverflow.com/questions/11665829/how-can-i-print-stack-trace-for-caught-exceptions-in-c-code-injection-in-c @@ -110,18 +108,18 @@ void log_stack_trace(const char *msg) #endif if(msg) - ST_LOG(msg); - ST_LOG("Unwound call stack:"); + GULPS_LOG_L0(msg); + GULPS_LOG_L0("Unwound call stack:"); #ifdef USE_UNWIND if(unw_getcontext(&ctx) < 0) { - ST_LOG("Failed to create unwind context"); + GULPS_LOG_L0("Failed to create unwind context"); return; } if(unw_init_local(&cur, &ctx) < 0) { - ST_LOG("Failed to find the first unwind frame"); + GULPS_LOG_L0("Failed to find the first unwind frame"); return; } for(level = 1; level < 999; ++level) @@ -129,34 +127,28 @@ void log_stack_trace(const char *msg) int ret = unw_step(&cur); if(ret < 0) { - ST_LOG("Failed to find the next frame"); + GULPS_LOG_L0("Failed to find the next frame"); return; } if(ret == 0) break; if(unw_get_reg(&cur, UNW_REG_IP, &ip) < 0) { - ST_LOG(" " << std::setw(4) << level); + GULPSF_LOG_L0("{:<4}", level); continue; } if(unw_get_proc_name(&cur, sym, sizeof(sym), &off) < 0) { - ST_LOG(" " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip); + GULPSF_LOG_L0("{:<4}{:<20#0.x}", level, ip); continue; } dsym = abi::__cxa_demangle(sym, NULL, NULL, &status); - ST_LOG(" " << std::setw(4) << level << std::setbase(16) << std::setw(20) << "0x" << ip << " " << (!status && dsym ? dsym : sym) << " + " - << "0x" << off); + GULPSF_LOG_L0("{:<4}{:<20#0.x} {#0.x} + {#0.x}", level, ip, (!status && dsym ? dsym : sym), off); free(dsym); } #else - std::stringstream ss; - ss << el::base::debug::StackTrace(); - std::vector lines; - std::string s = ss.str(); - boost::split(lines, s, boost::is_any_of("\n")); - for(const auto &line : lines) - ST_LOG(line); + //TODO PRINTING STACK + GULPS_LOG_L0(""); #endif } diff --git a/src/common/stack_trace.h b/src/common/stack_trace.h index f7d4f7b3..1f5e2c3a 100644 --- a/src/common/stack_trace.h +++ b/src/common/stack_trace.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/string.cpp b/src/common/string.cpp new file mode 100644 index 00000000..57eef7de --- /dev/null +++ b/src/common/string.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2018, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + + +#include + +std::string operator ""_s(const char * str, size_t len) { + return std::string(str, len); +} diff --git a/src/common/string.hpp b/src/common/string.hpp new file mode 100644 index 00000000..a878b36d --- /dev/null +++ b/src/common/string.hpp @@ -0,0 +1,54 @@ +// Copyright (c) 2018, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +#pragma once + +#include + +/** convert a C string into a C++ std::string + * + * @code{cpp} + * auto foo = "Hello World!"_s; // type of foo is std::string + * @endcode + */ +std::string operator ""_s(const char * str, size_t len); diff --git a/src/common/thdq.hpp b/src/common/thdq.hpp new file mode 100644 index 00000000..8b3666fb --- /dev/null +++ b/src/common/thdq.hpp @@ -0,0 +1,133 @@ +// Copyright (c) 2018, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +#pragma once + +#include +#include +#include +#include +#include + +template +class thdq +{ +public: + + bool pop(T& item) + { + std::unique_lock mlock(mutex_); + while (queue_.empty() && !finish) { cond_.wait(mlock); } + if(!queue_.empty()) + { + item = std::move(queue_.front()); + queue_.pop(); + mlock.unlock(); + size_cond_.notify_all(); + return true; + } + return false; + } + + std::unique_lock get_lock() + { + return std::unique_lock(mutex_, std::defer_lock); + } + + bool wait_for_pop(std::unique_lock& lck) + { + lck.lock(); + while (queue_.empty() && !finish) { cond_.wait(lck); } + bool has_pop = !queue_.empty(); + if(!has_pop) { lck.unlock(); } + return has_pop; + } + + size_t wait_for_size(size_t q_size) + { + std::unique_lock mlock(mutex_); + while (queue_.size() > q_size) { size_cond_.wait(mlock); } + return queue_.size(); + } + + T pop(std::unique_lock& lck) + { + T item = std::move(queue_.front()); + queue_.pop(); + lck.unlock(); + size_cond_.notify_all(); + return item; + } + + void push(const T& item) + { + std::unique_lock mlock(mutex_); + if(finish) return; + queue_.push(item); + mlock.unlock(); + cond_.notify_one(); + } + + void push(T&& item) + { + std::unique_lock mlock(mutex_); + if(finish) return; + queue_.push(std::move(item)); + mlock.unlock(); + cond_.notify_one(); + } + + void set_finish_flag() + { + std::unique_lock mlock(mutex_); + finish = true; + cond_.notify_all(); + } + +private: + std::queue queue_; + std::mutex mutex_; + std::condition_variable cond_; + std::condition_variable size_cond_; + bool finish = false; +}; diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 3d62ede3..a41b5d39 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -15,8 +15,8 @@ // 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 "common/threadpool.h" -#include "misc_log_ex.h" #include #include @@ -86,7 +86,7 @@ threadpool::waiter::~waiter() { boost::unique_lock lock(mt); if(num) - MERROR("wait should have been called before waiter dtor - waiting now"); + GULPS_ERROR("wait should have been called before waiter dtor - waiting now"); } try { diff --git a/src/common/threadpool.h b/src/common/threadpool.h index 97edc541..f7feaff4 100644 --- a/src/common/threadpool.h +++ b/src/common/threadpool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -17,6 +17,8 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once +#include "common/gulps.hpp" + #include #include #include @@ -31,6 +33,7 @@ namespace tools //! A global thread pool class threadpool { + GULPS_CAT_MAJOR("thdpool"); public: static threadpool &getInstance() { diff --git a/src/common/unordered_containers_boost_serialization.h b/src/common/unordered_containers_boost_serialization.h index b4333537..1becb7e3 100644 --- a/src/common/unordered_containers_boost_serialization.h +++ b/src/common/unordered_containers_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/updates.cpp b/src/common/updates.cpp index 614c45b3..b089924a 100644 --- a/src/common/updates.cpp +++ b/src/common/updates.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,12 +18,12 @@ #include "updates.h" #include "dns_utils.h" -#include "misc_log_ex.h" #include "util.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "updates" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("updates"); namespace tools { @@ -34,7 +34,7 @@ bool check_updates(const std::string &software, const std::string &buildtag, std std::vector records; bool found = false; - MDEBUG("Checking updates for " << buildtag << " " << software); + GULPSF_LOG_L0("Checking updates for {} {}", buildtag, software); // All four MoneroPulse domains have DNSSEC on and valid static const std::vector dns_urls = { @@ -53,7 +53,7 @@ bool check_updates(const std::string &software, const std::string &buildtag, std boost::split(fields, record, boost::is_any_of(":")); if (fields.size() != 4) { - MWARNING("Updates record does not have 4 fields: " << record); + GULPS_WARN("Updates record does not have 4 fields: ", record); continue; } @@ -66,7 +66,7 @@ bool check_updates(const std::string &software, const std::string &buildtag, std alnum = false; if (hash.size() != 64 && !alnum) { - MWARNING("Invalid hash: " << hash); + GULPS_WARN("Invalid hash: ", hash); continue; } @@ -77,13 +77,13 @@ bool check_updates(const std::string &software, const std::string &buildtag, std if (cmp > 0) continue; if (cmp == 0 && hash != fields[3]) - MWARNING("Two matches found for " << software << " version " << version << " on " << buildtag); + GULPSF_WARN("Two matches found for {} verion {} on {}", software, version, buildtag); } version = fields[2]; hash = fields[3]; - MINFO("Found new version " << version << " with hash " << hash); + GULPSF_INFO("Found new version {} with has {}", version, hash); found = true; } return found; diff --git a/src/common/updates.h b/src/common/updates.h index a58ff571..0aad4a88 100644 --- a/src/common/updates.h +++ b/src/common/updates.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/common/util.cpp b/src/common/util.cpp index 8453937a..e2cd417e 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -52,8 +52,10 @@ using namespace epee; #include #include + namespace tools { +GULPS_CAT_MAJOR("cmn_util"); std::function signal_handler::m_handler; private_file::private_file() noexcept : m_handle(), m_filename() {} @@ -406,7 +408,7 @@ std::string get_windows_version_display_string() } else { - printf("This sample does not support this version of Windows.\n"); + GULPS_PRINT("This sample does not support this version of Windows.\n"); return pszOS; } } @@ -443,7 +445,7 @@ std::string get_special_folder_path(int nfolder, bool iscreate) return folder_name; } - LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path."); + GULPS_LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path."); return ""; } #endif @@ -486,11 +488,11 @@ bool create_directories_if_necessary(const std::string &path) bool res = fs::create_directories(fs_path, ec); if(res) { - LOG_PRINT_L2("Created directory: " << path); + GULPS_LOG_L2("Created directory: ", path); } else { - LOG_PRINT_L2("Can't create directory: " << path << ", err: " << ec.message()); + GULPSF_LOG_L2("Can't create directory: {}, err {}", path, ec.message()); } return res; @@ -533,7 +535,7 @@ static bool unbound_built_with_threads() // if no threads, bails out early with UB_NOERROR, otherwise fails with UB_AFTERFINAL id already finalized bool with_threads = ub_ctx_async(ctx, 1) != 0; // UB_AFTERFINAL is not defined in public headers, check any error ub_ctx_delete(ctx); - MINFO("libunbound was built " << (with_threads ? "with" : "without") << " threads"); + GULPSF_LOG_L0("libunbound was built {} threads", (with_threads ? "with" : "without") ); return with_threads; } @@ -599,8 +601,6 @@ static void setup_crash_dump() bool on_startup() { - mlog_configure("", true); - setup_crash_dump(); sanitize_locale(); @@ -608,7 +608,7 @@ bool on_startup() #ifdef __GLIBC__ const char *ver = gnu_get_libc_version(); if(!strcmp(ver, "2.25")) - MCLOG_RED(el::Level::Warning, "global", "Running with glibc " << ver << ", hangs may occur - change glibc version if possible"); + GULPS_CAT_WARN("global", "Running with glibc ", ver, " hangs may occur - change glibc version if possible"); #endif #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(LIBRESSL_VERSION_TEXT) @@ -618,8 +618,7 @@ bool on_startup() #endif if(!unbound_built_with_threads()) - MCLOG_RED(el::Level::Warning, "global", "libunbound was not built with threads enabled - crashes may occur"); - + GULPS_CAT_WARN("global", "libunbound was not built with threads enabled - crashes may occur"); return true; } void set_strict_default_file_permissions(bool strict) @@ -661,12 +660,12 @@ bool is_local_address(const std::string &address) epee::net_utils::http::url_content u_c; if(!epee::net_utils::parse_url(address, u_c)) { - MWARNING("Failed to determine whether address '" << address << "' is local, assuming not"); + GULPSF_WARN("Failed to determine whether address '{}' is local, assuming not", address ); return false; } if(u_c.host.empty()) { - MWARNING("Failed to determine whether address '" << address << "' is local, assuming not"); + GULPSF_WARN("Failed to determine whether address '{}' is local, assuming not", address ); return false; } @@ -680,13 +679,13 @@ bool is_local_address(const std::string &address) const boost::asio::ip::tcp::endpoint &ep = *i; if(ep.address().is_loopback()) { - MDEBUG("Address '" << address << "' is local"); + GULPSF_LOG_L0("Address '{}' is local", address ); return true; } ++i; } - MDEBUG("Address '" << address << "' is not local"); + GULPSF_LOG_L0("Address '{}' is not local", address ); return false; } int vercmp(const char *v0, const char *v1) diff --git a/src/common/util.h b/src/common/util.h index 8d197af3..2b53467f 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,16 +30,17 @@ #include #ifdef _WIN32 -#include "misc_log_ex.h" #include "windows.h" #endif #include "crypto/hash.h" +#include "common/gulps.hpp" + /*! \brief Various Tools * - * - * + * + * */ namespace tools { @@ -95,12 +96,12 @@ std::string get_default_data_dir(); #ifdef WIN32 /** - * @brief + * @brief * * @param nfolder * @param iscreate * - * @return + * @return */ std::string get_special_folder_path(int nfolder, bool iscreate); #endif @@ -115,7 +116,7 @@ std::string get_os_version_string(); /*! \brief creates directories for a path * - * wrapper around boost::filesyste::create_directories. + * wrapper around boost::filesyste::create_directories. * (ensure-directory-exists): greenspun's tenth rule in action! */ bool create_directories_if_necessary(const std::string &path); @@ -168,7 +169,8 @@ class signal_handler } else { - MGINFO_RED("Got control signal " << type << ". Exiting without saving..."); + GULPS_CAT_MAJOR("cmn_util"); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_RED, "Got control signal {}. Exiting without saving...", type); return FALSE; } return TRUE; diff --git a/src/common/varint.h b/src/common/varint.h index 9788a867..493c1d46 100644 --- a/src/common/varint.h +++ b/src/common/varint.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 59c2e3d3..0181eec0 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -43,6 +43,7 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(crypto_sources + ${ASM_FILE} chacha.c crypto-ops-data.c crypto-ops.c @@ -57,6 +58,12 @@ set(crypto_sources pow_hash/cn_slow_hash_intel_avx2.cpp pow_hash/cn_slow_hash_hard_arm.cpp) +if(HAVE_EC_64) + list(APPEND crypto_sources + ecops64/ecops64-c.c + ecops64/ecops64-data.c + ecops64/ecops64.asm) +endif() if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") @@ -80,6 +87,11 @@ set(crypto_private_headers random.hpp pow_hash/cn_slow_hash.hpp) +if(HAVE_EC_64) + list(APPEND crypto_private_headers + ecops64/ecops64.h) +endif() + ryo_private_headers(cncrypto ${crypto_private_headers}) ryo_add_library(cncrypto @@ -90,6 +102,7 @@ target_link_libraries(cncrypto PUBLIC epee ${Boost_SYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) @@ -104,6 +117,7 @@ if(BUILD_TESTS) PUBLIC epee ${Boost_SYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) target_compile_definitions(cncrypto_for_test diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index dacda591..5046c17d 100644 --- a/src/crypto/chacha.h +++ b/src/crypto/chacha.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index e7ddee0b..313afe07 100644 --- a/src/crypto/crypto-ops-data.c +++ b/src/crypto/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index f4d1f5a9..7bd7adc1 100644 --- a/src/crypto/crypto-ops.c +++ b/src/crypto/crypto-ops.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h index 8b78000d..82289cee 100644 --- a/src/crypto/crypto-ops.h +++ b/src/crypto/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 7a683f80..a48fba6e 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -35,6 +35,10 @@ #include "warnings.h" #include "random.hpp" +#ifdef HAVE_EC_64 +# include "ecops64/ecops64.h" +#endif + namespace { static void local_abort(const char *msg) @@ -86,9 +90,9 @@ static inline bool scalar_ok(const unsigned char *k) { // l = 2^252 + 27742317777372353535851937790883648493 // l15 = 15*l - //unsigned char l15[32] = { - // 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, - // 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 + //unsigned char l15[32] = { + // 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, + // 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 //}; // Scalar above in little-endian words constexpr uint64_t lw3 = 0xf000000000000000ull; @@ -144,10 +148,10 @@ void hash_to_scalar(const void *data, size_t length, ec_scalar &res) sc_reduce32(&res); } -/* +/* * generate public and secret keys from a random 256-bit integer * TODO: allow specifying random value (for wallet recovery) - * + * */ secret_key crypto_ops::generate_legacy_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key, bool recover) { @@ -299,6 +303,46 @@ bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const k return true; } +#ifdef HAVE_EC_64 + +bool crypto_ops::generate_key_derivation_64(const public_key &key1, const secret_key &key2, key_derivation &derivation) +{ + ge64_p3 point; + ge64_p2 point2; + ge64_p1p1 point3; + assert(sc_check(&key2) == 0); + if(ge64_frombytes_vartime(&point, &key1) != 0) + { + return false; + } + ge64_scalarmult(&point2, &unwrap(key2), &point); + ge64_mul8(&point3, &point2); + ge64_p1p1_to_p2(&point2, &point3); + ge64_tobytes(&derivation, &point2); + return true; +} + +bool crypto_ops::derive_subaddress_public_key_64(const public_key& out_key, const key_derivation& derivation, const std::size_t output_index, public_key &derived_key) +{ + ec_scalar scalar; + ge64_p3 point1; + ge64_p3 point3; + ge64_p1p1 point4; + ge64_p2 point5; + if(ge64_frombytes_vartime(&point1, &out_key) != 0) + { + return false; + } + derivation_to_scalar(derivation, output_index, scalar); + ge64_scalarmult_base(&point3, &scalar); + ge64_sub(&point4, &point1, &point3); + ge64_p1p1_to_p2(&point5, &point4); + ge64_tobytes(&derived_key, &point5); + return true; +} + +#endif + struct s_comm { hash h; diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 14cc343f..2305d38a 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -29,6 +29,7 @@ #include #include +#include "fmt/format.h" #include "common/util.h" #include "generic-ops.h" #include "hash.h" @@ -144,6 +145,12 @@ class crypto_ops friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); static bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); friend bool derive_subaddress_public_key(const public_key &, const key_derivation &, std::size_t, public_key &); +#ifdef HAVE_EC_64 + static bool generate_key_derivation_64(const public_key &, const secret_key &, key_derivation &); + friend bool generate_key_derivation_64(const public_key &, const secret_key &, key_derivation &); + static bool derive_subaddress_public_key_64(const public_key &, const key_derivation &, std::size_t, public_key &); + friend bool derive_subaddress_public_key_64(const public_key &, const key_derivation &, std::size_t, public_key &); +#endif static void generate_signature(const hash &, const public_key &, const secret_key &, signature &); friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &); static bool check_signature(const hash &, const public_key &, const signature &); @@ -249,6 +256,17 @@ inline bool derive_subaddress_public_key(const public_key &out_key, const key_de { return crypto_ops::derive_subaddress_public_key(out_key, derivation, output_index, result); } +#ifdef HAVE_EC_64 +inline bool generate_key_derivation_64(const public_key &key1, const secret_key &key2, key_derivation &derivation) +{ + return crypto_ops::generate_key_derivation_64(key1, key2, derivation); +} + +inline bool derive_subaddress_public_key_64(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result) +{ + return crypto_ops::derive_subaddress_public_key_64(out_key, derivation, output_index, result); +} +#endif /* Generation and checking of a standard signature. */ @@ -261,7 +279,7 @@ inline bool check_signature(const hash &prefix_hash, const public_key &pub, cons return crypto_ops::check_signature(prefix_hash, pub, sig); } -/* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key +/* Generation and checking of a tx proof; given a tx pubkey R, the recipient's view pubkey A, and the key * derivation D, the signature proves the knowledge of the tx secret key r such that R=r*G and D=r*A * When the recipient's address is a subaddress, the tx pubkey R is defined as R=r*B where B is the recipient's spend pubkey */ @@ -344,6 +362,19 @@ const static crypto::public_key null_pkey = boost::value_initialized(); } +namespace fmt +{ +template <> +struct formatter : formatter +{ + template + auto format(const crypto::public_key &pk, FormatContext &ctx) -> decltype(ctx.out()) + { + return formatter::format(epee::string_tools::pod_to_hex(pk), ctx); + } +}; +} + CRYPTO_MAKE_HASHABLE(public_key) CRYPTO_MAKE_HASHABLE(secret_key) CRYPTO_MAKE_HASHABLE(secret_key_16) diff --git a/src/crypto/crypto_ops_builder/crypto-ops-data.c b/src/crypto/crypto_ops_builder/crypto-ops-data.c index 7868f672..45f4de74 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops-data.c +++ b/src/crypto/crypto_ops_builder/crypto-ops-data.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto_ops_builder/crypto-ops-old.c b/src/crypto/crypto_ops_builder/crypto-ops-old.c index fe3f3b6a..b92c3746 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops-old.c +++ b/src/crypto/crypto_ops_builder/crypto-ops-old.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto_ops_builder/crypto-ops.h b/src/crypto/crypto_ops_builder/crypto-ops.h index 96cdf68b..3b7f6ded 100644 --- a/src/crypto/crypto_ops_builder/crypto-ops.h +++ b/src/crypto/crypto_ops_builder/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py b/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py index db7315ca..15cb8dc2 100644 --- a/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py +++ b/src/crypto/crypto_ops_builder/ref10CommentedCombined/MakeCryptoOps.py @@ -15,7 +15,7 @@ a = "" license = textwrap.dedent("""\ - // Copyright (c) 2018, Ryo Currency Project + // Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h b/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h index bf86d145..7d6c9744 100644 --- a/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h +++ b/src/crypto/crypto_ops_builder/ref10CommentedCombined/crypto-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/ecops64/ecops64-c.c b/src/crypto/ecops64/ecops64-c.c new file mode 100644 index 00000000..58369bb1 --- /dev/null +++ b/src/crypto/ecops64/ecops64-c.c @@ -0,0 +1,502 @@ +// Copyright (c) 2019, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see +// ORIGINAL-LICENSE for details All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This +// includes +// posting the work online, or hosting copies of the modified work for +// download. +// +// 4. Any derivative version of this work is also covered by this license, +// including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may +// be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in +// accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this +// licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +// Based on Dr Bernstein's public domain code. +// https://bench.cr.yp.to/supercop.html + +#include "ecops64.h" + +static inline void fe64_setint(fe64 r, unsigned int v) +{ + r[0] = v; + r[1] = 0; + r[2] = 0; + r[3] = 0; +} + +static inline void fe64_copy(fe64 t, const fe64 x) +{ + t[0] = x[0]; + t[1] = x[1]; + t[2] = x[2]; + t[3] = x[3]; +} + +static inline void fe64_neg(fe64 r, const fe64 x) +{ + fe64 t; + fe64_setint(t, 0); + fe64_sub(r, t, x); +} + +static inline void fe64_unpack(fe64 r, const unsigned char x[32]) +{ + r[0] = *(unsigned long long*)x; + r[1] = *(((unsigned long long*)x) + 1); + r[2] = *(((unsigned long long*)x) + 2); + r[3] = *(((unsigned long long*)x) + 3); + r[3] &= 0x7fffffffffffffffULL; +} + +static inline void fe64_pack(unsigned char r[32], const fe64 x) +{ + fe64 t; + fe64_copy(t, x); + fe64_reduce(t); + + *(uint64_t*)r = t[0]; + *(((uint64_t*)r) + 1) = t[1]; + *(((uint64_t*)r) + 2) = t[2]; + *(((uint64_t*)r) + 3) = t[3]; +} + +static inline int fe64_iszero_vartime(const fe64 x) +{ + fe64 t; + fe64_copy(t, x); + fe64_reduce(t); + + if(t[0]) + return 0; + if(t[1]) + return 0; + if(t[2]) + return 0; + if(t[3]) + return 0; + + return 1; +} + +static inline int fe64_isnegative(const fe64 f) +{ + fe64 t; + fe64_copy(t, f); + fe64_reduce(t); + + return (unsigned char)t[0] & 1; +} + +void fe64_divpowm1(fe64 r, const fe64 u, const fe64 v) +{ + fe64 v3, uv7, t0, t1, t2; + size_t i; + + fe64_square(v3, v); + fe64_mul(v3, v3, v); /* v3 = v^3 */ + fe64_square(uv7, v3); + fe64_mul(uv7, uv7, v); + fe64_mul(uv7, uv7, u); /* uv7 = uv^7 */ + + /*fe_pow22523(uv7, uv7);*/ + /* From fe_pow22523.c */ + fe64_square(t0, uv7); + fe64_square(t1, t0); + fe64_square(t1, t1); + fe64_mul(t1, uv7, t1); + fe64_mul(t0, t0, t1); + fe64_square(t0, t0); + fe64_mul(t0, t1, t0); + fe64_square(t1, t0); + + for(i = 0; i < 4; ++i) + fe64_square(t1, t1); + + fe64_mul(t0, t1, t0); + fe64_square(t1, t0); + + for(i = 0; i < 9; ++i) + fe64_square(t1, t1); + + fe64_mul(t1, t1, t0); + fe64_square(t2, t1); + for(i = 0; i < 19; ++i) + fe64_square(t2, t2); + + fe64_mul(t1, t2, t1); + for(i = 0; i < 10; ++i) + fe64_square(t1, t1); + + fe64_mul(t0, t1, t0); + fe64_square(t1, t0); + for(i = 0; i < 49; ++i) + fe64_square(t1, t1); + + fe64_mul(t1, t1, t0); + fe64_square(t2, t1); + for(i = 0; i < 99; ++i) + fe64_square(t2, t2); + + fe64_mul(t1, t2, t1); + for(i = 0; i < 50; ++i) + fe64_square(t1, t1); + + fe64_mul(t0, t1, t0); + fe64_square(t0, t0); + fe64_square(t0, t0); + fe64_mul(t0, t0, uv7); + + /* End fe_pow22523.c */ + /* t0 = (uv^7)^((q-5)/8) */ + fe64_mul(t0, t0, v3); + fe64_mul(r, t0, u); /* u^(m+1)v^(-(m+1)) */ +} + +void fe64_invert(fe64 out, const fe64 z) +{ + fe64 t0, t1, t2, t3; + int i; + + fe64_square(t0, z); + fe64_square(t1, t0); + fe64_square(t1, t1); + fe64_mul(t1, z, t1); + fe64_mul(t0, t0, t1); + fe64_square(t2, t0); + fe64_mul(t1, t1, t2); + fe64_square(t2, t1); + + for(i = 0; i < 4; ++i) + fe64_square(t2, t2); + + fe64_mul(t1, t2, t1); + fe64_square(t2, t1); + for(i = 0; i < 9; ++i) + fe64_square(t2, t2); + + fe64_mul(t2, t2, t1); + fe64_square(t3, t2); + for(i = 0; i < 19; ++i) + fe64_square(t3, t3); + + fe64_mul(t2, t3, t2); + fe64_square(t2, t2); + for(i = 0; i < 9; ++i) + fe64_square(t2, t2); + + fe64_mul(t1, t2, t1); + fe64_square(t2, t1); + for(i = 0; i < 49; ++i) + fe64_square(t2, t2); + + fe64_mul(t2, t2, t1); + fe64_square(t3, t2); + for(i = 0; i < 99; ++i) + fe64_square(t3, t3); + + fe64_mul(t2, t3, t2); + fe64_square(t2, t2); + for(i = 0; i < 49; ++i) + fe64_square(t2, t2); + + fe64_mul(t1, t2, t1); + fe64_square(t1, t1); + + for(i = 0; i < 4; ++i) + fe64_square(t1, t1); + + fe64_mul(out, t1, t0); +} + +void ge64_p3_to_p2(ge64_p2* r, const ge64_p3* p) +{ + fe64_copy(r->x, p->x); + fe64_copy(r->y, p->y); + fe64_copy(r->z, p->z); +} + +void ge64_mul8(ge64_p1p1* r, const ge64_p2* t) +{ + ge64_p2 u; + ge64_p2_dbl(r, t); + ge64_p1p1_to_p2(&u, r); + ge64_p2_dbl(r, &u); + ge64_p1p1_to_p2(&u, r); + ge64_p2_dbl(r, &u); +} + +/* d */ +extern const fe64 fe64_d; +extern const fe64 fe64_2d; +/* sqrt(-1) */ +extern const fe64 fe64_sqrtm1; + +/* return 0 on success, -1 otherwise */ +int ge64_frombytes_vartime(ge64_p3* h, const unsigned char p[32]) +{ + fe64 u, v, vxx, check; + + fe64_unpack(h->y, p); + + fe64_setint(h->z, 1); + fe64_square(u, h->y); /* x = y^2 */ + fe64_mul(v, u, fe64_d); /* den = dy^2 */ + fe64_sub(u, u, h->z); /* x = y^2-1 */ + fe64_add(v, v, h->z); /* den = dy^2+1 */ + + fe64_divpowm1(h->x, u, v); + + fe64_square(vxx, h->x); + fe64_mul(vxx, vxx, v); + fe64_sub(check, vxx, u); + + if(!fe64_iszero_vartime(check)) + { + fe64_add(check, vxx, u); + if(!fe64_iszero_vartime(check)) + return -1; + fe64_mul(h->x, h->x, fe64_sqrtm1); + } + + if(fe64_isnegative(h->x) != (p[31] >> 7)) + { + if(fe64_iszero_vartime(h->x)) + return -1; + fe64_neg(h->x, h->x); + } + + fe64_mul(h->t, h->x, h->y); + return 0; +} + +void ge64_tobytes(unsigned char s[32], const ge64_p2* h) +{ + fe64 recip, x, y; + + fe64_invert(recip, h->z); + fe64_mul(x, h->x, recip); + fe64_mul(y, h->y, recip); + fe64_pack(s, y); + + s[31] ^= fe64_isnegative(x) << 7; +} + +/* no overflow for this particular order */ +extern const uint64_t sc64_reduce_order[16]; + +static inline uint64_t smaller(uint64_t a, uint64_t b) +{ + uint64_t atop = a >> 32; + uint64_t abot = a & 4294967295; + uint64_t btop = b >> 32; + uint64_t bbot = b & 4294967295; + uint64_t atopbelowbtop = (atop - btop) >> 63; + uint64_t atopeqbtop = ((atop ^ btop) - 1) >> 63; + uint64_t abotbelowbbot = (abot - bbot) >> 63; + return atopbelowbtop | (atopeqbtop & abotbelowbbot); +} + +void sc64_reduce32(unsigned char x[32]) +{ + uint64_t rv0, rv1, rv2, rv3; + int j; + + /* assuming little-endian */ + rv0 = *(uint64_t*)x; + rv1 = *(((uint64_t*)x) + 1); + rv2 = *(((uint64_t*)x) + 2); + rv3 = *(((uint64_t*)x) + 3); + + for(j = 3; j >= 0; j--) + { + uint64_t t0, t1, t2, t3; + uint64_t b = sc64_reduce_order[4 * j + 0]; + t0 = rv0 - b; + b = smaller(rv0, b); + + b += sc64_reduce_order[4 * j + 1]; + t1 = rv1 - b; + b = smaller(rv1, b); + + b += sc64_reduce_order[4 * j + 2]; + t2 = rv2 - b; + b = smaller(rv2, b); + + b += sc64_reduce_order[4 * j + 3]; + t3 = rv3 - b; + b = smaller(rv3, b); + + uint64_t mask = b - 1; + rv0 ^= mask & (rv0 ^ t0); + rv1 ^= mask & (rv1 ^ t1); + rv2 ^= mask & (rv2 ^ t2); + rv3 ^= mask & (rv3 ^ t3); + } + + *(uint64_t*)x = rv0; + *(((uint64_t*)x) + 1) = rv1; + *(((uint64_t*)x) + 2) = rv2; + *(((uint64_t*)x) + 3) = rv3; +} + +static inline void mult_extract(signed char b[64], const unsigned char s[32]) +{ + int carry, carry2; + + carry = 0; /* 0..1 */ + for(uint64_t i = 0; i < 31; i++) + { + carry += s[i]; /* 0..256 */ + carry2 = (carry + 8) >> 4; /* 0..16 */ + b[2 * i] = carry - (carry2 << 4); /* -8..7 */ + carry = (carry2 + 8) >> 4; /* 0..1 */ + b[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ + } + + carry += s[31]; /* 0..128 */ + carry2 = (carry + 8) >> 4; /* 0..8 */ + b[62] = carry - (carry2 << 4); /* -8..7 */ + b[63] = carry2; /* 0..8 */ +} + +/* Multiples of the base point in Niels' representation */ +extern const ge64_niels ge64_base_multiples_niels[]; +extern const fe64 ge64_base_mult0_x[]; +extern const fe64 ge64_base_mult0_y[]; +extern const fe64 ge64_base_mult0_t[]; + +void ge64_scalarmult_base(ge64_p3* r, const unsigned char s[32]) +{ + signed char b[64]; + mult_extract(b, s); + + fe64_copy(r->x, ge64_base_mult0_x[b[0] + 8]); + fe64_copy(r->y, ge64_base_mult0_y[b[0] + 8]); + fe64_copy(r->t, ge64_base_mult0_t[b[0] + 8]); + fe64_setint(r->z, 2); + + for(uint64_t i = 1; i < 64; i++) + { + uint64_t idx = (i - 1) * 17 + b[i] + 8; + ge64_nielsadd2(r, &ge64_base_multiples_niels[idx]); + } +} + +static inline void ge64_p3_to_pniels(ge64_pniels* r, const ge64_p3* p) +{ + fe64_add(r->xaddy, p->x, p->y); + fe64_sub(r->ysubx, p->y, p->x); + fe64_copy(r->z, p->z); + fe64_mul(r->t2d, p->t, fe64_2d); +} + +/* Assumes that a[31] <= 127 */ +void ge64_scalarmult(ge64_p2* r, const unsigned char a[32], const ge64_p3* A) +{ + signed char e[64]; + mult_extract(e, a); + + ge64_pniels Ai[17]; + + fe64_setint(Ai[8].xaddy, 1); + fe64_setint(Ai[8].ysubx, 1); + fe64_setint(Ai[8].z, 1); + fe64_setint(Ai[8].t2d, 0); + + ge64_p3_to_pniels(&Ai[9], A); + + ge64_p3 u; + ge64_p1p1 t; + for(uint64_t i = 9; i < 16; i++) + { + ge64_pnielsadd_p1p1(&t, A, &Ai[i]); + ge64_p1p1_to_p3(&u, &t); + ge64_p3_to_pniels(&Ai[i + 1], &u); + } + + for(uint64_t i = 0; i < 8; i++) + { + fe64_copy(Ai[i].xaddy, Ai[16 - i].ysubx); + fe64_copy(Ai[i].ysubx, Ai[16 - i].xaddy); + fe64_copy(Ai[i].z, Ai[16 - i].z); + fe64_neg(Ai[i].t2d, Ai[16 - i].t2d); + } + + fe64_setint(r->x, 0); + fe64_setint(r->y, 1); + fe64_setint(r->z, 1); + + for(int64_t i = 63; i >= 0; i--) + { + ge64_p2_dbl(&t, r); + ge64_p1p1_to_p2(r, &t); + ge64_p2_dbl(&t, r); + ge64_p1p1_to_p2(r, &t); + ge64_p2_dbl(&t, r); + ge64_p1p1_to_p2(r, &t); + ge64_p2_dbl(&t, r); + ge64_p1p1_to_p3(&u, &t); + + uint64_t idx = e[i] + 8; + ge64_pnielsadd_p1p1(&t, &u, &Ai[idx]); + ge64_p1p1_to_p2(r, &t); + } +} + +inline void ge64_sub(ge64_p1p1* r, const ge64_p3* p, const ge64_p3* q) +{ + fe64 t0, xaddy, ysubx, t2d; + fe64_add(xaddy, q->x, q->y); + fe64_sub(ysubx, q->y, q->x); + fe64_mul(t2d, q->t, fe64_2d); + + fe64_add(r->x, p->y, p->x); + fe64_sub(r->y, p->y, p->x); + fe64_mul(r->z, r->x, ysubx); + fe64_mul(r->y, r->y, xaddy); + fe64_mul(r->t, t2d, p->t); + fe64_mul(r->x, p->z, q->z); + fe64_add(t0, r->x, r->x); + fe64_sub(r->x, r->z, r->y); + fe64_add(r->y, r->z, r->y); + fe64_sub(r->z, t0, r->t); + fe64_add(r->t, t0, r->t); +} diff --git a/src/crypto/ecops64/ecops64-data.c b/src/crypto/ecops64/ecops64-data.c new file mode 100644 index 00000000..9d928e2f --- /dev/null +++ b/src/crypto/ecops64/ecops64-data.c @@ -0,0 +1,3342 @@ +// Copyright (c) 2019, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see +// ORIGINAL-LICENSE for details All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This +// includes +// posting the work online, or hosting copies of the modified work for +// download. +// +// 4. Any derivative version of this work is also covered by this license, +// including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may +// be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in +// accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this +// licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +// Based on Dr Bernstein's public domain code. +// https://bench.cr.yp.to/supercop.html + +#include "ecops64.h" + +const fe64 fe64_d = {0x75EB4DCA135978A3, 0x00700A4D4141D8AB, 0x8CC740797779E898, 0x52036CEE2B6FFE73}; +const fe64 fe64_2d = {0xEBD69B9426B2F146, 0x00E0149A8283B156, 0x198E80F2EEF3D130, 0xA406D9DC56DFFCE7}; +const fe64 fe64_sqrtm1 = {0xC4EE1B274A0EA0B0, 0x2F431806AD2FE478, 0x2B4D00993DFBD7A7, 0x2B8324804FC1DF0B}; + +const uint64_t sc64_reduce_order[16] = + { 0x5812631A5CF5D3EDULL, 0x14DEF9DEA2F79CD6ULL, + 0x0000000000000000ULL, 0x1000000000000000ULL, + 0xB024C634B9EBA7DAULL, 0x29BDF3BD45EF39ACULL, + 0x0000000000000000ULL, 0x2000000000000000ULL, + 0x60498C6973D74FB4ULL, 0x537BE77A8BDE7359ULL, + 0x0000000000000000ULL, 0x4000000000000000ULL, + 0xC09318D2E7AE9F68ULL, 0xA6F7CEF517BCE6B2ULL, + 0x0000000000000000ULL, 0x8000000000000000ULL }; + +const fe64 ge64_base_mult0_x[] = { + { 0x88f00487eeb4f64a, 0x298a7308ff2ce8cd, 0x7af3a5460f6260d8, 0x317a3d40d0511c93 }, + { 0x4f54cfca15e37dcc, 0xf82fec18881c62d5, 0x2c3823cd69c4fdf0, 0xd752f2f406168562 }, + { 0x0f8b17cb04681b4d, 0xbc34ccfb270977b1, 0x3aa2a67e45ebac82, 0xe6d0d08b0b753fc7 }, + { 0xdd7ec67f9ba21b61, 0x47afcc0d83c83cb4, 0x062106105da4b443, 0xec04b182a4394f08 }, + { 0x6d8ab350766c0efa, 0xcb18c27cd863d571, 0xf9b4568f0b95be0d, 0xbf84ae4952601d72 }, + { 0xa73b6f40580e3b0f, 0x3978cfccfd3b6ef2, 0xc016a317824a6f8b, 0xb0a2c76bbadae16d }, + { 0xf874bd63af7863d1, 0xefe4e375d450b740, 0x85f78905cf9830a7, 0x12a98f66c14bf727 }, + { 0x6d53a53ee1b455b9, 0x2da6713ed5b4b09a, 0x7eb63b9c04524747, 0x3d2d925865235802 }, + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, + { 0x92ac5ac11e4baa21, 0xd2598ec12a4b4f65, 0x8149c463fbadb8b8, 0xc2d26da79adca7fd }, + { 0x078b429c50879c09, 0x101b1c8a2baf48bf, 0x7a0876fa3067cf58, 0xed5670993eb408d8 }, + { 0x58c490bfa7f1c4cb, 0xc687303302c4910d, 0x3fe95ce87db59074, 0x4f5d389445251e92 }, + { 0x92754caf8993f0e0, 0x34e73d83279c2a8e, 0x064ba970f46a41f2, 0x407b51b6ad9fe28d }, + { 0x22813980645de479, 0xb85033f27c37c34b, 0xf9def9efa25b4bbc, 0x13fb4e7d5bc6b0f7 }, + { 0xf074e834fb97e48d, 0x43cb3304d8f6884e, 0xc55d5981ba14537d, 0x192f2f74f48ac038 }, + { 0xb0ab3035ea1c820e, 0x07d013e777e39d2a, 0xd3c7dc32963b020f, 0x28ad0d0bf9e97a9d }, + { 0x770ffb78114b0990, 0xd6758cf700d31732, 0x850c5ab9f09d9f27, 0xce85c2bf2faee36c }}; + +const fe64 ge64_base_mult0_y[] = { + { 0x3c5eb753f86f7368, 0x02f079f8c43dc926, 0xdd5ade12cd15e71f, 0x43a60c0193cae6f2 }, + { 0x2589896b3e80c570, 0xe110568def57e47a, 0x0f9cc8d1ba6d5a83, 0x638ac7c6568faa5f }, + { 0x83a4f5a1f292fdd5, 0xf282f80d289ad6c1, 0x3b6e134ffa9efaef, 0x8a9bc7f8510db142 }, + { 0x21a43f07aced91ed, 0x62505d95128616ba, 0xc058dc2913248ccc, 0x3e904b6531fd5cdf }, + { 0xbe7156c39464225e, 0x99e45065d45e1fe1, 0x8e1d710b01aae2d8, 0x8fa1d04f962b2bc2 }, + { 0x0586d090f1eb6995, 0x3e2dd82ece480608, 0x424d431cc04d3def, 0xa4cf63a2efdcd357 }, + { 0x1cbe8d5cd5f1477f, 0x2e721ea2c870a2ac, 0x3b44bdd193443ead, 0xc4c19be612465384 }, + { 0xccccccccccccccc3, 0xcccccccccccccccc, 0xcccccccccccccccc, 0x4ccccccccccccccc }, + { 0x0000000000000002, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, + { 0xccccccccccccccc3, 0xcccccccccccccccc, 0xcccccccccccccccc, 0x4ccccccccccccccc }, + { 0x1cbe8d5cd5f1477f, 0x2e721ea2c870a2ac, 0x3b44bdd193443ead, 0xc4c19be612465384 }, + { 0x0586d090f1eb6995, 0x3e2dd82ece480608, 0x424d431cc04d3def, 0xa4cf63a2efdcd357 }, + { 0xbe7156c39464225e, 0x99e45065d45e1fe1, 0x8e1d710b01aae2d8, 0x8fa1d04f962b2bc2 }, + { 0x21a43f07aced91ed, 0x62505d95128616ba, 0xc058dc2913248ccc, 0x3e904b6531fd5cdf }, + { 0x83a4f5a1f292fdd5, 0xf282f80d289ad6c1, 0x3b6e134ffa9efaef, 0x8a9bc7f8510db142 }, + { 0x2589896b3e80c570, 0xe110568def57e47a, 0x0f9cc8d1ba6d5a83, 0x638ac7c6568faa5f }, + { 0x3c5eb753f86f7368, 0x02f079f8c43dc926, 0xdd5ade12cd15e71f, 0x43a60c0193cae6f2 }}; + +const fe64 ge64_base_mult0_t[] = { + { 0x208217ca57cb5c5c, 0x741e63259767a815, 0xd3ee7ac98e984cd9, 0xa7614c2624102a3d }, + { 0xde85755354f025a4, 0x5ad739abc2cab637, 0xc82fa474ec548a97, 0xdcc3109dc5d343c8 }, + { 0x7062526e97621c36, 0xe8a0dbd707046ec8, 0xfaf54acd60304677, 0x879a205decab3f60 }, + { 0x37cd5e86182ffc27, 0xa08d62f5ffedb281, 0x9d3e2b5ef192700c, 0x974753a6c74d8567 }, + { 0x40e1ba131aebd92a, 0x1cd439c29245f06b, 0x1bd68b2a7307ad3f, 0xbb0f864e4f19b3e7 }, + { 0x640dee0b0e98b7a6, 0x47b194e809d2076a, 0x282190f8a48dd5b1, 0xab65fb469c44d5de }, + { 0x91cb8155252c97d8, 0x450ca66c7c11b7fa, 0xc43541ef19f897d9, 0xb6ceb0f5e9a12e47 }, + { 0x2442ea98b4904481, 0xbe1ec0ff115d5a15, 0x322b62e336a83905, 0xb0f141e050e91335 }, + { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, + { 0xdbbd15674b6fbb59, 0x41e13f00eea2a5ea, 0xcdd49d1cc957c6fa, 0x4f0ebe1faf16ecca }, + { 0x6e347eaadad36802, 0xbaf3599383ee4805, 0x3bcabe10e6076826, 0x49314f0a165ed1b8 }, + { 0x9bf211f4f1674834, 0xb84e6b17f62df895, 0xd7de6f075b722a4e, 0x549a04b963bb2a21 }, + { 0xbf1e45ece51426b0, 0xe32bc63d6dba0f94, 0xe42974d58cf852c0, 0x44f079b1b0e64c18 }, + { 0xc832a179e7d003b3, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98 }, + { 0x8f9dad91689de3a4, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f }, + { 0x217a8aacab0fda36, 0xa528c6543d3549c8, 0x37d05b8b13ab7568, 0x233cef623a2cbc37 }, + { 0xdf7de835a834a37e, 0x8be19cda689857ea, 0x2c1185367167b326, 0x589eb3d9dbefd5c2 }}; + + +const ge64_niels ge64_base_multiples_niels[] = { + {{0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8}, + {0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8}, + {0x16130d12f30793c2, 0x4b92f9edf8ca202b, 0x43625f67fb469418, 0x8c1d19d026923d94}}, + {{0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee}, + {0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a}, + {0x2c5228dadda33078, 0x6ee5cc7e4dead3a2, 0x274c6052a4f70782, 0x90fa9f94b86601c4}}, + {{0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235}, + {0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2}, + {0xcd17c79b8a0c2897, 0xc9a47450951a2610, 0x7dadc749c7a497e1, 0xdcb6d63ee9829a1e}}, + {{0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181}, + {0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a}, + {0xb876fb2a5fb206e8, 0x050451b54efebd2c, 0x0937539caaa2f667, 0xa553b5bed06f4efb}}, + {{0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c}, + {0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714}, + {0x2a9fffa1040f432d, 0x7148f0d12e78f3a1, 0xdfe06fcc2f7b195f, 0xb3c5a51e3184998f}}, + {{0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275}, + {0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4}, + {0x2c59bb59209b7ba3, 0x8fc49aa677f04022, 0x347adabf52c5e55a, 0xf6ff4c0871b39b97}}, + {{0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965}, + {0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371}, + {0x994d5b6931a497e7, 0x00ab6d2742a96869, 0xafc313d6b5a6d32f, 0xa996bc9af7ec534d}}, + {{0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61}, + {0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883}, + {0x607983826975352f, 0xa0abda71d8f6d8d6, 0x2f582cb415e7f68a, 0xde4ab95cc8bed91e}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x7ec851ca553e2df3, 0xa71284cba64878b3, 0xe6b5e4193288d1e7, 0x4cf210ec5a9a8883}, + {0x322d04a52d9021f6, 0xb9c19f3375c6bf9c, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61}, + {0x9f867c7d968acaab, 0x5f54258e27092729, 0xd0a7d34bea180975, 0x21b546a3374126e1}}, + {{0xa94ff858a2888343, 0xce0ed4565313ed3c, 0xf55c3dcfb5bf34fa, 0x0a653ca5c9eab371}, + {0x490a7a45d185218f, 0x9a15377846049335, 0x0060ea09cc31e1f6, 0x7e041577f86ee965}, + {0x66b2a496ce5b67f3, 0xff5492d8bd569796, 0x503cec294a592cd0, 0x566943650813acb2}}, + {{0xb818db0c26620798, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4}, + {0x5672f9eb1dabb69d, 0xba70b535afe853fc, 0x47ac0f752796d66d, 0x32a5351794117275}, + {0xd3a644a6df648437, 0x703b6559880fbfdd, 0xcb852540ad3a1aa5, 0x0900b3f78e4c6468}}, + {{0x0a851b9f679d651b, 0xe108cb61033342f2, 0xd601f57fe88b30a3, 0x371f3acaed2dd714}, + {0xed280fbec816ad31, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c}, + {0xd560005efbf0bcad, 0x8eb70f2ed1870c5e, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670}}, + {{0x4138a434dcb8fa95, 0x870cf67d6c96840b, 0xde388574297be82c, 0x7c814db27262a55a}, + {0xbaf875e4c93da0dd, 0xb93282a771b9294d, 0x80d63fb7f4c6c460, 0x6de9c73dea66c181}, + {0x478904d5a04df8f2, 0xfafbae4ab10142d3, 0xf6c8ac63555d0998, 0x5aac4a412f90b104}}, + {{0xc64f326b3ac92908, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2}, + {0x603a0d0abd7f5134, 0x8089c932e1d3ae46, 0xdf2591398798bd63, 0x1c145cd274ba0235}, + {0x32e8386475f3d743, 0x365b8baf6ae5d9ef, 0x825238b6385b681e, 0x234929c1167d65e1}}, + {{0x984decaba077ade8, 0x383f77ad19eb389d, 0xc7ec6b7e2954d794, 0x59c77b3aeb7c3a7a}, + {0x48145cc21d099fcf, 0x4535c192cc28d7e5, 0x80e7c1e548247e01, 0x4a5f28743b2973ee}, + {0xd3add725225ccf62, 0x911a3381b2152c5d, 0xd8b39fad5b08f87d, 0x6f05606b4799fe3b}}, + {{0x9ffe9e92177ba962, 0x98aee71d0de5cae1, 0x3ff4ae942d831044, 0x714de12e58533ac8}, + {0x5b433149f91b6483, 0xadb5dc655a2cbf62, 0x87fa8412632827b3, 0x60895e91ab49f8d8}, + {0xe9ecf2ed0cf86c18, 0xb46d06120735dfd4, 0xbc9da09804b96be7, 0x73e2e62fd96dc26b}}, + {{0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}, + {0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}, + {0xf74e48ab73e506ea, 0x31f08583db9d664b, 0x089f4f06e1f926c6, 0xbe4477848d92edec}}, + {{0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}, + {0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}, + {0xe0a509fb515951d5, 0x3edcae0e411b6366, 0x9e57f74a11009499, 0xf0313ef0fe1fdeae}}, + {{0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}, + {0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}, + {0xc396dcd269c224a6, 0xe22178254b68c7a7, 0x55282e065f6e0d7a, 0xed4a01d05fb71249}}, + {{0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}, + {0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}, + {0xf058870e1ebea450, 0xf9bf6008453c5881, 0x90ad2847655d65af, 0xfdade309859ca5a9}}, + {{0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}, + {0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}, + {0xdb474c51ad5020fd, 0xcb6a9c7312c4cf30, 0xcc5b437c56417e6a, 0xc8c898b8a39ae0fb}}, + {{0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}, + {0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}, + {0xc328b9e9967a0806, 0xa6c1a17b3637ffa8, 0xd03c0d49849eece1, 0xeb7d63157c03ad93}}, + {{0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}, + {0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}, + {0xc0ec1ed733a799d6, 0x90a78c134ba68b81, 0x5f49c21233ed970a, 0xa992879cba791dd3}}, + {{0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}, + {0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}, + {0x93bbbbe8def91b13, 0x04ac297f6d728096, 0x4b8c615b96b2c0d9, 0xef3968eed179b44f}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xed5b635449aa515e, 0xa865c49f0bc6823a, 0x850c1fe95b42d1c4, 0x30d76d6f03d315b9}, + {0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39}, + {0x6c4444172106e4c7, 0xfb53d680928d7f69, 0xb4739ea4694d3f26, 0x10c697112e864bb0}}, + {{0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09}, + {0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef}, + {0x3f13e128cc586604, 0x6f5873ecb459747e, 0xa0b63dedcc1268f5, 0x566d78634586e22c}}, + {{0x1637a49f9cc10834, 0xbc8e56d5a89bc451, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9}, + {0xa1054285c65a2fd0, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a}, + {0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c}}, + {{0xff437b8497dd95c2, 0x6c744e30aa4eb5a7, 0x9e0c5d613c85e88b, 0x2fd9c71e5f758173}, + {0x21e70b2f4e71ecb8, 0xe656ddb940a477e3, 0xbf6556cece1d4f80, 0x05fc3bc4535d7b7e}, + {0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04}}, + {{0x2fba99fd40d1add9, 0xb307166f96f4d027, 0x4363f05215f03bae, 0x1fbea56c3b18f999}, + {0x634095cb14246590, 0xef12144016c15535, 0x9e38140c8910bc60, 0x6bf5905730907c8c}, + {0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56}}, + {{0x513fee0b0a9d5294, 0x8f98e75c0fdf5a66, 0xd4618688bfe107ce, 0x3fa00a7e71382ced}, + {0xb1146720772f5ee4, 0xe8f894b196079ace, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4}, + {0x3c69232d963ddb34, 0x1dde87dab4973858, 0xaad7d1f9a091f285, 0x12b5fe2fa048edb6}}, + {{0x71f0fbc496fce34d, 0x73b9826badf35bed, 0xd2047261ff28c561, 0x749b76f96fb1206f}, + {0xdf2b7c26ad6f1e92, 0x4b66d323504b8913, 0x8c409dc0751c8bc3, 0x6f7e93c20796c7b8}, + {0x1f5af604aea6ae05, 0xc12351f1bee49c99, 0x61a808b5eeff6b66, 0x0fcec10f01e02151}}, + {{0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3}, + {0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a}, + {0x08b1b7548c1af8f0, 0xce0f7a7c246299b4, 0xf760b0f91e06d939, 0x41bb887b726d1213}}, + {{0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717}, + {0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9}, + {0xe3654de93835482a, 0x829a2c8bf8443c33, 0xad8bb8afafb5a72a, 0xf60d9f94ece5d66f}}, + {{0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a}, + {0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965}, + {0x1614fd3b24ce095b, 0x12da0276ef4304d4, 0xb937ece0a3a3224b, 0xcc4de3ec5f346431}}, + {{0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a}, + {0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe}, + {0xcd11821d78b16706, 0xeb3c9d164681f39f, 0xa87e2321959f5c75, 0xde822a15558557bf}}, + {{0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0}, + {0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96}, + {0xa9f5d32978231910, 0x80ca973b799b30b2, 0x78be16addd7fc5c7, 0xb7c4254ea6a9ac03}}, + {{0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143}, + {0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c}, + {0x6825d0da493771f1, 0xdae45815530dfe96, 0xf64bb07810b14b1b, 0x826f54e44395825a}}, + {{0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e}, + {0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403}, + {0x6126e62a2c966ee7, 0xadec514424b1460d, 0x38f715fab3466eca, 0xa7212a808dd9f1a9}}, + {{0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb}, + {0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd}, + {0xadeaec9d86cbf70b, 0x14f0e8fce669c26b, 0x57cc4d0577c26b99, 0xf6c580588affc387}}, + {{0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362}, + {0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2}, + {0xd53ae63ef2eb5686, 0x150b8b4b6b4a056f, 0x19507c7d560785a5, 0xf215924e78641f6b}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x9267806c567c49d8, 0x066d04ccca791e6a, 0xa69f5645e3cc394b, 0x5c95b686a0788cd2}, + {0x97d980e0aa39f7d2, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362}, + {0x2ac519c10d14a954, 0xeaf474b494b5fa90, 0xe6af8382a9f87a5a, 0x0dea6db1879be094}}, + {{0xaa66bf547344e5ab, 0xda1258888f1b4309, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd}, + {0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb}, + {0x52151362793408cf, 0xeb0f170319963d94, 0xa833b2fa883d9466, 0x093a7fa775003c78}}, + {{0xe5107de63a16d7be, 0xa377ffdc9af332cf, 0x70d5bf18440b677f, 0x6a252b19a4a31403}, + {0xb8e9604460a91286, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e}, + {0x9ed919d5d36990f3, 0x5213aebbdb4eb9f2, 0xc708ea054cb99135, 0x58ded57f72260e56}}, + {{0x78e79dade9413d77, 0xf257f9d59729e67d, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c}, + {0xda6d53265b0fd48b, 0x8960823193bfa988, 0xd78ac93261d57e28, 0x79f2942d3a5c8143}, + {0x97da2f25b6c88de9, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5}}, + {{0x9acca683a7016bfe, 0x90505f4df2c50b6d, 0x6b610d5fcce435aa, 0x19a10d446198ff96}, + {0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0}, + {0x560a2cd687dce6ca, 0x7f3568c48664cf4d, 0x8741e95222803a38, 0x483bdab1595653fc}}, + {{0xfa780f148734fa49, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe}, + {0xd6cf4d0ab4da80f6, 0x82483e45f8307fe0, 0x05005269ae6f9da4, 0x1c7052909cf7877a}, + {0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840}}, + {{0x9db7c4d0248e1eb0, 0xe07697e14d74bf52, 0x1e6a9b173c562354, 0x7fa7c21f795a4965}, + {0x8bdf1fb9be8c0ec8, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a}, + {0xe9eb02c4db31f67f, 0xed25fd8910bcfb2b, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce}}, + {{0x360692f8087d8e31, 0xf4dcc637d27163f7, 0x25a4e62065ea5963, 0x659bf72e5ac160d9}, + {0x9aafb9b05ee38c5b, 0xbf9d2d4e071a13c7, 0x8eee6e6de933290a, 0x1c3bab17ae109717}, + {0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990}}, + {{0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}, + {0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}, + {0xf69e0b9839359d1c, 0xfb13de29dee6ad11, 0xe7dc9f88642ab88f, 0x8bf23592a70f1f2d}}, + {{0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}, + {0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}, + {0x36b4d2ca78b13a88, 0x3a19373067db9072, 0x0834b905e93fca31, 0xa428babcf7cfc233}}, + {{0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}, + {0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}, + {0x8d772e2b83e89b24, 0x8dabeebf1fbe74ae, 0x60fce59fe753092e, 0xdf67617601d8bd39}}, + {{0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}, + {0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}, + {0x2dcdefd2c5146ceb, 0x1e9dac4b9ee9579e, 0xc2815418e6f455db, 0xb60a0445b6934140}}, + {{0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}, + {0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}, + {0x0e6f5b8b5f7b9564, 0xed10067b32d0833f, 0x96a1d6f9a755d470, 0xa6e4982640013747}}, + {{0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}, + {0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}, + {0x4e5597e0736cc674, 0x73de6b63dfd6f367, 0xc6eead6ede62c3ad, 0xbefb22fd01639884}}, + {{0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}, + {0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}, + {0xc0252feb710f28fa, 0x62c18b656eab90c3, 0x8e139defd9447ea8, 0xeb730a72cb36137f}}, + {{0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}, + {0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}, + {0xccfe4a66b4437651, 0x8c9451c5a422bd9f, 0xf29e521de62a61c3, 0xc118cff0d97a2b9b}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7}, + {0x7e234c597c6691ae, 0x64889d3d0a85b4c8, 0xdae2c90c354afae7, 0x0a871e070c6a9e1d}, + {0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464}}, + {{0xf5d255e49e7dd6b7, 0x8016115c610b1eac, 0x3c99975d92e187ca, 0x13815762979125c2}, + {0x43fa7947841e7518, 0xe5c6fa59639c46d7, 0xa1065e1de3052b74, 0x7d47c6a2cfb89030}, + {0x3fdad0148ef0d6e0, 0x9d3e749a91546f3c, 0x71ec621026bb8157, 0x148cf58d34c9ec80}}, + {{0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4}, + {0xe2572f7d9ae4756d, 0x56c345bb88f3487f, 0x9fd10b6d6960a88d, 0x278febad4eaea1b9}, + {0xb1aa681f8c933966, 0x8c21949c20290c98, 0x39115291219d3c52, 0x4104dd02fe9c677b}}, + {{0x72b2bf5e1124422a, 0xa1fa0c3398a33ab5, 0x94cb6101fa52b666, 0x2c863b00afaf53d5}, + {0x81214e06db096ab8, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481}, + {0xf190a474a0846a76, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8}}, + {{0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb}, + {0x99b9b3719f18b55d, 0xe465e5faa18c641e, 0x61081136c29f05ed, 0x489b4f867030128b}, + {0xd232102d3aeb92ef, 0xe16253b46116a861, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf}}, + {{0x30949a108a5bcfd4, 0xdc40dd70bc6473eb, 0x92c294c1307c0d1c, 0x5604a86dcbfa6e74}, + {0x155d628c1e9c572e, 0x8a4d86acc5884741, 0x91a352f6515763eb, 0x06a1a6c28867515b}, + {0x7288d1d47c1764b6, 0x72541140e0418b51, 0x9f031a6018acf6d1, 0x20989e89fe2742c6}}, + {{0x499777fd3a2dcc7f, 0x32857c2ca54fd892, 0xa279d864d207e3a0, 0x0403ed1d0ca67e29}, + {0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3}, + {0xc94b2d35874ec552, 0xc5e6c8cf98246f8d, 0xf7cb46fa16c035ce, 0x5bd7454308303dcc}}, + {{0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83}, + {0x85c4932115e7792a, 0xc64c89a2bdcdddc9, 0x9d1e3da8ada3d762, 0x5bb7db123067f82c}, + {0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2}}, + {{0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992}, + {0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b}, + {0x20c2ecb2567f0669, 0x85b0472edde5dd58, 0xc2082bdfca552927, 0xd5eb123395e5eda1}}, + {{0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8}, + {0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784}, + {0x9a42e4158f07fdfc, 0xe410483f01b61d75, 0x579cf9324e4d51b5, 0xc4853f32d9a3d5f6}}, + {{0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e}, + {0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b}, + {0x24c11ff6bc404dca, 0xb68dfe78df7ff53d, 0xd954a29e8c427998, 0xdf4df63d54dfb6c7}}, + {{0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d}, + {0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a}, + {0x6f8e26ecd49414ab, 0xf0d91652d7be7db8, 0x1546e13642136da2, 0xb419a4370b750d21}}, + {{0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9}, + {0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e}, + {0xcea2a38a4b4d8ab4, 0x33347bd2fdc9255a, 0xdd0f375ccba01171, 0x8c68a59e82c62412}}, + {{0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc}, + {0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92}, + {0x22f12374290d049e, 0xab39c5586338485f, 0x51f4fcd4d37260e5, 0x90631ef89fd69804}}, + {{0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282}, + {0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd}, + {0x46e836ada7c3f582, 0x9ac00647f01b390c, 0x64f258284320c3f3, 0xbc5f114954ab29f1}}, + {{0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47}, + {0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed}, + {0x46f7d640868e7860, 0xa1bbbb9c92e819ce, 0xb2fa3ad1e7d8976c, 0xd89cd265a5b5b50a}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed}, + {0x3906c72aed261ae5, 0x9ab68fd988e100f7, 0xf5e9059af3360197, 0x0e53dc78bf2b6d47}, + {0xb90829bf7971877a, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5}}, + {{0xd11ff05154b260ce, 0xd86dc38e72f95270, 0x601fcd0d267cc138, 0x2b67916429e90ccd}, + {0xa98285d187eaffdb, 0xa5b4fbbbd8d0a864, 0xb658f27f022663f7, 0x3bbc2b22d99ce282}, + {0xb917c952583c0a58, 0x653ff9b80fe4c6f3, 0x9b0da7d7bcdf3c0c, 0x43a0eeb6ab54d60e}}, + {{0x396966a46d4a5487, 0xf811a18aac2bb3ba, 0x66e4685b5628b26b, 0x70a477029d929b92}, + {0x3ac6322357875fe8, 0xd9d4f4ecf5fbcb8f, 0x8dee8493382bb620, 0x50c5eaa14c799fdc}, + {0xdd0edc8bd6f2fb3c, 0x54c63aa79cc7b7a0, 0xae0b032b2c8d9f1a, 0x6f9ce107602967fb}}, + {{0xad1054b1cde1c22a, 0xc4a8e90248eb32df, 0x5f3e7b33accdc0ea, 0x72364713fc79963e}, + {0x139693063520e0b5, 0x437fcf7c88ea03fe, 0xf7d4c40bd3c959bc, 0x699154d1f893ded9}, + {0x315d5c75b4b27526, 0xcccb842d0236daa5, 0x22f0c8a3345fee8e, 0x73975a617d39dbed}}, + {{0xe4024df96375da10, 0x78d3251a1830c870, 0x902b1948658cd91c, 0x7e18b10b29b7438a}, + {0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d}, + {0x9071d9132b6beb2f, 0x0f26e9ad28418247, 0xeab91ec9bdec925d, 0x4be65bc8f48af2de}}, + {{0x78487feba36e7028, 0x5f3f13001dd8ce34, 0x934fb12d4b30c489, 0x056c244d397f0a2b}, + {0x1d50fba257c26234, 0x7bd4823adeb0678b, 0xc2b0dc6ea6538af5, 0x5665eec6351da73e}, + {0xdb3ee00943bfb210, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938}}, + {{0x549e342ac07fb34b, 0x02d8220821373d93, 0xbc262d70acd1f567, 0x7a92c9fdfbcac784}, + {0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8}, + {0x65bd1bea70f801de, 0x1befb7c0fe49e28a, 0xa86306cdb1b2ae4a, 0x3b7ac0cd265c2a09}}, + {{0x822bee438c01bcec, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b}, + {0xf0d54e4f22ed39a7, 0xa2aae91e5608150a, 0xf421b2e9eddae875, 0x31bc531d6b7de992}, + {0xdf3d134da980f971, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e}}, + {{0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}, + {0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}, + {0xf7b0b5bbfe5cf6dd, 0x57dde63c895a3553, 0x214721b9bc2e4382, 0xe27ea6d29f42c739}}, + {{0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}, + {0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}, + {0xd3c7d0ac969eb6a2, 0x2501bf6548d292ef, 0x1737cc6e49b90dd8, 0xba018f0afadbcf93}}, + {{0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}, + {0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}, + {0x0dd4c7bdadb4ef72, 0xaf97cbc411631678, 0x03628e7bb59daf37, 0x9edbc9cbe0f74eee}}, + {{0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}, + {0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}, + {0x27822679aec5d033, 0x0a53648e062b30f7, 0x2f943ce4e15d7c4c, 0xcce5e76de668e589}}, + {{0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}, + {0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}, + {0x02ad8094f7fc6289, 0xe74eb69bfe83fff9, 0x2addf14fd1da5b57, 0xc68345779db9fc8a}}, + {{0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}, + {0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}, + {0xf5badd4d203f389a, 0xef2f9180bf365bf8, 0x3930ebbe87300997, 0xa19f84dae75bc86f}}, + {{0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}, + {0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}, + {0xc891ecb46daeecf9, 0x8fc8874a235ea25f, 0x4fba7650b9e3ceee, 0xa49fa3bb80fcd7dc}}, + {{0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}, + {0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}, + {0x86f0e78a84ac5b5d, 0xcf84fecf30f3a786, 0xce6fc288da810806, 0x966b974242694450}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xdf48ee0752cfce4e, 0xc3fffaf306ec08b7, 0x05710b2ab95459c4, 0x161d25fa963ea38d}, + {0x231a8c570478433c, 0xb7b5270ec281439d, 0xdbaa99eae3d9079f, 0x2c03f5256c2b03d9}, + {0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf}}, + {{0xbd1f2f46f4dafecf, 0x7cef0114a47fd6f7, 0xd31ffdda4a47b37f, 0x525219a473905785}, + {0xd8dd3de66aa91948, 0x485064c22fc0d2cc, 0x9b48246634fdea2f, 0x293e1c4e6c4a2e3a}, + {0x376e134b925112e1, 0x703778b5dca15da0, 0xb04589af461c3111, 0x5b605c447f032823}}, + {{0xb965805920c47c89, 0xe7f0100c923b8fcc, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee}, + {0x3be9fec6f0e7f04c, 0x866a579e75e34962, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5}, + {0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, 0xc6cf144178cff668, 0x5e607b2518a43790}}, + {{0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, 0xe1b3ff4f66e61d6e, 0x5067acab6ccdd5f7}, + {0xa02c431ca596cf14, 0xe3c42d40aed3e400, 0xd24526802e0f26db, 0x201f33139e457068}, + {0xfd527f6b08039d51, 0x18b14964017c0006, 0xd5220eb02e25a4a8, 0x397cba8862460375}}, + {{0x30c13093f05959b2, 0xe23aa18de9a97976, 0x222fd491721d5e26, 0x2339d320766e6c3a}, + {0x7815c3fbc81379e7, 0xa6619420dde12af1, 0xffa9c0f885a8fdd5, 0x771b4022c1e1c252}, + {0xd87dd986513a2fa7, 0xf5ac9b71f9d4cf08, 0xd06bc31b1ea283b3, 0x331a189219971a76}}, + {{0xf5166f45fb4f80c6, 0x9c36c7de61c775cf, 0xe3d4e81b9041d91c, 0x31167c6b83bdfe21}, + {0x26512f3a9d7572af, 0x5bcbe28868074a9e, 0x84edc1c11180f7c4, 0x1ac9619ff649a67b}, + {0xf22b3842524b1068, 0x5068343bee9ce987, 0xfc9d71844a6250c8, 0x612436341f08b111}}, + {{0xd99d41db874e898d, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40}, + {0x8b6349e31a2d2638, 0x9ddfb7009bd3fd35, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445}, + {0x2c382f5369614938, 0xdafe409ab72d6d10, 0xe8c83391b646f227, 0x45fe70f50524306c}}, + {{0xda4875a6960c0b8c, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4}, + {0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245}, + {0x084f4a4401a308fd, 0xa82219c376a5caac, 0xdeb8de4643d1bc7d, 0x1d81592d60bd38c6}}, + {{0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4}, + {0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6}, + {0x440d4e5f8d2d8338, 0x40c6c3a6042138fb, 0x167244311d9d47e1, 0xfd1142f4cfd64a76}}, + {{0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b}, + {0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa}, + {0x619cf2d380e6e0f6, 0xb0407cfe43c0098f, 0x878271b185048c3b, 0xaf27c2a4170a705a}}, + {{0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd}, + {0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33}, + {0x7e76b4b2b5ad5632, 0x5226c1ed09477cd0, 0xe7b27ab749e429c7, 0xc0e39d2429360932}}, + {{0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec}, + {0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f}, + {0xe82d04c279afd260, 0x4a9b27bbaf596cad, 0x82569d3759f128a2, 0xff2f07a4ce78c955}}, + {{0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f}, + {0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d}, + {0x9f5f3b3433bc5ae5, 0x88a39935c9884156, 0x5e855e8ad0070a12, 0xee2126fdf1fe023f}}, + {{0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5}, + {0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081}, + {0x2f6a6016573077c1, 0x2f566aaf7b8a5663, 0x9153e8ccdf4f633a, 0x9d7130fbcce4ef6a}}, + {{0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b}, + {0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c}, + {0x24df45f0474947db, 0x48cd3c4988aee05e, 0x56d4ae3f660fd276, 0xb0c78a52b7635a0e}}, + {{0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f}, + {0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81}, + {0xc91be83434e46f39, 0xcc4c225580ee86b1, 0xc0aef7f777a439f8, 0xdbebe23f1957fdf2}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xd833d7beec2a4c38, 0x2c9162830acc20ed, 0xe93a47aa92df7581, 0x702d67a3333c4a81}, + {0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, 0xbcac008a78eda015, 0x2cb8b3a5b483b03f}, + {0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d}}, + {{0x59f73c773fefee9d, 0xb3f1ef89c1cf989d, 0xe35dfb42e02e545f, 0x5766120b47a1b47c}, + {0x91925dccbd83157d, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b}, + {0xdb20ba0fb8b6b7ff, 0xb732c3b677511fa1, 0xa92b51c099f02d89, 0x4f3875ad489ca5f1}}, + {{0xc7fc762f4932ab22, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081}, + {0x79ed13f6ee73eec0, 0xa5c6526d69110bb1, 0xe48928c38603860c, 0x722a1446fd7059f5}, + {0xd0959fe9a8cf8819, 0xd0a995508475a99c, 0x6eac173320b09cc5, 0x628ecf04331b1095}}, + {{0x98bcb118a9d0ddbc, 0xee449e3408b4802b, 0x87089226b8a6b104, 0x685f349a45c7915d}, + {0x9b41acf85c74ccf1, 0xb673318108265251, 0x99c92aed11adb147, 0x7a47d70d34ecb40f}, + {0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, 0xa17aa1752ff8f5ed, 0x11ded9020e01fdc0}}, + {{0x890e7809caefe704, 0x8728296de30e8c6c, 0x4c5cd2a392aeb1c9, 0x194263d15771531f}, + {0x471f95b03bea93b7, 0x0552d7d43313abd3, 0xbd9370e2e17e3f7b, 0x7b120f1db20e5bec}, + {0x17d2fb3d86502d7a, 0xb564d84450a69352, 0x7da962c8a60ed75d, 0x00d0f85b318736aa}}, + {{0x978b142e777c84fd, 0xf402644705a8c062, 0xa67ad51be7e612c7, 0x2f7b459698dd6a33}, + {0xa6753c1efd7621c1, 0x69c0b4a7445671f5, 0x971f527405b23c11, 0x387bc74851a8c7cd}, + {0x81894b4d4a52a9a8, 0xadd93e12f6b8832f, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd}}, + {{0x2e8f1f0091910c1f, 0xa4df4fe0bff2e12c, 0x60c6560aee927438, 0x6338283facefc8fa}, + {0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b}, + {0x9e630d2c7f191ee4, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5}}, + {{0x85683916c11a1897, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6}, + {0xc0accf90b4d3b66d, 0xa7059de561732e60, 0x033d1f7870c6b0ba, 0x584161cd26d946e4}, + {0xbbf2b1a072d27ca2, 0xbf393c59fbdec704, 0xe98dbbcee262b81e, 0x02eebd0b3029b589}}, + {{0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}, + {0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}, + {0x92b8feea15793dce, 0x6675483493b92eda, 0x2887cd4ac599fe77, 0xbaf27e316f9045fc}}, + {{0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}, + {0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}, + {0xab7eee096c51af64, 0xe251de20e202ab59, 0xeddb736f0ceea19a, 0xa2602ea072180b6b}}, + {{0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}, + {0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}, + {0x05d8a7556636b34e, 0xdcff90904fff47f8, 0x042d6e225225ac6d, 0xaf7deb05a8b42e54}}, + {{0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}, + {0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}, + {0x18d4760731ce6bfd, 0xb2efcca95eda3f44, 0xfbe656c2d1e3017c, 0xdd067ff54e631d8d}}, + {{0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}, + {0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}, + {0x309e2665ba4a49dd, 0x79f67b16e4c586db, 0x18cff6e6cfc1c176, 0xc60d9b02beaff4e1}}, + {{0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}, + {0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}, + {0x8f91c7f2cf601e4f, 0x914fd259461e9a38, 0xa84445668251df54, 0xc5bd89dcd53e6922}}, + {{0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}, + {0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}, + {0x2e944f30b5b9afaa, 0x05b694beea3a8854, 0x7d3051750b54be62, 0xde234759f957d7ed}}, + {{0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}, + {0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}, + {0x892df2498e874d88, 0xf8e3cb062ae12e9f, 0x09d5b5df4c1bee8f, 0x83297dcac3001c99}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0}, + {0x8765b69f7b85c5e8, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c}, + {0x76d20db67178b252, 0x071c34f9d51ed160, 0xf62a4a20b3e41170, 0x7cd682353cffe366}}, + {{0x0be1a45bd887fab6, 0x2a846a32ba403b6e, 0xd9921012e96e6000, 0x2838c8863bdc0943}, + {0xa665cd6068acf4f3, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff}, + {0xd16bb0cf4a465030, 0xfa496b4115c577ab, 0x82cfae8af4ab419d, 0x21dcb8a606a82812}}, + {{0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab}, + {0x9a8d00fabe7731ba, 0x8203607e629e1889, 0xb2cc023743f3d97f, 0x5d840dbf6c6f678b}, + {0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd}}, + {{0x4b42432c8a7084fa, 0x898a19e3dfb9e545, 0xbe9f00219c58e45d, 0x1ff177cea16debd1}, + {0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, 0x80acffc075aa15fe, 0x0770c9e824e1a9f9}, + {0xcf61d99a45b5b5fd, 0x860984e91b3a7924, 0xe7300919303e3e89, 0x39f264fd41500b1e}}, + {{0xa7ad3417dbe7e29c, 0xbd94376a2b9c139c, 0xa0e91b8e93597ba9, 0x1712d73468889840}, + {0xd19b4aabfe097be1, 0xa46dfce1dfe01929, 0xc3c908942ca6f1ff, 0x65c621272c35f14e}, + {0xe72b89f8ce3193dd, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272}}, + {{0x605a368a3e9ef8cb, 0xe3e9c022a5504715, 0x553d48b05f24248f, 0x13f416cd647626e5}, + {0x42029fdd9a6efdac, 0xb912cebe34a54941, 0x640f64b987bdf37b, 0x4171a4d38598cab4}, + {0xfa2758aa99c94c8c, 0x23006f6fb000b807, 0xfbd291ddadda5392, 0x508214fa574bd1ab}}, + {{0xc20269153ed6fe4b, 0xa65a6739511d77c4, 0xcbde26462c14af94, 0x22f960ec6faba74b}, + {0x461a15bb53d003d6, 0xb2102888bcf3c965, 0x27c576756c683a5a, 0x3a7758a4c86cb447}, + {0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494}}, + {{0x031408d36d63727f, 0x6a379aefd7c7b533, 0xa9e18fc5ccaee24b, 0x332f35914f8fbed3}, + {0x3f244d2aeed7521e, 0x8e3a9028432e9615, 0xe164ba772e9c16d4, 0x3bc187fa47eb98d8}, + {0x6d470115ea86c20c, 0x998ab7cb6c46d125, 0xd77832b53a660188, 0x450d81ce906fba03}}, + {{0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2}, + {0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49}, + {0x749b4a627cfcb095, 0xd0748e0de05df104, 0x96db6b6a459aaf1b, 0xac610671ba2ab8d4}}, + {{0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd}, + {0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0}, + {0xc9cf205e47fd592a, 0x77f078b8bd52c42a, 0xf506f293113a5b2b, 0x8b95db85c8323a26}}, + {{0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855}, + {0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d}, + {0x6bbb44ce030279a0, 0xd01c96f5c1b1b73a, 0x23d637982f7705da, 0xec42e1c72e8cd6d1}}, + {{0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69}, + {0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d}, + {0xf49fc33fd63a7e64, 0xa6771c7da34ea29e, 0xd449ebec230f5272, 0x847113938be7cd78}}, + {{0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d}, + {0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f}, + {0x9bf618a6298dd399, 0x598b1e308d408d64, 0x43f5db14c3de1a96, 0xc6fe982db14534dc}}, + {{0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9}, + {0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4}, + {0xb55bc57173db5813, 0xfb3e0abf270fa10a, 0x5245a1f3f4c14623, 0xd54aafbbb75b631c}}, + {{0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb}, + {0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9}, + {0x2787dc32ce61f85a, 0x103b303e76888a3a, 0xb7ab04ed65f54c08, 0xed3b62be8dc73c8e}}, + {{0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510}, + {0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79}, + {0xd5dc4618a3fed28b, 0xf368b9ae351e0d15, 0xd049cd8c98a28f35, 0xf458daf479bbfc0a}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xf8ae4d2ad8453902, 0x7018058ee8db2d1d, 0xaab3995fc7d2c11e, 0x53b16d2324ccca79}, + {0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510}, + {0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5}}, + {{0xbb0d18fd029c6421, 0xbc2d142189298f02, 0x8347f8e68b250e96, 0x7b9f2fe8032d71c9}, + {0xdd63589386f86d9c, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb}, + {0xd87823cd319e0780, 0xefc4cfc1897775c5, 0x4854fb129a0ab3f7, 0x12c49d417238c371}}, + {{0x0950b533ffe83769, 0x21861c1d8e1d6bd1, 0xf022d8381302e510, 0x2509200c6391cab4}, + {0x09b3a01783799542, 0x626dd08faad5ee3f, 0xba00bceeeb70149f, 0x1421b246a0a444c9}, + {0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, 0xadba5e0c0b3eb9dc, 0x2ab5504448a49ce3}}, + {{0x2ed227266f0f5dec, 0x9824ee415ed50824, 0x807bec7c9468d415, 0x7093bae1b521e23f}, + {0xdc07ac631c5d3afa, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d}, + {0x6409e759d6722c41, 0xa674e1cf72bf729b, 0xbc0a24eb3c21e569, 0x390167d24ebacb23}}, + {{0x27f58e3bba353f1c, 0x4c47764dbf6a4361, 0xafbbc4e56e562650, 0x07db2ee6aae1a45d}, + {0xd7bb054ba2f2120b, 0xe2b9ceaeb10589b7, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69}, + {0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287}}, + {{0xe4ca40782cd27cb0, 0xdaf9c323fbe967bd, 0xb29bd34a8ad41e9e, 0x72810497626ede4d}, + {0x32fee570fc386b73, 0xda8b0141da3a8cc7, 0x975ffd0ac8968359, 0x6ee809a1b132a855}, + {0x9444bb31fcfd863a, 0x2fe3690a3e4e48c5, 0xdc29c867d088fa25, 0x13bd1e38d173292e}}, + {{0xd32b4cd8696149b5, 0xe55937d781d8aab7, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0}, + {0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd}, + {0x3630dfa1b802a6b0, 0x880f874742ad3bd5, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9}}, + {{0xd531b8bd2b7b9af6, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49}, + {0x6eccd85278d941ed, 0x2254ae83d22f7843, 0xc522d02e7bbfcdb7, 0x681e3351bff0e4e2}, + {0x8b64b59d83034f45, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b}}, + {{0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}, + {0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}, + {0xa9572810163ec92a, 0x42f81a32a71bb4df, 0x5019d025e4a81f54, 0xe6e5d508bd88172d}}, + {{0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}, + {0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}, + {0x8124cb2ef5456e9f, 0xb15c327dd19253f1, 0x99f7c2009a8707ea, 0xb3cfc0cf800ff5e8}}, + {{0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}, + {0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}, + {0xf9994ae858ae4e9f, 0x8b82f97981647a73, 0x53533feebab221b6, 0xdd20326340161963}}, + {{0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}, + {0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}, + {0x75f736c7553ef355, 0xb9e8649f24d89434, 0x56df3fe1f190538f, 0xd0ed8c0ea69b8c25}}, + {{0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}, + {0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}, + {0x388038ba2932cf1c, 0x1b20172c1c455104, 0x5dd377cf55a225f3, 0x8067ab673fa4357f}}, + {{0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}, + {0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}, + {0x6dece765a17b6533, 0x2b273cca9a270532, 0x73adaba4ac02442e, 0xd8c67cf725d29c19}}, + {{0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}, + {0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}, + {0xe66d68279584c872, 0x2f2fa7dbe52e859c, 0x45fd6352a3e3f3e8, 0x83322f7bc785fcf8}}, + {{0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}, + {0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}, + {0x7f2e6fdb5f28e00d, 0x3ada3df504d77507, 0x4e5c68b4a0c59be6, 0x828043101dff8dcc}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x6e7bb6a1a6205275, 0xaa4f21d7413c8e83, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1}, + {0xd074d8961cae743f, 0xf86d18f5ee1c63ed, 0x97bdc55be7f4ed29, 0x4cbad279663ab108}, + {0x80d19024a0d71fcd, 0xc525c20afb288af8, 0xb1a3974b5f3a6419, 0x7d7fbcefe2007233}}, + {{0xfaef1e6a266b2801, 0x866c68c4d5739f16, 0xf68a2fbc1b03762c, 0x5975435e87b75a8d}, + {0xcd7c5dc5f3c29094, 0xc781a29a2a9105ab, 0x80c61d36421c3058, 0x4f9cd196dcd8d4d7}, + {0x199297d86a7b3768, 0xd0d058241ad17a63, 0xba029cad5c1c0c17, 0x7ccdd084387a0307}}, + {{0xdca6422c6d260417, 0xae153d50948240bd, 0xa9c0c1b4fb68c677, 0x428bd0ed61d0cf53}, + {0x9b0c84186760cc93, 0xcdae007a1ab32a99, 0xa88dec86620bda18, 0x3593ca848190ca44}, + {0x9213189a5e849aa7, 0xd4d8c33565d8facd, 0x8c52545b53fdbbd1, 0x27398308da2d63e6}}, + {{0x42c38d28435ed413, 0xbd50f3603278ccc9, 0xbb07ab1a79da03ef, 0x269597aebe8c3355}, + {0xb9a10e4c0a702453, 0x0fa25866d57d1bde, 0xffb9d9b5cd27daf7, 0x572c2945492c33fd}, + {0xc77fc745d6cd30be, 0xe4dfe8d3e3baaefb, 0xa22c8830aa5dda0c, 0x7f985498c05bca80}}, + {{0x3849ce889f0be117, 0x8005ad1b7b54a288, 0x3da3c39f23fc921c, 0x76c2ec470a31f304}, + {0xd35615520fbf6363, 0x08045a45cf4dfba6, 0xeec24fbc873fa0c2, 0x30f2653cd69b12e7}, + {0x8a08c938aac10c85, 0x46179b60db276bcb, 0xa920c01e0e6fac70, 0x2f1273f1596473da}}, + {{0x4739fc7c8ae01e11, 0xfd5274904a6aab9f, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2}, + {0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, 0xead1a69ebc596162, 0x38ac1997edc5f784}, + {0x0666b517a751b13b, 0x747d06867e9b858c, 0xacacc011454dde49, 0x22dfcd9cbfe9e69c}}, + {{0x8ddbd2e0c30d0cd9, 0xad8e665facbb4333, 0x8f6b258c322a961f, 0x6b2916c05448c1c7}, + {0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472}, + {0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17}}, + {{0xd30a3bd617b28c85, 0xc5d377b739773bea, 0xc6c6e78c1e6a5cbf, 0x0d61b8f78b2ab7c4}, + {0x29fc03580dd94500, 0xecd27aa46fbbec93, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5}, + {0x56a8d7efe9c136b0, 0xbd07e5cd58e44b20, 0xafe62fda1b57e0ab, 0x191a2af74277e8d2}}, + {{0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81}, + {0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223}, + {0x593a58ecb648268f, 0x5c0c2ea7dc146bb9, 0xfbe9042d88b7b7cb, 0x962ba190d38f7ed0}}, + {{0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae}, + {0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f}, + {0x1cfa358d14810950, 0x99d30ce08f1524dc, 0xe70fd9024b3ba497, 0xaec4ac7b4a2d1342}}, + {{0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85}, + {0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1}, + {0xdb8aefde347549f3, 0x03dcbbb6a3afef14, 0xa0e18e84b1a9ef5e, 0xbb25a0e73d8ef32a}}, + {{0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91}, + {0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742}, + {0x000a04b430acaec1, 0x0b67628620eef75f, 0x4203159a65c45cda, 0xe75ee0ee8b2e590d}}, + {{0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3}, + {0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d}, + {0x063dbeb596a55bef, 0x255bd3b3fa5970de, 0x8393dc67806c69c1, 0xdef1732cf3c6ab1c}}, + {{0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef}, + {0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa}, + {0xe243557bf8479959, 0xf7e0ffe174d98ac4, 0xc32831957bfb717e, 0x8750ee9cc0da0dd3}}, + {{0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68}, + {0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0}, + {0x82acea8bfd73d8d5, 0x7fce829624f28a01, 0xcf00531710737222, 0x81621684493c1667}}, + {{0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a}, + {0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286}, + {0xe79c2826eedb3331, 0x853f7eba47758f71, 0xd4328cf67a8fce0a, 0x9dcc85917547051a}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xd550095bab6f4985, 0x04f4cd5b4fbfaf1a, 0x9d8e2ed12a0c7540, 0x2bc24e04b2212286}, + {0x09d4b60b2fe09a14, 0xc384f0afdbb1747e, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a}, + {0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5}}, + {{0x4bcef17f06ffca16, 0xde06e1db692ae16a, 0x0753702d614f42b0, 0x5f6041b45b9212d0}, + {0xd1ab324e1b3a1273, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68}, + {0x7d531574028c2705, 0x80317d69db0d75fe, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998}}, + {{0x1558967b9e6585a3, 0x97c99ce098e98b92, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa}, + {0xf004be62a24d40dd, 0xba0659910452d41f, 0x81c45ee162a44234, 0x4cb829d8a22266ef}, + {0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c}}, + {{0x8416ebd40b50babc, 0x1508722628208bee, 0xa3148fafb9c1c36d, 0x0d07daacd32d7d5d}, + {0x3241c00e7d65318c, 0xe6bee5dcd0e86de7, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3}, + {0xf9c2414a695aa3eb, 0xdaa42c4c05a68f21, 0x7c6c23987f93963e, 0x210e8cd30c3954e3}}, + {{0xac4201f210a71c06, 0x6a65e0aef3bfb021, 0xbc42c35c393632f7, 0x56ea8db1865f0742}, + {0x2b50f16137fe6c26, 0xe102bcd856e404d8, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91}, + {0xfff5fb4bcf535119, 0xf4989d79df1108a0, 0xbdfcea659a3ba325, 0x18a11f1174d1a6f2}}, + {{0x407375ab3f6bba29, 0x9ec3b6d8991e482e, 0x99c80e82e55f92e9, 0x307c13b6fb0c0ae1}, + {0xfbd63cdad27a5f2c, 0xf00fc4bc8aa106d7, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85}, + {0x24751021cb8ab5e7, 0xfc2344495c5010eb, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5}}, + {{0x033cc55ff1b82eb5, 0xb15ae36d411cae52, 0xba40b6198ffbacd3, 0x768edce1532e861f}, + {0x9156fe6b89d8eacc, 0xe6b79451e23126a1, 0xbd7463d93944eb4e, 0x726373f6767203ae}, + {0xe305ca72eb7ef68a, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd}}, + {{0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223}, + {0x5e2702878af34ceb, 0x900b0409b946d6ae, 0x6512ebf7dabd8512, 0x61d9b76988258f81}, + {0xa6c5a71349b7d94b, 0xa3f3d15823eb9446, 0x0416fbd277484834, 0x69d45e6f2c70812f}}, + {{0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}, + {0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}, + {0xe46e24b66e4bd427, 0xa8d969dcb4fd2335, 0x6020611ae0738723, 0xa01e9d7b731de02c}}, + {{0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}, + {0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}, + {0xf306977a69036f82, 0xe223440c84a95fe4, 0x233d1882b6ca2995, 0xe3b08c0d395a80f5}}, + {{0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}, + {0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}, + {0xdcdddfb0c5ea9c99, 0x048c1f1645f5fcd2, 0x031f22b3bef0fcf1, 0xb7255a69046db555}}, + {{0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}, + {0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}, + {0x4a2c3c2e786874e2, 0x8dd4a5c280f1bbec, 0xf284b7b744b8835f, 0xce8e4d9550e1236d}}, + {{0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}, + {0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}, + {0x06b3204e5cfa4209, 0xf0c9b4626007d3f7, 0xd578275a3c44a775, 0xfdde7caef4172345}}, + {{0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}, + {0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}, + {0xe02d36c3c817786b, 0x5d09e1a5e72eb9d3, 0xaf7f0a7dc6dbed89, 0x9590466140f2b696}}, + {{0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}, + {0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}, + {0x1bcf38e7b707e75a, 0x4069f3dda1313ee6, 0x49251f7c9445ea1c, 0xb3b290ccb81ea7f7}}, + {{0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}, + {0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}, + {0xfeca8a1298fe4baa, 0xdcef6b1960f402ef, 0x8acdf0ea7c1b80dd, 0x8e5059664eeeaa1c}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xce16f74bc53c1431, 0x2b9725ce2072edde, 0xb8b9c36fb5b23ee7, 0x7e2e0e450b5cc908}, + {0x9fe62b434f460efb, 0xded303d4a63607d6, 0xf052210eb7a0da24, 0x237e7dbe00545b93}, + {0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3}}, + {{0x65ce6f9b3953b61d, 0xc65839eaafa141e6, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e}, + {0xea423c1c473b50d6, 0x51e87a1f3b38ef10, 0x9b84bf5fb2c9be95, 0x00731fbc78f89a1c}, + {0xe430c71848f81880, 0xbf960c225ecec119, 0xb6dae0836bba15e3, 0x4c4d6f3347e15808}}, + {{0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, 0xdbde712bf7ee0cdf, 0x193fddaaa7e47a22}, + {0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8}, + {0x1fd2c93c37e8876f, 0xa2f61e5a18d1462c, 0x5080f58239241276, 0x6a6fb99ebf0d4969}}, + {{0x6a46c1bb560855eb, 0x2416bb38f893f09d, 0xd71d11378f71acc1, 0x75f76914a31896ea}, + {0xeeb122b5b6e423c6, 0x939d7010f286ff8e, 0x90a92a831dcf5d8c, 0x136fda9f42c5eb10}, + {0xf94cdfb1a305bdd1, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba}}, + {{0x4af766385ead2d14, 0xa08ed880ca7c5830, 0x0d13a6e610211e3d, 0x6a071ce17b806c03}, + {0x9d5a710143307a7f, 0xb063de9ec47da45f, 0x22bbfe52be927ad3, 0x1387c441fd40426c}, + {0xb5d3c3d187978af8, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92}}, + {{0xa92f319097564ca8, 0xff7bb84c2275e119, 0x4f55fe37a4875150, 0x221fd4873cf0835a}, + {0xa60db7d8b28a47d1, 0xa6bf14d61770a4f1, 0xd4a1f89353ddbd58, 0x6c514a63344243e9}, + {0x2322204f3a156341, 0xfb73e0e9ba0a032d, 0xfce0dd4c410f030e, 0x48daa596fb924aaa}}, + {{0x6eca8e665ca59cc7, 0xa847254b2e38aca0, 0x31afc708d21e17ce, 0x676dd6fccad84af7}, + {0x14f61d5dc84c9793, 0x9941f9e3ef418206, 0xcdf5b88f346277ac, 0x58c837fa0e8a79a9}, + {0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, 0xdcc2e77d4935d66a, 0x1c4f73f2c6a57f0a}}, + {{0x0e7a4fbd305fa0bb, 0x829d4ce054c663ad, 0xf421c3832fe33848, 0x795ac80d1bf64c42}, + {0xb36e706efc7c3484, 0x73dfc9b4c3c1cf61, 0xeb1d79c9781cc7e5, 0x70459adb7daf675c}, + {0x1b91db4991b42bb3, 0x572696234b02dcca, 0x9fdf9ee51f8c78dc, 0x5fe162848ce21fd3}}, + {{0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd}, + {0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38}, + {0xbc1520340b4ce28d, 0x39afc08beeeb776d, 0x0111973af9f2c4e8, 0xcd6d6c4c22b5f537}}, + {{0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1}, + {0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0}, + {0xc2fabc2c9dc18654, 0x986beb3d3d875cab, 0x51bc0f338d9e6909, 0x87c93be07dba1545}}, + {{0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b}, + {0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b}, + {0xf3ffc0423f72984d, 0xb267d05c8152d4e8, 0x3f8194324d1a7d0e, 0xd6938d6e20bed5bb}}, + {{0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99}, + {0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752}, + {0xaa493637d00d9bc8, 0xe53b5736e0499857, 0x2ad840301488740d, 0xcfccc8258fed5c41}}, + {{0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f}, + {0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c}, + {0x2d6e72587ea65a3e, 0x9423e326c0f8ec0c, 0xa9a0856cb5329a6f, 0xac255313b34b3ed7}}, + {{0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a}, + {0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685}, + {0x372b53fbae954854, 0xa6a50cdead6a4dc2, 0x29122dcb24fdcf3e, 0xf6d610177da4be33}}, + {{0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee}, + {0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743}, + {0x32757159ee6a2265, 0x5afb2757e22657d0, 0xabf2357e5ca78649, 0x9f22e95c86379575}}, + {{0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4}, + {0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72}, + {0x51654aac40955cca, 0xfaf5af567f9291e4, 0x6d448bfc5200aec6, 0xfc6b2d89ba419e74}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xe2790aae4d077c41, 0x8b938270db7469a3, 0x6eb632dc8abd16a2, 0x720814ecaa064b72}, + {0x315c29c795115389, 0xd7e0e507862f74ce, 0x0c4a762185927432, 0x72de6c984a25a1e4}, + {0xae9ab553bf6aa310, 0x050a50a9806d6e1b, 0x92bb7403adff5139, 0x0394d27645be618b}}, + {{0x4d572251857eedf4, 0xe3724edde19e93c5, 0x8a71420e0b797035, 0x3b3c833687abe743}, + {0xf5396425b23545a4, 0x15a7a27e98fbb296, 0xab6c52bc636fdd86, 0x79d995a8419334ee}, + {0xcd8a8ea61195dd75, 0xa504d8a81dd9a82f, 0x540dca81a35879b6, 0x60dd16a379c86a8a}}, + {{0x35a2c8487381e559, 0x596ffea6d78082cb, 0xcb9771ebdba7b653, 0x5a08b5019b4da685}, + {0x3501d6f8153e47b8, 0xb7a9675414a2f60c, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a}, + {0xc8d4ac04516ab786, 0x595af3215295b23d, 0xd6edd234db0230c1, 0x0929efe8825b41cc}}, + {{0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, 0x83604432238dde87, 0x1e3a5272f5c0753c}, + {0x8b3172b7ad56651d, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f}, + {0xd2918da78159a59c, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128}}, + {{0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, 0xf4cbf12942f5fe00, 0x01a13ff9bdbf0752}, + {0x99852bc3852cfdb0, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99}, + {0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, 0xd527bfcfeb778bf2, 0x303337da7012a3be}}, + {{0x955422228c1c9d7c, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b}, + {0x976d3ccbfad2fdd1, 0xcb88839737a640a8, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b}, + {0x0c003fbdc08d678d, 0x4d982fa37ead2b17, 0xc07e6bcdb2e582f1, 0x296c7291df412a44}}, + {{0x7903de2b33daf397, 0xd0ff0619c9a624b3, 0x8a1d252b555b3e18, 0x2b6d581c52e0b7c0}, + {0xdfb23205dab8b59e, 0x465aeaa0c8092250, 0xd133c1189a725d18, 0x2327370261f117d1}, + {0x3d0543d3623e7986, 0x679414c2c278a354, 0xae43f0cc726196f6, 0x7836c41f8245eaba}}, + {{0xe7a254db49e95a81, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38}, + {0xca651e848011937c, 0xc6b0c46e6ef41a28, 0xb7021ba75f3f8d52, 0x119dff99ead7b9fd}, + {0x43eadfcbf4b31d4d, 0xc6503f7411148892, 0xfeee68c5060d3b17, 0x329293b3dd4a0ac8}}, + {{0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}, + {0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}, + {0x2037b972e6d98322, 0xf4d78763991ab250, 0xd514e2d5999113e8, 0xecb9ef595482589f}}, + {{0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}, + {0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}, + {0xb78126b3e6d01940, 0x9e51d315c56eeaec, 0x7884092c465b21d8, 0x8725f039ef8c0c14}}, + {{0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}, + {0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}, + {0x5625755ecd9de0fb, 0xcf47dd5ea6dd9a86, 0xbffbe68458653e6c, 0xe9532868e7ace289}}, + {{0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}, + {0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}, + {0x507d93bdd1c9dce6, 0x3edfd67867ccafd2, 0x643e481ed4c76edc, 0xdb44dced566adb76}}, + {{0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}, + {0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}, + {0x861808411bb73276, 0x9537c598f787792f, 0x07602b265f1b24d1, 0xbe86dea38ca5b0be}}, + {{0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}, + {0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}, + {0xfd6bfd2c914be631, 0x0f4bb181884b9f5a, 0x30579dcf2bc3b6a9, 0x8f3d2275852e9918}}, + {{0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}, + {0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}, + {0x557517b4c13d5f7f, 0x6796610b12e87e1f, 0x86baec1b8f717a2e, 0x9c8aa42c56890bec}}, + {{0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}, + {0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}, + {0xe5e37854f8b1484c, 0x05392e7166250b98, 0xc1534432b7b06f98, 0x9f3ad110d4465b1b}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x4e59214fe194961a, 0x49be7dc70d71cd4f, 0x9300cfd23b50f22d, 0x4789d446fc917232}, + {0x2879852d5d7cb208, 0xb8dedd70687df2e7, 0xdc0bffab21687891, 0x2b44c043677daa35}, + {0x1a1c87ab074eb78e, 0xfac6d18e99daf467, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4}}, + {{0x0b5d89bc3bfd8bf1, 0xb06b9237c9f3551a, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab}, + {0x702bc5c27cae6d11, 0x44c7699b54a48cab, 0xefbc4056ba492eb2, 0x70d77248d9b6676d}, + {0xaa8ae84b3ec2a05b, 0x98699ef4ed1781e0, 0x794513e4708e85d1, 0x63755bd3a976f413}}, + {{0xb55fa03e2ad10853, 0x356f75909ee63569, 0x9ff9f1fdbe69b890, 0x0d8cc1c48bc16f84}, + {0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56}, + {0x029402d36eb419a9, 0xf0b44e7e77b460a5, 0xcfa86230d43c4956, 0x70c2dd8a7ad166e7}}, + {{0x656194509f6fec0e, 0xee2e7ea946c6518d, 0x9733c1f367e09b5c, 0x2e0fac6363948495}, + {0x91d4967db8ed7e13, 0x74252f0ad776817a, 0xe40982e00d852564, 0x32b8613816a53ce5}, + {0x79e7f7bee448cd64, 0x6ac83a67087886d0, 0xf89fd4d9a0e4db2e, 0x4179215c735a4f41}}, + {{0x8c7094e7d7dced2a, 0x97fb8ac347d39c70, 0xe13be033a906d902, 0x700344a30cd99d76}, + {0xe4ae33b9286bcd34, 0xb7ef7eb6559dd6dc, 0x278b141fb3d38e1f, 0x31fa85662241c286}, + {0xaf826c422e3622f4, 0xc12029879833502d, 0x9bc1b7e12b389123, 0x24bb2312a9952489}}, + {{0xb1a8ed1732de67c3, 0x3cb49418461b4948, 0x8ebd434376cfbcd2, 0x0fee3e871e188008}, + {0x41f80c2af5f85c6b, 0x687284c304fa6794, 0x8945df99a3ba1bad, 0x0d1d2af9ffeb5d16}, + {0xa9da8aa132621edf, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76}}, + {{0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309}, + {0xc959c6c57887b6ad, 0x94e19ead5f90feba, 0x16e24e62a342f504, 0x164ed34b18161700}, + {0x487ed94c192fe69a, 0x61ae2cea3a911513, 0x877bf6d3b9a4de27, 0x78da0fc61073f3eb}}, + {{0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a}, + {0xa29f80f1680c3a94, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd}, + {0xdfc8468d19267cb8, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760}}, + {{0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc}, + {0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28}, + {0xa95753db292a653b, 0x37248ac1cf690ff9, 0xb880be1970b3ad66, 0xa7727ae309379eeb}}, + {{0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22}, + {0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd}, + {0x2aae9a77c12d72fb, 0xed27b02d2c9d21c6, 0xf578b52c1cc871b0, 0xfff2d4e08389c18b}}, + {{0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a}, + {0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d}, + {0x4b17a91ba562e108, 0x1017b7899368565d, 0x4efb309be1a11182, 0xd0af47e37758e370}}, + {{0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa}, + {0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622}, + {0x2d91a3c16efc6055, 0x3f161882090cc556, 0x176973aa8ff9956c, 0xc3cb2e77e0555222}}, + {{0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76}, + {0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b}, + {0xb5b5ab6fdb95a638, 0x29c142211780226f, 0x26bc8398f2dc8e05, 0x96178cf72cf07129}}, + {{0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe}, + {0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f}, + {0x8f67fe41c8a37742, 0xb4f9254a1c027cb7, 0x8a77f312d8dcf8eb, 0xd4f6b97022d0b3bd}}, + {{0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592}, + {0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233}, + {0xbfa022cf65034c94, 0x268dc2bbd719c0ab, 0x6b3fe20fa09a5551, 0xbc1b23c51eb3f7f6}}, + {{0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c}, + {0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2}, + {0x8401396554a3529d, 0x3dc1732cb34d3052, 0x97a22eb404c8295d, 0xf52929bbea9885e7}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xcaf55ec27c59b23f, 0x99aeed3e154d04f2, 0x68441d72e14141f4, 0x140345133932a0a2}, + {0xd91430e0dc028c3c, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c}, + {0x7bfec69aab5cad3d, 0xc23e8cd34cb2cfad, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18}}, + {{0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233}, + {0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592}, + {0x405fdd309afcb346, 0xd9723d4428e63f54, 0x94c01df05f65aaae, 0x43e4dc3ae14c0809}}, + {{0xbc12c7f1a938a517, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f}, + {0xea6f7ac3adc2c6a3, 0xd0e928f6e9717c94, 0xe2d379ead645eaf5, 0x46dd8785c51ffbbe}, + {0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42}}, + {{0x97c749eeb701cb96, 0x83f438d4b6a369c3, 0x62962b8b9a402cd9, 0x6976c7509888df7b}, + {0x5b97946582ffa02a, 0xda096a51fea8f549, 0xa06351375f77af9b, 0x1bcfde61201d1e76}, + {0x4a4a5490246a59a2, 0xd63ebddee87fdd90, 0xd9437c670d2371fa, 0x69e87308d30f8ed6}}, + {{0x435a8bb15656beb0, 0xf8fac9ba4f4d5bca, 0xb9b278c41548c075, 0x3eb0ef76e892b622}, + {0x0f80bf028bc80303, 0x6aae16b37a18cefb, 0xdd47ea47d72cd6a3, 0x61943588f4ed39aa}, + {0xd26e5c3e91039f85, 0xc0e9e77df6f33aa9, 0xe8968c5570066a93, 0x3c34d1881faaaddd}}, + {{0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, 0xa09ba3ea72d926c4, 0x374193513fd8b36d}, + {0xbd5b0b8f2fffe0d9, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a}, + {0xb4e856e45a9d1ed2, 0xefe848766c97a9a2, 0xb104cf641e5eee7d, 0x2f50b81c88a71c8f}}, + {{0x31723c61fc6811bb, 0x9cb450486211800f, 0x768933d347995753, 0x3491a53502752fcd}, + {0x2b552ca0a7da522a, 0x3230b336449b0250, 0xf2c4c5bca4b99fb9, 0x7b2c674958074a22}, + {0xd55165883ed28cdf, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74}}, + {{0x3d420811d06d4a67, 0xbefc048590e0ffe3, 0xf870c6b7bd487bde, 0x6e2a7316319afa28}, + {0x9624778c3e94a8ab, 0x0ad6f3cee9a78bec, 0x948ac7810d743c4f, 0x76627935aaecfccc}, + {0x56a8ac24d6d59a9f, 0xc8db753e3096f006, 0x477f41e68f4c5299, 0x588d851cf6c86114}}, + {{0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}, + {0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}, + {0xf215420b68b3dc19, 0x5590f5da6231b96c, 0xfbdfd3475d6545d3, 0xb4ebbcc9d2f869f2}}, + {{0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}, + {0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}, + {0x0086bb3fa31667e6, 0xa8a2c21b4fa3ae5c, 0xa7cc7e02a5897b83, 0xd278c12185092560}}, + {{0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}, + {0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}, + {0x8812c1113c103a60, 0xfb1faae82b00b7ee, 0x15c285c00e598e34, 0xedf9cc4b6b8301ab}}, + {{0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}, + {0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}, + {0xa48da278e6cd6690, 0xcdcae34a314e254f, 0x823beab6254835fa, 0xa721279ed8713e08}}, + {{0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}, + {0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}, + {0x7ec7459ae3a4d493, 0x798e4913cee4e47f, 0x8400f34e43ceca4f, 0x8ba2d00563f30e1f}}, + {{0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}, + {0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}, + {0xea7905ce9c979c18, 0xf80973b7a8d2cc0d, 0xb08c336087615103, 0xd2bd1def7152b8fe}}, + {{0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}, + {0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}, + {0x3cd2c9c9fbeae8bc, 0x32d410ee7667b7c4, 0x78f591522f6baeef, 0xf433448d5d579a9e}}, + {{0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}, + {0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}, + {0x69611bfafaa31939, 0xc9435897edae52d6, 0xc5e50ae855825bea, 0xf528da24d6134d45}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650}, + {0xcd2a65e777d1f515, 0x548991878faa60f1, 0xb1b73bbcdabc06e5, 0x654878cba97cc9fb}, + {0x969ee405055ce6a1, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba}}, + {{0xdc4267b1834e2457, 0xb67544b570ce1bc5, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650}, + {0xfec7bc0c9b056f85, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9}, + {0xc32d36360415171e, 0xcd2bef118998483b, 0x870a6eadd0945110, 0x0bccbb72a2a86561}}, + {{0x185e962feab1a9c8, 0x86e7e63565147dcd, 0xb092e031bb5b6df2, 0x4024f0ab59d6b73e}, + {0x186d5e4c50fe1296, 0xe0397b82fee89f7e, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2}, + {0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701}}, + {{0x97f5131594dfd29b, 0x6155985d313f4c6a, 0xeba13f0708455010, 0x676b2608b8d2d322}, + {0x21717b0d0f537593, 0x914e690b131e064c, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e}, + {0x8138ba651c5b2b47, 0x8671b6ec311b1b80, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0}}, + {{0xbf525a1e2bc9c8bd, 0xea5b260826479d81, 0xd511c70edf0155db, 0x1ae23ceb960cf5d0}, + {0x6036df5721d34e6a, 0xb1db8827997bb3d0, 0xd3c209c3c8756afa, 0x06e15be54c1dc839}, + {0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7}}, + {{0xd8173793f266c55c, 0xc8c976c5cc454e49, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9}, + {0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8}, + {0x77ed3eeec3efc57a, 0x04e05517d4ff4811, 0xea3d7a3ff1a671cb, 0x120633b4947cfe54}}, + {{0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185}, + {0x82bd31474912100a, 0xde237b6d7e6fbe06, 0xe11e761911ea79c6, 0x07433be3cb393bde}, + {0xff7944c05ce997f4, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f}}, + {{0x157a316443373409, 0xfab8b7eef4aa81d9, 0xb093fee6f5a64806, 0x2e773654707fa7b6}, + {0xaa6202e14e5df981, 0xa20d59175015e1f5, 0x18a275d3bae21d6c, 0x0543618a01600253}, + {0x0deabdf4974c23c1, 0xaa6f0a259dce4693, 0x04202cb8a29aba2c, 0x4b1443362d07960d}}, + {{0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a}, + {0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8}, + {0x884313b36da153b5, 0xe7b78e7b9fec88c7, 0xa4c8bcc801560bae, 0xe79a1871371955b9}}, + {{0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f}, + {0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9}, + {0xc1401484571285d1, 0xb6023d441afd8763, 0xbb1431a2c3ee6bd7, 0xca1e14aa416b80b5}}, + {{0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634}, + {0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3}, + {0x9e6bc21192663eba, 0x79efe0d1b9f4601f, 0x944d0eae7117a672, 0x89489d76033b8a33}}, + {{0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed}, + {0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900}, + {0x2f1078b250cc2593, 0xff2c41a2491cc606, 0xc0d575d063631131, 0xa2e51486dcadbca5}}, + {{0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a}, + {0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c}, + {0xf4ad4a9f9245a524, 0x56ecb0f0444e1254, 0xcf56adf264fb59ca, 0x97ec470c868c1a24}}, + {{0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67}, + {0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14}, + {0x2fc39893b31acf06, 0xf49b3fb8c4a2060b, 0xf9a31074e64c5ce1, 0xcf7b299eaccefd36}}, + {{0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148}, + {0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6}, + {0x0e5666fe8a9c7942, 0xcac22e4111559f2c, 0x7b6b8eccb3645b77, 0x9c059197bc521cee}}, + {{0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1}, + {0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07}, + {0xf9f836837f077c9b, 0xf17aea8735da13a4, 0xab08baf4e9e14490, 0x8434b86d5f2107f1}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x47b837f753242cec, 0x256dc48cc04212f2, 0xe222fbfbe1d928c5, 0x48ea295bad8a2c07}, + {0x299b1c3f57c5715e, 0x96cb929e6b686d90, 0x3004806447235ab3, 0x2c435c24a44d9fe1}, + {0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e}}, + {{0x8487e3d02bc73659, 0x4baf8445059979df, 0xd17c975adcad6fbf, 0x57369f0bdefc96b6}, + {0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148}, + {0xf1a9990175638698, 0x353dd1beeeaa60d3, 0x849471334c9ba488, 0x63fa6e6843ade311}}, + {{0xd15c20536597c168, 0x9f73740098d28789, 0x18aee7f13257ba1f, 0x3418bfda07346f14}, + {0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, 0xdf28074441ca9ede, 0x07073b98f35b7d67}, + {0xd03c676c4ce530d4, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9}}, + {{0xe1f6b79ebf8469ad, 0x15801004e2663135, 0x9a498330af74181b, 0x3ba2504f049b673c}, + {0x9a6ce876760321fd, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a}, + {0x0b52b5606dba5ab6, 0xa9134f0fbbb1edab, 0x30a9520d9b04a635, 0x6813b8f37973e5db}}, + {{0x9854b054334127c1, 0x105d047882fbff25, 0xdb49f7f944186f4f, 0x1768e838bed0b900}, + {0xf194ca56f3157e29, 0x136d35705ef528a5, 0xdd4cef778b0599bc, 0x7d5472af24f833ed}, + {0xd0ef874daf33da47, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a}}, + {{0xf59e6bb319cd63ca, 0x670c159221d06839, 0xb06d565b2150cab6, 0x20fb199d104f12a3}, + {0x12c7bfaeb61ba775, 0xb84e621fe263bffd, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634}, + {0x61943dee6d99c120, 0x86101f2e460b9fe0, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc}}, + {{0x791b4cc1756286fa, 0xdbced317d74a157c, 0x7e732421ea72bde6, 0x01fe18491131c8e9}, + {0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f}, + {0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a}}, + {{0xdbdae701c5738dd3, 0xf9c6f635b26f1bee, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8}, + {0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, 0xf33ae4f552a2c8b4, 0x59aab07a0d40166a}, + {0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46}}, + {{0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}, + {0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}, + {0x49c2e2cab2d69114, 0x0c3cfac1a052ce27, 0x98f46a734b42bd13, 0xdec671f35e9cac02}}, + {{0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}, + {0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}, + {0xf3b63678815ad236, 0xb3bc96aa6423e2bc, 0xfdd3c7f60833142d, 0xa881eb5cb4117b42}}, + {{0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}, + {0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}, + {0xe3829444b085a863, 0x74ca012b6e7cec1e, 0xb5235e393694b97b, 0xaa92e37ced528e42}}, + {{0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}, + {0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}, + {0x2b4b64b9e509841c, 0x29fcfc853754769e, 0x8e211e6006596604, 0x80e7d2f91831d565}}, + {{0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}, + {0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}, + {0x97b42a25740e4995, 0x04742c81094ab4ac, 0xcec6e928564f2dac, 0xee9f6df69eab7fa6}}, + {{0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}, + {0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}, + {0xee8024d2e5a2653e, 0x6388ba432effa3d5, 0x102b410eab2a9015, 0x89a865d617dd2fe9}}, + {{0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}, + {0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}, + {0x2f13eadb2c69b99d, 0xed449d753ca5db0f, 0x5af3c586e343a05b, 0xfbfb5a35f504503c}}, + {{0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}, + {0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}, + {0x39ce842cdfcdb2f6, 0x57efbd175bb7743b, 0x4de10e74b1a5ec9b, 0xf3d5e3b4325d7236}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xccc4b7c7b66e1f7a, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7}, + {0x967c54e91c529ccb, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c}, + {0xc6317bd320324ce4, 0xa81042e8a4488bc4, 0xb21ef18b4e5a1364, 0x0c2a1c4bcda28dc9}}, + {{0xd24dc7d06f1f0447, 0xb2269e3edb87c059, 0xd15b0272fbb2d28f, 0x7c558bd1c6f64877}, + {0xedc4814869bd6945, 0x0d6d907dbe1c8d22, 0xc63bd212d55cc5ab, 0x5a6a9b30a314dc83}, + {0xd0ec1524d396463d, 0x12bb628ac35a24f0, 0xa50c3a791cbc5fa4, 0x0404a5ca0afbafc3}}, + {{0x8c1f40070aa743d6, 0xccbad0cb5b265ee8, 0x574b046b668fd2de, 0x46395bfdcadd9633}, + {0x62bc9e1b2a416fd1, 0xb5c6f728e350598b, 0x04343fd83d5d6967, 0x39527516e7f8ee98}, + {0x117fdb2d1a5d9a9c, 0x9c7745bcd1005c2a, 0xefd4bef154d56fea, 0x76579a29e822d016}}, + {{0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1}, + {0x333cb51352b434f2, 0xd832284993de80e1, 0xb5512887750d35ce, 0x02c514bb2a2777c1}, + {0x684bd5da8bf1b645, 0xfb8bd37ef6b54b53, 0x313916d7a9b0d253, 0x1160920961548059}}, + {{0xb44d166929dacfaa, 0xda529f4c8413598f, 0xe9ef63ca453d5559, 0x351e125bc5698e0b}, + {0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042}, + {0xd4b49b461af67bbe, 0xd603037ac8ab8961, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a}}, + {{0x7a7c8e64ab0168ec, 0xcb5a4a5515edc543, 0x095519d347cd0eda, 0x67d4ac8c343e93b0}, + {0x09454b728e217522, 0xaa58e8f4d484b8d8, 0xd358254d7f46903c, 0x44acc043241c5217}, + {0x1c7d6bbb4f7a5777, 0x8b35fed4918313e1, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd}}, + {{0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff}, + {0x81f06756b11be821, 0x0faff82310a3f3dd, 0xf8b2d0556a99465d, 0x097abe38cc8c7f05}, + {0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd}}, + {{0xf0e268ac61a73b0a, 0xf2fafa103791a5f5, 0xc1e13e826b6d00e9, 0x60fa7ee96fd78f42}, + {0x94fecebebd4dd72b, 0xf46a4fda060f2211, 0x124a5977c0c8d1ff, 0x705304b8fb009295}, + {0xb63d1d354d296ec6, 0xf3c3053e5fad31d8, 0x670b958cb4bd42ec, 0x21398e0ca16353fd}}, + {{0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a}, + {0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995}, + {0x9b72e2601633dce5, 0x9943a9e6d722a883, 0xb82c12de9adbc62e, 0xb62d8e53125074b6}}, + {{0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf}, + {0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b}, + {0xc1b968d5e465fc4f, 0xd1b11995811fc04b, 0x7e5db78891244b35, 0xe56bb1177132fa9c}}, + {{0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac}, + {0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25}, + {0x66a771e61b3b6ead, 0x1033c4b1e35a3194, 0xbadd159f05a4672a, 0x8f9b4454e21b57e6}}, + {{0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf}, + {0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0}, + {0x68af90d09078487e, 0x39db515ffcb51f8f, 0xe137a91c552cb229, 0xfaa4f41f1bbf1a70}}, + {{0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850}, + {0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173}, + {0xdc2f1f7eb4330db4, 0x6d38ba327e69046c, 0x749e8693a6abe1a4, 0xbf5bb20f3fde0687}}, + {{0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee}, + {0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9}, + {0xaa1352c82db4ec9e, 0xbbe1eb829fc736f4, 0x9a997c5e29d39011, 0xfea82a23781f1351}}, + {{0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017}, + {0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99}, + {0xbc83c4cc59af2463, 0x945017e2453ad44d, 0x0166bfd2d2482ce7, 0xd4a48113c8d45931}}, + {{0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb}, + {0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62}, + {0x59e805600ac09ea1, 0x9f0d4a1aec199349, 0x285741104cbb755b, 0x85d6cd7a90a15e6d}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, 0xae64b9004fdd3c75, 0x403a395b53909e62}, + {0x86c5fc16861b7e9a, 0xf6a330476a27c451, 0x01667267a1e93597, 0x05ffb9cd6082dfeb}, + {0xa617fa9ff53f6139, 0x60f2b5e513e66cb6, 0xd7a8beefb3448aa4, 0x7a2932856f5ea192}}, + {{0x0b39d761b02de888, 0x5f550e7ed2414e1f, 0xa6bfa45822e1a940, 0x050a2f7dfd447b99}, + {0xb89c444879639302, 0x4ae4f19350c67f2c, 0xf0b35da8c81af9c6, 0x39d0003546871017}, + {0x437c3b33a650db77, 0x6bafe81dbac52bb2, 0xfe99402d2db7d318, 0x2b5b7eec372ba6ce}}, + {{0xb3bc4bbd83f50eef, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9}, + {0xa694404d613ac8f4, 0x500c3c2bfa97e72c, 0x874104d21fcec210, 0x1b205fb38604a8ee}, + {0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae}}, + {{0xf2a7af510354c13d, 0xd7a0b145aa372b60, 0x2869b96a05a3d470, 0x6528e42d82460173}, + {0x95265514d71eb524, 0xe603d8815df14593, 0x147cdf410d4de6b7, 0x5293b1730437c850}, + {0x23d0e0814bccf226, 0x92c745cd8196fb93, 0x8b61796c59541e5b, 0x40a44df0c021f978}}, + {{0xdaa869894f20ea6a, 0xea14a3d14c620618, 0x6001fccb090bf8be, 0x35f4e822947e9cf0}, + {0x86c96e514bc5d095, 0xf20d4098fca6804a, 0x27363d89c826ea5d, 0x39ca36565719cacf}, + {0x97506f2f6f87b75c, 0xc624aea0034ae070, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f}}, + {{0x6469a17d89735d12, 0xdb6f27d5e662b9f1, 0x9fcba3286a395681, 0x363b8004d269af25}, + {0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, 0x90ec9675ee44d967, 0x64ca348d2a985aac}, + {0x99588e19e4c4912d, 0xefcc3b4e1ca5ce6b, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819}}, + {{0xb919e1515a770641, 0xa9a2e2c74e7f8039, 0x7527250b3df23109, 0x756a7330ac27b78b}, + {0xa290c06142542129, 0xf2e2c2aebe8d5b90, 0xcf2458db76abfe1b, 0x02157ade83d626bf}, + {0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, 0x81a248776edbb4ca, 0x1a944ee88ecd0563}}, + {{0xd5a91d1151039372, 0x2ed377b799ca26de, 0xa17202acfd366b6b, 0x0730291bd6901995}, + {0xbb40a859182362d6, 0xb99f55778a4d1abb, 0x8d18b427758559f6, 0x26c20fe74d26235a}, + {0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49}}, + {{0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}, + {0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}, + {0xc50aa3f2020fa244, 0x22d9d11fd54b1185, 0xee4d4478ede8e8f6, 0xe010db057ff0fcf4}}, + {{0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}, + {0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}, + {0xae7246981506c515, 0x8e436764fa99ad3f, 0x01d47a26a98e680a, 0xfaf135ad9ae1b1c7}}, + {{0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}, + {0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}, + {0x7ab1a119a4e983ee, 0xa6a6f5bd692f323d, 0x8d4d20cb67efde66, 0xa8a116d5b5f400a9}}, + {{0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}, + {0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}, + {0xa3ce21b433d50c14, 0x4fb44fcf01df72e0, 0x48728ff63eb04b99, 0xf8640564f786dbec}}, + {{0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}, + {0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}, + {0x118549185ed74f69, 0x5b3ea6926c577455, 0x084b217d4dde9ecf, 0xc9c16662226842e7}}, + {{0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}, + {0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}, + {0x23341c85cabbbb57, 0x8a7786ccf012416c, 0x879ffb3ced3a2278, 0x9f6c23343d6af19b}}, + {{0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}, + {0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}, + {0x91b021feea09a3f5, 0xd667d9dede9ef64d, 0x87fdfa7ef4522926, 0xe6de5ce945142ff9}}, + {{0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}, + {0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}, + {0x9a98881638269a79, 0x34d4edab8d387fc9, 0x9afacd6626af9111, 0xb5f81eb1a176a833}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x89f5058a382b33f3, 0x5ae2ba0bad48c0b4, 0x8f93b503a53db36e, 0x5aa3ed9d95a232e6}, + {0x2798aaf9b4b75601, 0x5eac72135c8dad72, 0xd2ceaa6161b7a023, 0x1bbfb284e98f7d4e}, + {0x656777e9c7d96561, 0xcb2b125472c78036, 0x65053299d9506eee, 0x4a07e14e5e8957cc}}, + {{0x4ee412cb980df999, 0xa315d76f3c6ec771, 0xbba5edde925c77fd, 0x3f0bac391d313402}, + {0x240b58cdc477a49b, 0xfd38dade6447f017, 0x19928d32a7c86aad, 0x50af7aed84afa081}, + {0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006}}, + {{0x89422f7edfb870fc, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0}, + {0xd75aad9ad9f3c18b, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5}, + {0xdccbe37a35444483, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64}}, + {{0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c}, + {0x6bdeeebe6084034b, 0x3199c2b6780fb854, 0x973376abb62d0695, 0x6e3180c98b647d90}, + {0xee7ab6e7a128b071, 0xa4c1596d93a88baa, 0xf7b4de82b2216130, 0x363e999ddd97bd18}}, + {{0x96a843c135ee1fc4, 0x976eb35508e4c8cf, 0xb42f6801b58cd330, 0x48ee9b78693a052b}, + {0x2f1848dce24baec6, 0x769b7255babcaf60, 0x90cb3c6e3cefe931, 0x231f979bc6f9b355}, + {0x5c31de4bcc2af3c6, 0xb04bb030fe208d1f, 0xb78d7009c14fb466, 0x079bfa9b08792413}}, + {{0xe3903a51da300df4, 0x843964233da95ab0, 0xed3cf12d0b356480, 0x038c77f684817194}, + {0xf3c9ed80a2d54245, 0x0aa08b7877f63952, 0xd76dac63d1085475, 0x1ef4fb159470636b}, + {0x854e5ee65b167bec, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56}}, + {{0xd4c080908a182fcf, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00}, + {0x5d46bc450aa4d801, 0xc3af1227a533b9d8, 0x389e3b262b8906c2, 0x200a1e7e382f581b}, + {0x518db967eaf93ac5, 0x71bc989b056652c0, 0xfe2b85d9567197f5, 0x050eca52651e4e38}}, + {{0xc3431ade453f0c9c, 0xe9f5045eff703b9b, 0xfcd97ac9ed847b3d, 0x4b0ee6c21c58f4c6}, + {0x97ac397660e668ea, 0x9b19bbfe153ab497, 0x4cb179b534eca79f, 0x6151c09fa131ae57}, + {0x3af55c0dfdf05d96, 0xdd262ee02ab4ee7a, 0x11b2bb8712171709, 0x1fef24fa800f030b}}, + {{0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468}, + {0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046}, + {0x823f49b3bb346096, 0xe75c1e531c6da240, 0x85cfcb79d2fba83b, 0xb3b6740875f376d1}}, + {{0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1}, + {0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2}, + {0x31fbf1613fbeba1e, 0x38e00b1df7097cb3, 0x42ab91725477b85c, 0x9b99955f5b2d545a}}, + {{0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f}, + {0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f}, + {0x134d6000e667fde3, 0x62c9e2e05d5f08d0, 0xda0ee2dc8a02d0b6, 0xedb31017f01ef01d}}, + {{0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4}, + {0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df}, + {0xc926143a2b7a4fce, 0x5da69b6d1b524c9a, 0x3e9a6b7f3dee6332, 0xbacf9cb6e791f2a0}}, + {{0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2}, + {0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6}, + {0x9e145f3aaa1252c1, 0xdb4acc010f57c219, 0xc488fbd77c455a07, 0x98707d47675b8172}}, + {{0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661}, + {0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9}, + {0xd2ba76d4e8361885, 0x2fcc028d76cf7207, 0x93d01626ada47426, 0xd124130e3ee33f86}}, + {{0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26}, + {0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e}, + {0x5b00c19675b759ff, 0x4595c7f9426abfc4, 0x60831e50b82a49a2, 0xea1f781aa6c62d04}}, + {{0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9}, + {0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c}, + {0x9d06f29a2021c1a6, 0x30d73a6d4605a052, 0x6637910639e9baef, 0xda2bb7fbb5da937b}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xb496123a6b6c6609, 0xa750fe8580ab5938, 0xf471bf39b7c27a5f, 0x507903ce77ac193c}, + {0xff91a66a90166220, 0xf22552ae5bf1e009, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9}, + {0x62f90d65dfde3e34, 0xcf28c592b9fa5fad, 0x99c86ef9c6164510, 0x25d448044a256c84}}, + {{0xbd68230ec7e9b16f, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e}, + {0x2c7c4415c9022b55, 0x56a0d241812eb1fe, 0xf02ea1c9d7b65e0d, 0x4180512fd5323b26}, + {0xa4ff3e698a48a5db, 0xba6a3806bd95403b, 0x9f7ce1af47d5b65d, 0x15e087e55939d2fb}}, + {{0x12207543745c1496, 0xdaff3cfdda38610c, 0xe4e797272c71c34f, 0x39c07b1934bdede9}, + {0x8894186efb963f38, 0x48a00e80dc639bd5, 0xa4e8092be96c1c99, 0x5a097d54ca573661}, + {0x2d45892b17c9e755, 0xd033fd7289308df8, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079}}, + {{0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, 0x96ef5329c7e899cb, 0x3d4e8dbba668baa6}, + {0xee0f0fddd087a25f, 0x9c7531555c3e34ee, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2}, + {0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d}}, + {{0xb1491d0bd6900c54, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df}, + {0x1e09d94057775696, 0xeed1265c3cd951db, 0xfa9dac2b20bce16f, 0x0f7f76e0e8d089f4}, + {0x36d9ebc5d485b00c, 0xa2596492e4adb365, 0xc1659480c2119ccd, 0x45306349186e0d5f}}, + {{0x94ddd0c1a6cdff1d, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f}, + {0x96a414ec2b072491, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f}, + {0xecb29fff199801f7, 0x9d361d1fa2a0f72f, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2}}, + {{0x4c126cf9d18df255, 0xc1d471e9147a63b6, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2}, + {0x1518e85b31b16489, 0x8faadcb7db710bfb, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1}, + {0xce040e9ec04145bc, 0xc71ff4e208f6834c, 0xbd546e8dab8847a3, 0x64666aa0a4d2aba5}}, + {{0x6841435a7c06d912, 0xca123c21bb3f830b, 0xd4b37b27b1cbe278, 0x1d753b84c76f5046}, + {0xb0c53bf73337e94c, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468}, + {0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e}}, + {{0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}, + {0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}, + {0x0ef3694c802044ac, 0x60656ca1ede31506, 0x20eec93bc5a467c0, 0x884d1c0fa2c16650}}, + {{0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}, + {0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}, + {0x6b49da1a0eaa3e27, 0xbe840c586684846e, 0x3dd342239294d9ff, 0xaebba1eb2232ad0b}}, + {{0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}, + {0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}, + {0xf2d76bd9af9917cd, 0x033c087acf837394, 0xe4ac2587f3eeed02, 0xf863e8f427bc4c77}}, + {{0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}, + {0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}, + {0x3f40e26af7bd568f, 0x4d2c3c9ca770d1c1, 0xf569ebc744ae1d10, 0xea7c2887c3e34079}}, + {{0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}, + {0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}, + {0x96d10ebf6bdd1ac0, 0x343f38c3d4a2098e, 0xdefeb0188bb31fd6, 0xf9de1d382ccfb783}}, + {{0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}, + {0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}, + {0x7804046343f722c8, 0x75f994c51e113d64, 0xf2a8dbd424e03e40, 0xe3cadf5ca159b449}}, + {{0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}, + {0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}, + {0x89acfa25fc2407f5, 0x5b250db6ebcb3242, 0x84b52a322db57713, 0xff06bfae11fbfabc}}, + {{0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}, + {0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}, + {0x95104560cbad7952, 0xa3e4006bdaef825e, 0x08a444329926b4c9, 0x8d1b8d6cf0ce9205}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x37d653fb1aa73196, 0x0f9495303fd76418, 0xad200b09fb3a17b2, 0x544d49292fc8613e}, + {0x22d2aff530976b86, 0x8d90b806c2d24604, 0xdca1896c4de5bae5, 0x28005fe6c8340c17}, + {0x6aefba9f34528688, 0x5c1bff9425107da1, 0xf75bbbcd66d94b36, 0x72e472930f316dfa}}, + {{0x2695208c9781084f, 0xb1502a0b23450ee1, 0xfd9daea603efde02, 0x5a9d2e8c2733a34c}, + {0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438}, + {0x765305da03dbf7e5, 0xa4daf2491434cdbd, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543}}, + {{0x8d356b23c3d330b2, 0xf21c8b9bb0471b06, 0xb36c316c6e42b83c, 0x07d79c7e8beab10d}, + {0xd7ef93bb07af9753, 0x583ed0cf3db766a7, 0xce6998bf6e0b1ec5, 0x47b7ffd25dd40452}, + {0x87fbfb9cbc08dd12, 0x8a066b3ae1eec29b, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6}}, + {{0x80d253a6bccba34a, 0x3e61c3a13838219b, 0x90c3b6019882e396, 0x1c3d05775d0ee66f}, + {0xcda86f40216bc059, 0x1fbb231d12bcd87e, 0xb4956a9e17c70990, 0x38750c3b66d12e55}, + {0x692ef1409422e51a, 0xcbc0c73c2b5df671, 0x21014fe7744ce029, 0x0621e2c7d330487c}}, + {{0xaf9860cc8259838d, 0x90ea48c1c69f9adc, 0x6526483765581e30, 0x0007d6097bd3a5bc}, + {0xb7ae1796b0dbf0f3, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d}, + {0xc0bf1d950842a94b, 0xb2d3c363588f2e3e, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86}}, + {{0xeceea2ef5da27ae1, 0x597c3a1455670174, 0xc9a62a126609167a, 0x252a5f2e81ed8f70}, + {0x90034704cc9d28c7, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a}, + {0x0d2894265066e80d, 0xfcc3f785307c8c6b, 0x1b53da780c1112fd, 0x079c170bd843b388}}, + {{0x0506ece464fa6fff, 0xbee3431e6205e523, 0x3579422451b8ea42, 0x6dec05e34ac9fb00}, + {0xcdd6cd50c0d5d056, 0x9af7686dbb03573b, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc}, + {0x94b625e5f155c1b3, 0x417bf3a7997b7b91, 0xc22cbddc6d6b2600, 0x51445e14ddcd52f4}}, + {{0x57502b4b3b144951, 0x8e67ff6b444bbcb3, 0xb8bd6927166385db, 0x13186f31e39295c8}, + {0x893147ab2bbea455, 0x8c53a24f92079129, 0x4b49f948be30f7a7, 0x12e990086e4fd43d}, + {0xf10c96b37fdfbb2e, 0x9f9a935e121ceaf9, 0xdf1136c43a5b983f, 0x77b2e3f05d3e99af}}, + {{0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643}, + {0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f}, + {0x941bbfb2f143ad13, 0x51b9dcc44e586e0a, 0xd513e8f12da24bd4, 0xe272026999ba296b}}, + {{0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a}, + {0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24}, + {0x78410b4b95a5843e, 0x2dd662e4a03e2f9d, 0x7dbf67e722cde9b7, 0xa3a5414e1a5d1fc2}}, + {{0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab}, + {0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192}, + {0x84b70a8beb44c0b8, 0x9738311b51233377, 0x12d06c9e86127f41, 0xda28f477a08843b4}}, + {{0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa}, + {0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6}, + {0xd398b8bfd36ea3b5, 0xe4232e57f4f2cbf5, 0xa1a9fe42f84bc0a0, 0xdaaa4b1faac65dbd}}, + {{0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47}, + {0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00}, + {0x0e3e4a1d21cce325, 0xa560a271ea035bdf, 0x605bc70e8426cd4e, 0xd5c7e40fe39eb918}}, + {{0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7}, + {0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660}, + {0x34ee948c5b642cd2, 0xfda55294dc6d8d61, 0x4b86c105c0aa264e, 0x8d5efa9ebf987446}}, + {{0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847}, + {0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784}, + {0xc390632e2b5af284, 0x49dbbf8839015481, 0x900640b7ca7f68d1, 0xffc8a77c4ccd5304}}, + {{0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2}, + {0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2}, + {0xe2a526b76f44fd1a, 0xaf1df74ef13daeea, 0x5d95dd76b10de8fd, 0xb236dccbc4adb7fa}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xfd0d75879cf12657, 0xe82fef94e53a0e29, 0xcc34a7f05bbb4be7, 0x0b251172a50c38a2}, + {0x9532f48fcc5cd29b, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2}, + {0x1d5ad94890bb02c0, 0x50e208b10ec25115, 0xa26a22894ef21702, 0x4dc923343b524805}}, + {{0xe3828c400f8086b6, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784}, + {0x3ad3e3ebf36c4975, 0xd75d25a537862125, 0xe873943da025a516, 0x6bbc7cb4c411c847}, + {0x3c6f9cd1d4a50d56, 0xb6244077c6feab7e, 0x6ff9bf483580972e, 0x00375883b332acfb}}, + {{0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, 0xb5ad8691dcd5ca31, 0x67238dbd8c450660}, + {0xc98bec856c75c99c, 0xe44184c000e33cf4, 0x0a676b9bba907634, 0x669e2cb571f379d7}, + {0xcb116b73a49bd308, 0x025aad6b2392729e, 0xb4793efa3f55d9b1, 0x72a1056140678bb9}}, + {{0xa2b6812b1cc9249d, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00}, + {0x0d8d2909e2e505b6, 0x98ca78abc0291230, 0x77ef5569a9b12327, 0x7c77897b81439b47}, + {0xf1c1b5e2de331cb5, 0x5a9f5d8e15fca420, 0x9fa438f17bd932b1, 0x2a381bf01c6146e7}}, + {{0xac9b9879cfc811c1, 0x8b7d29813756e567, 0x50da4e607c70edfc, 0x5dbca62f884400b6}, + {0xf7c0be32b534166f, 0x27e6ca6419cf70d4, 0x934df7d7a957a759, 0x5701461dabdec2aa}, + {0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242}}, + {{0x6fc09f5266ddd216, 0xdce560a7c8e37048, 0xec65939da2df62fd, 0x7a869ae7e52ed192}, + {0x78409b1d87e463d4, 0xad4da95acdfb639d, 0xec28773755259b9c, 0x69c806e9c31230ab}, + {0x7b48f57414bb3f22, 0x68c7cee4aedccc88, 0xed2f936179ed80be, 0x25d70b885f77bc4b}}, + {{0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24}, + {0x98459d29bb1ae4d4, 0x56b9c4c739f954ec, 0x832743f6c29b4b3e, 0x21ea8e2798b6878a}, + {0x87bef4b46a5a7b9c, 0xd2299d1b5fc1d062, 0x82409818dd321648, 0x5c5abeb1e5a2e03d}}, + {{0x14722af4b73c2ddb, 0xbc470c5f5a05060d, 0x00943eac2581b02e, 0x0e434b3b1f499c8f}, + {0x02cde6de1306a233, 0x7b5a52a2116f8ec7, 0xe1c681f4c1163b5b, 0x241d350660d32643}, + {0x6be4404d0ebc52c7, 0xae46233bb1a791f5, 0x2aec170ed25db42b, 0x1d8dfd966645d694}}, + {{0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}, + {0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}, + {0xe3d3bada20dff283, 0xa3c4d229403598b5, 0xf5f8184e1e7cbfcf, 0x965e6719b0e318e9}}, + {{0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}, + {0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}, + {0x244ea27ad5e7e760, 0x0c1b552c79225328, 0xbb451d7ef0093b7d, 0xb930b3b8c250fe30}}, + {{0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}, + {0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}, + {0xa6113206c6f41e0a, 0x56bddfbb8d731c0e, 0x7d76e399856b0f0b, 0x84e20b48c76f0bc9}}, + {{0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}, + {0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}, + {0x4b5eaa34d72e71e8, 0x1533b9b9e7931af7, 0x3b630b6c937dbc76, 0xd85937f651a2cbef}}, + {{0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}, + {0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}, + {0x0b1389b7002b31bb, 0x1fba150fab5373e3, 0x772dda7de2f6ca83, 0xbc4d9e236514b7a6}}, + {{0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}, + {0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}, + {0x07cb8b63a45d6a3a, 0x296b83a435c82da5, 0x990ec4581836ce95, 0xa94250dc724bf353}}, + {{0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}, + {0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}, + {0x9dc6243f8f322e44, 0x9f01757493827565, 0x4c77b84314bfed9f, 0xf6fb2f84788861a1}}, + {{0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}, + {0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}, + {0x57c970fdc761a012, 0x6fbcc4fd30721bc4, 0x505e02a23abed9bc, 0xc17017c2fcd0fec8}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x296fa9c59c2ec4de, 0xbc8b61bf4f84f3cb, 0x1c7706d917a8f908, 0x63b795fc7ad3255d}, + {0xd598639c12ddb0a4, 0xa5d19f30c024866b, 0xd17c2f0358fce460, 0x07a195152e095e8a}, + {0xa8368f02389e5fc8, 0x90433b02cf8de43b, 0xafa1fd5dc5412643, 0x3e8fe83d032f0137}}, + {{0x2f8b15b90570a294, 0x94f2427067084549, 0xde1c5ae161bbfd84, 0x75ba3b797fac4007}, + {0x08704c8de8efd13c, 0xdfc51a8e33e03731, 0xa59d5da51260cde3, 0x22d60899a6258c86}, + {0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, 0xb38847bceb401260, 0x0904d07b87779e5e}}, + {{0xb4ce1fd4ddba919c, 0xcf31db3ec74c8daa, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07}, + {0xf4322d6648f940b9, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c}, + {0xf834749c5ba295a0, 0xd6947c5bca37d25a, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac}}, + {{0x362ab9e3f53533eb, 0x338568d56eb93d40, 0x9e0e14521d5a5572, 0x1d24a86d83741318}, + {0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754}, + {0xf4ec7648ffd4ce1f, 0xe045eaf054ac8c1c, 0x88d225821d09357c, 0x43b261dc9aeb4859}}, + {{0xe55b1e1988bb79bb, 0xa09ed07dc17a359d, 0xb02c2ee2603dea33, 0x326055cf5b276bc2}, + {0x19513d8b6c951364, 0x94fe7126000bf47b, 0x028d10ddd54f9567, 0x02b4d5e242940964}, + {0xb4a155cb28d18df2, 0xeacc4646186ce508, 0xc49cf4936c824389, 0x27a6c809ae5d3410}}, + {{0x8ba6ebcd1f0db188, 0x37d3d73a675a5be8, 0xf22edfa315f5585a, 0x2cb67174ff60a17e}, + {0xcd2c270ac43d6954, 0xdd4a3e576a66cab2, 0x79fa592469d7036c, 0x221503603d8c2599}, + {0x59eecdf9390be1d0, 0xa9422044728ce3f1, 0x82891c667a94f0f4, 0x7b1df4b73890f436}}, + {{0xe492f2e0b3b2a224, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992}, + {0x5f2e221807f8f58c, 0xe3555c9fd49409d4, 0xb2aaa88d1fb6a630, 0x68698245d352e03d}, + {0xdbb15d852a18187a, 0xf3e4aad386ddacd7, 0x44bae2810ff6c482, 0x46cf4c473daf01cf}}, + {{0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40}, + {0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb}, + {0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716}}, + {{0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb}, + {0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7}, + {0xb57619747d4853ea, 0x0be326d864594846, 0xe9193def1e727890, 0x835324f080e4f639}}, + {{0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7}, + {0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb}, + {0x647bf0990ec9ecc5, 0xe7b9ddbd8feffc16, 0x9a12ba051b5daf7f, 0xf5d79dc6c0258cdf}}, + {{0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f}, + {0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855}, + {0xd8d3e0b9065c6faf, 0x36e45c48669a8433, 0x519eb4cfb075e3f1, 0x85035528f466fe84}}, + {{0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea}, + {0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4}, + {0x7eaa1dade5ca3177, 0x41eff2b206edfd71, 0x4007f4075a822313, 0xa8cbd2369294391b}}, + {{0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5}, + {0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668}, + {0x54c9f580daa9c859, 0xdaeddd75b7f086a7, 0x38a2fad89eeb4b1c, 0xddd269da268901d5}}, + {{0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61}, + {0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c}, + {0x3a3946a559f956ff, 0x6eb480614f97da0e, 0xd58ce094bb036100, 0xcf220c7a9d8fa303}}, + {{0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d}, + {0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f}, + {0x3b4999b5c58fea3b, 0x89e6b0f0f56fb1eb, 0x5a9eb3c65bf693ec, 0x932f00af68601312}}, + {{0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad}, + {0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365}, + {0xf0e691f2e47d9372, 0x08e00f1db69f1c24, 0x9eece98fdc48bc93, 0xf30f15a788258d7d}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x7afcd613efa9d697, 0x0cc45aa41c067959, 0xa56fe104c1fada96, 0x3a73b70472e40365}, + {0x7b26e56b9e2d4734, 0xc4c7132b81c61675, 0xef5c9525ec9cde7f, 0x39c80b16e71743ad}, + {0x0f196e0d1b826c68, 0xf71ff0e24960e3db, 0x6113167023b7436c, 0x0cf0ea5877da7282}}, + {{0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, 0xc75e33c740d6c71b, 0x7bb51279cb3c042f}, + {0xe332ced43ba6945a, 0xde0b1361e881c05d, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d}, + {0xc4b6664a3a70159f, 0x76194f0f0a904e14, 0xa5614c39a4096c13, 0x6cd0ff50979feced}}, + {{0xc0e067e78f4428ac, 0x14835ab0a61135e3, 0xf21d14f338062935, 0x6390a4c8df04849c}, + {0x7fecfabdb04ba18e, 0xd0fc7bfc3bddbcf7, 0xa41d486e057a131c, 0x641a4391f2223a61}, + {0xc5c6b95aa606a8db, 0x914b7f9eb06825f1, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc}}, + {{0x4e3dcbdad1bff7f9, 0xc9118e8220645717, 0xbacccebc0f189d56, 0x1b4822e9d4467668}, + {0x33bef2bd68bcd52c, 0xc649dbb069482ef2, 0xb5b6ee0c41cb1aee, 0x5c294d270212a7e5}, + {0xab360a7f25563781, 0x2512228a480f7958, 0xc75d05276114b4e3, 0x222d9625d976fe2a}}, + {{0x1c717f85b372ace1, 0x81930e694638bf18, 0x239cad056bc08b58, 0x0b34271c87f8fff4}, + {0x0f94be7e0a344f85, 0xeb2faa8c87f22c38, 0x9ce1e75e4ee16f0f, 0x43e64e5418a08dea}, + {0x8155e2521a35ce63, 0xbe100d4df912028e, 0xbff80bf8a57ddcec, 0x57342dc96d6bc6e4}}, + {{0xefeef065c8ce5998, 0xbf029510b5cbeaa2, 0x8c64a10620b7c458, 0x35134fb231c24855}, + {0xf3c3bcb71e707bf6, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f}, + {0x272c1f46f9a3902b, 0xc91ba3b799657bcc, 0xae614b304f8a1c0e, 0x7afcaad70b99017b}}, + {{0xc25ded54a4b8be41, 0x902d13e11bb0e2dd, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb}, + {0xa88141ecef842b6b, 0x55e7b14797abe6c5, 0x8c748f9703784ffe, 0x5b50a1f7afcd00b7}, + {0x9b840f66f1361315, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320}}, + {{0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7}, + {0x960e737b6ecb9d17, 0xfaf24948d67ceae1, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb}, + {0x4a89e68b82b7abf0, 0xf41cd9279ba6b7b9, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6}}, + {{0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}, + {0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}, + {0x2652f550ccccac0a, 0xc799625a532cf61a, 0xc3a89a753777080f, 0xb54c75aefad34105}}, + {{0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}, + {0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}, + {0xe10c7543dcb0cf7b, 0x65a88042ebfa21f7, 0xa17d5aebcb19d5f2, 0xa00be78d9d8e485e}}, + {{0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}, + {0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}, + {0x423f91235906d9f1, 0x86c10c0b9be4e0cc, 0x7d13ed7f627cc176, 0xfa400fdcd75eec76}}, + {{0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}, + {0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}, + {0xf870d0ce27c6b9b3, 0xc762ce7c216b5aef, 0x2e1c9392e866907f, 0xce73726c6c565784}}, + {{0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}, + {0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}, + {0x9f92c87c91201ec9, 0xcdcac1ea0fee5426, 0x9b4fc53cda48c469, 0xe22a9bbb8da02a51}}, + {{0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}, + {0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}, + {0x6bc194afa36235ee, 0xcfdaa8445883c8e5, 0x678c51a9becb89ae, 0xec3b7c98663a75a3}}, + {{0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}, + {0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}, + {0x681738ed61f9d48b, 0xb61b70b0d6cdf527, 0xa4131eb490e797c0, 0xaa30e149d2aafce8}}, + {{0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}, + {0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}, + {0x6298c004ec679776, 0xc35a0426bea23847, 0x1fb133c420d8c4a1, 0xebdf97c24ab1b32d}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x9062b2e0d91a78bc, 0x47c9889cc8509667, 0x9df54a66405070b8, 0x7369e6a92493a1bf}, + {0xe1014434dcc5caed, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4}, + {0x9d673ffb13986864, 0x3ca5fbd9415dc7b8, 0xe04ecc3bdf273b5e, 0x1420683db54e4cd2}}, + {{0xb478bd1e249dd197, 0x620c35005e58c102, 0xfb02d32fccbaac5c, 0x60b63bebf508a72d}, + {0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, 0xd3b0da49a66bde53, 0x31e83b4161d081c1}, + {0x97e8c7129e062b4f, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317}}, + {{0x5879101065c23d58, 0x8b9d086d5094819c, 0xe2402fa912c55fa7, 0x669a6564570891d4}, + {0x3076b5e37df58c52, 0xd73ab9dde799cc36, 0xbd831ce34913ee20, 0x1a56fbaa62ba0133}, + {0x943e6b505c9dc9ec, 0x302557bba77c371a, 0x9873ae5641347651, 0x13c4836799c58a5c}}, + {{0x423a5d465ab3e1b9, 0xfc13c187c7f13f61, 0x19f83664ecb5b9b6, 0x66f80c93a637b607}, + {0xc4dcfb6a5d8bd080, 0xdeebc4ec571a4842, 0xd4b2e883b8e55365, 0x50bdc87dc8e5b827}, + {0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae}}, + {{0x8fa47ff83362127d, 0xbc9f6ac471cd7c15, 0x6e71454349220c8b, 0x0e645912219f732e}, + {0xc297e60008bac89a, 0x7d4cea11eae1c3e0, 0xf3e38be19fe7977c, 0x3a3a450f63a305cd}, + {0x078f2f31d8394627, 0x389d3183de94a510, 0xd1e36c6d17996f80, 0x318c8d9393a9a87b}}, + {{0xf2745d032afffe19, 0x0c9f3c497f24db66, 0xbc98d3e3ba8598ef, 0x224c7c679a1d5314}, + {0x5d669e29ab1dd398, 0xfc921658342d9e3b, 0x55851dfdf35973cd, 0x509a41c325950af6}, + {0xbdc06edca6f925e9, 0x793ef3f4641b1f33, 0x82ec12809d833e89, 0x05bff02328a11389}}, + {{0x3632137023cae00b, 0x544acf0ad1accf59, 0x96741049d21a1c88, 0x780b8cc3fa2a44a7}, + {0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea}, + {0x1ef38abc234f305f, 0x9a577fbd1405de08, 0x5e82a51434e62a0d, 0x5ff418726271b7a1}}, + {{0x398e080c1789db9d, 0xa7602025f3e778f5, 0xfa98894c06bd035d, 0x106a03dc25a966be}, + {0xe5db47e813b69540, 0xf35d2a3b432610e1, 0xac1f26e938781276, 0x29d4db8ca0a0cb69}, + {0xd9ad0aaf333353d0, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa}}, + {{0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4}, + {0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3}, + {0xe314d6fcd66a8cde, 0x8373355d6afd2f11, 0x6e405bcbee331984, 0xa87bb7e69b57ce18}}, + {{0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f}, + {0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331}, + {0xf477946da02b26b6, 0x9f6f9085c9d957f2, 0x132c984b467542ed, 0xd789414e210cbb30}}, + {{0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534}, + {0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54}, + {0x25ed393bf87ce20f, 0xf25dcf28b2a3aef2, 0xb54eace1942bfb1e, 0xbef94e99430bbf10}}, + {{0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04}, + {0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1}, + {0x517ac36b54992393, 0x149dcbc12089d291, 0x0f71f1e7904d082e, 0xb0f4e3fd8ff54c85}}, + {{0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c}, + {0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659}, + {0x9e00f9bf5879d40e, 0x7e353f65a0ee5401, 0x6fb87cfbaa2ed544, 0xe65b421e6ba5178c}}, + {{0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d}, + {0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592}, + {0xe4fa5e6903c25a39, 0x8828573dbc4a612f, 0xf925c29d682e86e7, 0x99044b6b0edcac08}}, + {{0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8}, + {0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58}, + {0xca860d94fd7d3b28, 0x9b2a6d0db0501051, 0x48321284d737383f, 0x956d84948e8c5728}}, + {{0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e}, + {0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff}, + {0x0fe3370e8b8e33ce, 0x6adbd1c8a86f7d44, 0xd8889f6c2c1b94a0, 0xd2ec2aa5d7427a04}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xdfdacbee4324c0e9, 0x054442883f955bb7, 0xdef7aaa8ea31609f, 0x68aee70642287cff}, + {0xf68fe2e8809de054, 0xe3bc096a9c82bad1, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e}, + {0xf01cc8f17471cc0c, 0x95242e37579082bb, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb}}, + {{0xfac5d2065b35b8da, 0xa8da8a9a85624bb7, 0xccd2ca913d21cd0f, 0x6b8341ee8bf90d58}, + {0xbf019cce7aee7a52, 0xa8ded2b6e454ead3, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8}, + {0x3579f26b0282c4b2, 0x64d592f24fafefae, 0xb7cded7b28c8c7c0, 0x6a927b6b7173a8d7}}, + {{0x1f6db24f986e4656, 0x1021c02ed1e9105b, 0xf8ff3fff2cc0a375, 0x1d2a6bf8c6c82592}, + {0x8d7040863ece88eb, 0xf0e307a980eec08c, 0xac2250610d788fda, 0x056d92a43a0d478d}, + {0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7}}, + {{0x751a50b9d85c0fb8, 0xd1afdc258bcf097b, 0x2f16a6a38309a969, 0x14ddff9ee5b00659}, + {0xd6d70996f12309d6, 0xdbfb2385e9c3d539, 0x46d602b0f7552411, 0x270a0b0557843e0c}, + {0x61ff0640a7862bcc, 0x81cac09a5f11abfe, 0x9047830455d12abb, 0x19a4bde1945ae873}}, + {{0x9b9f26f520a6200a, 0x64804443cf13eaf8, 0x8a63673f8631edd3, 0x72bbbce11ed39dc1}, + {0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04}, + {0xae853c94ab66dc47, 0xeb62343edf762d6e, 0xf08e0e186fb2f7d1, 0x4f0b1c02700ab37a}}, + {{0xe1706787d81951fa, 0xa10a2c8eb290c77b, 0xe7382fa03ed66773, 0x0a4d84710bcc4b54}, + {0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, 0xc8172ec9d151486b, 0x68abe9443e0a7534}, + {0xda12c6c407831dcb, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef}}, + {{0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, 0x954e6727b1244480, 0x7f792f9d2699f331}, + {0xa485ccd539e4ecf2, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f}, + {0x0b886b925fd4d924, 0x60906f7a3626a80d, 0xecd367b4b98abd12, 0x2876beb1def344cf}}, + {{0xdc84e93563144691, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3}, + {0xd594b3333a8a85f8, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4}, + {0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, 0x91bfa43411cce67b, 0x5784481964a831e7}}, + {{0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}, + {0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}, + {0x2b792e4e35021f14, 0xb0c0191ce9c4ae7e, 0xa65750f2050d6c65, 0xb354384213ccf8d5}}, + {{0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}, + {0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}, + {0xc0c1f9590e28216c, 0xc10689d871f9dcf7, 0x73eb09d9b1759388, 0x9ac65f76eab7b8a6}}, + {{0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}, + {0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}, + {0xbd818f86bb645399, 0x7aa51c92431dcef5, 0xb35189dea07be583, 0xc7618bf365631e29}}, + {{0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}, + {0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}, + {0x5917d8bbf75b0004, 0x8c71e88163ea8926, 0x88ccb749c2fd4c0d, 0xb0b431b2319433ae}}, + {{0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}, + {0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}, + {0xa1823ee922424a05, 0xd6ab2149725a22d2, 0xe349f7e8cccb5d6d, 0xb585b0d9e766e528}}, + {{0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}, + {0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}, + {0xd727e8d6bf219330, 0x7040d30fdd268cc5, 0xe9280322dca4fe2e, 0xf7bdf122a0320f1a}}, + {{0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}, + {0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}, + {0x37ebc4c2cf144f61, 0x8a76eaa5429ad1cf, 0x9ac3c3ce7092a3ce, 0xda8f04e83d86e9e0}}, + {{0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}, + {0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}, + {0xf00d0d0626a91e92, 0x5218688a60ca94d1, 0xe5b96744a093fda3, 0xefb44297ebfb6584}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xda7c2b256768d593, 0x98c1c0574422ca13, 0xf1a80bd5ca0ace1d, 0x29cdd1adc088a690}, + {0xd6cfd1ef5fddc09c, 0xe82b3efdf7575dce, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b}, + {0x0ff2f2f9d956e148, 0xade797759f356b2e, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b}}, + {{0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149}, + {0xa95d9a5fd67ff163, 0xe92be69d4cc75681, 0xb7f8024cde20f257, 0x204f2a20fb072df5}, + {0xc8143b3d30ebb079, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f}}, + {{0x3efa367f2cb61575, 0xf5f96f761cd6026c, 0xe8c7142a65b52562, 0x3dcb65ea53030acd}, + {0x192ea9550bb8245a, 0xc8e6fba88f9050d1, 0x7986ea2d88a4c935, 0x241c5f91de018668}, + {0x28d8172940de6caa, 0x8fbf2cf022d9733a, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5}}, + {{0xcdff20ab8362fa4a, 0x57e118d4e21a3e6e, 0xe3179617fc39e62b, 0x0d9a53efbc1769fd}, + {0x0358c34e04f410ce, 0xb6135b5a276e0685, 0x5d9670c7ebb91521, 0x04d654f321db889c}, + {0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7}}, + {{0xf4a718025fb15f95, 0x3df65f346b5c1b8f, 0xcdfcf08500e01112, 0x11b50c4cddd31848}, + {0x24c3b291af372a4b, 0x93da8270718147f2, 0xdd84856486899ef2, 0x4a96314223e0ee33}, + {0xa6e8274408a4ffd6, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51}}, + {{0xa71fce5ae2242584, 0x26ea725692f58a9e, 0xd21a09d71cea3cf4, 0x73fcdd14b71c01e6}, + {0x30e2616ec49d0b6f, 0xe456718fcaec2317, 0x48eb409bf26b4fa6, 0x3042cee561595f37}, + {0x427e7079449bac41, 0x855ae36dbce2310a, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6}}, + {{0x64fcb3ae34dcb9ce, 0x97500323e348d0ad, 0x45b3f07d62c6381b, 0x61545379465a6788}, + {0xc9bd78f6570eac28, 0xe55b0b3227919ce1, 0x65fc3eaba19b91ed, 0x25c425e5d6263690}, + {0x3f3e06a6f1d7de6e, 0x3ef976278e062308, 0x8c14f6264e8a6c77, 0x6539a08915484759}}, + {{0xe9d21f74c3d2f773, 0xc150544125c46845, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c}, + {0xddc4dbd414bb4a19, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90}, + {0xd486d1b1cafde0c6, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a}}, + {{0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00}, + {0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0}, + {0x9c4587571da27fa4, 0x9c9ae1ff6bcccb6f, 0xb727d0dfd7731acd, 0xc5ce5405c94a8adb}}, + {{0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376}, + {0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696}, + {0xdf7512b4b76c4caf, 0xc1040dc141a6469b, 0x289d214f245a1af8, 0x969f84297e42626b}}, + {{0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1}, + {0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec}, + {0x90a732a2aa500682, 0x45c155a38aa988de, 0x8a3edc666e9add82, 0x9641ecbc3d0d4ca1}}, + {{0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896}, + {0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc}, + {0xad6a7055ec329839, 0x69a11f7e74244ae8, 0xe91a7255d177ba4c, 0xca82c682ab662570}}, + {{0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee}, + {0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9}, + {0x6c79625c0b1c3499, 0x40fc6d0abf086881, 0xfd9dfb032fb9c47c, 0xc136e58961139112}}, + {{0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1}, + {0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf}, + {0x7a9c2e65df99306e, 0xbfe40273b2338328, 0x2689594132f2709d, 0x9830288c5d874fa1}}, + {{0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339}, + {0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4}, + {0xb675928f9b526b02, 0x5a4a37026509dd9c, 0x735712faba3ebe0b, 0xd39c413c99d2ca73}}, + {{0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d}, + {0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03}, + {0xb6704486a1fbd156, 0x82f22765896748eb, 0x7404f45bd8019d6a, 0xc9457d18dedffadb}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x16faa8fb532f7428, 0xdbd42ea046a4e272, 0x5337653b8b9ea480, 0x4065947223973f03}, + {0xf7c0a19c1a54a044, 0x4a1c5e2477bd9fbb, 0xa6e3ca115af22972, 0x1819bb953f2e9e0d}, + {0x498fbb795e042e84, 0x7d0dd89a7698b714, 0x8bfb0ba427fe6295, 0x36ba82e721200524}}, + {{0xd60ecbb74245ec41, 0xfd9be89e34348716, 0xc9240afee42284de, 0x4472f648d0531db4}, + {0xc8d69d0a57274ed5, 0x45ba803260804b17, 0xdf3cda102255dfac, 0x77d221232709b339}, + {0x498a6d7064ad94d8, 0xa5b5c8fd9af62263, 0x8ca8ed0545c141f4, 0x2c63bec3662d358c}}, + {{0x7fe60d8bea787955, 0xb9dc117eb5f401b7, 0x91c7c09a19355cce, 0x22692ef59442bedf}, + {0x9a518b3a8586f8bf, 0x9ee71af6cbb196f0, 0xaa0625e6a2385cf2, 0x1deb2176ddd7c8d1}, + {0x8563d19a2066cf6c, 0x401bfd8c4dcc7cd7, 0xd976a6becd0d8f62, 0x67cfd773a278b05e}}, + {{0x8dec31faef3ee475, 0x99dbff8a9e22fd92, 0x512d11594e26cab1, 0x0cde561eec4310b9}, + {0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, 0xaa074dddf21d33d3, 0x185cba721bcb9dee}, + {0x93869da3f4e3cb41, 0xbf0392f540f7977e, 0x026204fcd0463b83, 0x3ec91a769eec6eed}}, + {{0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, 0xba002ed8c1eaf988, 0x13fedb3e11f33cfc}, + {0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, 0xf745bcc8c5f8eaa6, 0x7a5fa8794a94e896}, + {0x52958faa13cd67a1, 0x965ee0818bdbb517, 0x16e58daa2e8845b3, 0x357d397d5499da8f}}, + {{0x1ebfa05fb0bace6c, 0xc934620c1caf9a1e, 0xcc771cc41d82b61a, 0x2d94a16aa5f74fec}, + {0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1}, + {0x6f58cd5d55aff958, 0xba3eaa5c75567721, 0x75c123999165227d, 0x69be1343c2f2b35e}}, + {{0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696}, + {0x82bbbdac684b8de3, 0xa2f4c7d03fca0718, 0x337f92fbe096aaa8, 0x200d4d8c63587376}, + {0x208aed4b4893b32b, 0x3efbf23ebe59b964, 0xd762deb0dba5e507, 0x69607bd681bd9d94}}, + {{0xf6be021068de1ce1, 0xe8d518e70edcbc1f, 0xe3effdd01b5505a5, 0x35f63353d3ec3fd0}, + {0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, 0xe5ba8ff53a7852a7, 0x28bc77a5838ece00}, + {0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524}}, + {{0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}, + {0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}, + {0x64a170c0e25dd113, 0xecf0e28893fe32ec, 0xdeb370305d676047, 0x925508dcc664622a}}, + {{0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}, + {0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}, + {0x5c2f5f0ee96a6fb1, 0xfdc4949345814276, 0x840ea5c1d987ccf8, 0xa9dfcef344271318}}, + {{0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}, + {0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}, + {0x47195b2bff5daf3f, 0x647e28fdf4377d4b, 0xa81833640e6a8a9e, 0xc522775a38329b9f}}, + {{0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}, + {0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}, + {0xc4b730de85877dce, 0x0895f54d7ed8c168, 0x56939a5873711284, 0x8bee59fab075bcc0}}, + {{0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}, + {0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}, + {0x7db222899721150a, 0x379bbadfb497a2dc, 0x4aeb3032a276299a, 0xb8c7d658b08a2ac8}}, + {{0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}, + {0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}, + {0x5b77a63be48093a8, 0xf0d29f430bc7cd67, 0xe7ea56d6364e2e26, 0xb83c78e444e8aa3b}}, + {{0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}, + {0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}, + {0xb23dd07e74b9a2e2, 0x8e5f0ca5eb7f1007, 0x51174052fb3829a8, 0xcaa44ed54d9e890b}}, + {{0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}, + {0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}, + {0x842af71c6eee5e17, 0xd4d46f2b7f6f8b76, 0x182d513d518d02e6, 0xf120b6c37a49fd59}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x239e9624089c0a2e, 0xc748c4c03afe4738, 0x17dbed2a764fa12a, 0x639b93f0321c8582}, + {0xc08f788f3f78d289, 0xfe30a72ca1404d9f, 0xf2778bfccf65cc9d, 0x7ee498165acb2021}, + {0x7bd508e39111a1c3, 0x2b2b90d480907489, 0xe7d2aec2ae72fd19, 0x0edf493c85b602a6}}, + {{0xaecc8158599b5a68, 0xea574f0febade20e, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4}, + {0x6767c4d284764113, 0xa090403ff7f5f835, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369}, + {0x4dc22f818b465cf8, 0x71a0f35a1480eff8, 0xaee8bfad04c7d657, 0x355bb12ab26176f4}}, + {{0xa71e64cc7493bbf4, 0xe5bd84d9eca3b0c3, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312}, + {0xa301dac75a8c7318, 0xed90039db3ceaa11, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e}, + {0xa48859c41b7f6c32, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4}}, + {{0x5144539771ec4f48, 0xf805b17dc98c5d6e, 0xf762c11a47c3c66b, 0x00b89b85764699dc}, + {0xfbe65d50c85066b0, 0x62ecc4b0b3a299b0, 0xe53754ea441ae8e0, 0x08fea02ce8d48d5f}, + {0x824ddd7668deead0, 0xc86445204b685d23, 0xb514cfcd5d89d665, 0x473829a74f75d537}}, + {{0x82d2da754679c418, 0xe63bd7d8b2618df0, 0x355eef24ac47eb0a, 0x2078684c4833c6b4}, + {0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390}, + {0x3b48cf217a78820c, 0xf76a0ab281273e97, 0xa96c65a78c8eed7b, 0x7411a6054f8a433f}}, + {{0x4d659d32b99dc86d, 0x044cdc75603af115, 0xb34c712cdcc2e488, 0x7c136574fb8134ff}, + {0x579ae53d18b175b4, 0x68713159f392a102, 0x8455ecba1eef35f5, 0x1ec9a872458c398f}, + {0xb8e6a4d400a2509b, 0x9b81d7020bc882b4, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460}}, + {{0xab895770b635dcf2, 0x02dfef6cf66c1fbc, 0x85530268beb6d187, 0x249929fccc879e74}, + {0x85c298d459393046, 0x8f7e35985ff659ec, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720}, + {0xa3d0a0f116959029, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7}}, + {{0x528993434934d643, 0xb9dbf806a51222f5, 0x8f6d878fc3f41c22, 0x37676a2a4d9d9730}, + {0x6646b5f477e285d6, 0x40e8ff676c8f6193, 0xa6ec7311abb594dd, 0x7ec846f3658cec4d}, + {0x9b5e8f3f1da22ec7, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5}}, + {{0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130}, + {0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3}, + {0x6da4a10f98f3af5e, 0x7e6437bd46c3cc40, 0xef86d1658f22ffc0, 0xa652b48591d7238b}}, + {{0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9}, + {0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9}, + {0x8f7c99eeeb0ee6f0, 0xd4c847846bcb6352, 0x8d8c0ae34b1660bf, 0x875d56a7dc28a967}}, + {{0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831}, + {0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006}, + {0xbf5c5ee1386ef50e, 0x6fec20070e92d851, 0xe568df27544e6a2b, 0xe44601bad1567b9c}}, + {{0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de}, + {0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028}, + {0xcd68bb7c63f7cbe7, 0x9019da802d543b7b, 0xacd82e7eb4ca77e8, 0x9a8eda7a76c01643}}, + {{0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04}, + {0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9}, + {0xff0a9a5606cd97fc, 0x313028723f2a7175, 0x5dea1d230ce71d71, 0xba66116e649cccad}}, + {{0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b}, + {0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87}, + {0x2979c145c8461c3b, 0xefa43e968dc4a5dc, 0xefb09ba659a3f89d, 0xa986aed6a4b2c72b}}, + {{0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8}, + {0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282}, + {0x0e84b7ca9798cdd5, 0xc7821517c3552693, 0x9e4b8e02a9001c79, 0xce8bee6a48ba5a66}}, + {{0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6}, + {0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e}, + {0x584368f9af462161, 0xc2ed58043cfe4a64, 0xfd9ad1972c951c73, 0x8628c67ca59e6623}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x591e4a5610628564, 0x2a4bb87ca8b4df34, 0xde2a2572e7a38e43, 0x3cbdabd9fee5046e}, + {0x81aebbdd2cd13070, 0x962e4325f85a0e9e, 0xde9391aacadffecb, 0x53177fda52c230e6}, + {0xa7bc970650b9de79, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc}}, + {{0xd9354df64131c1bd, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282}, + {0x21c9d9920d591737, 0x9bea41d2e9b46cd6, 0xe20e84200d89bfca, 0x79d99f946eae5ff8}, + {0xf17b483568673205, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599}}, + {{0xe8d10190b77a360b, 0x99b983209995e702, 0xbd4fdff8fa0247aa, 0x2772e344e0d36a87}, + {0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b}, + {0xd6863eba37b9e39f, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4}}, + {{0x535fd60613037524, 0xe210adf6b0fbc26a, 0xac8d0a9b23e990ae, 0x47204d08d72fdbf9}, + {0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04}, + {0x00f565a9f93267de, 0xcecfd78dc0d58e8a, 0xa215e2dcf318e28e, 0x4599ee919b633352}}, + {{0xd3c220ca70e0e76b, 0xb12bea58ea9f3094, 0x294ddec8c3271282, 0x0c3539e1a1d1d028}, + {0xac746d6b861ae579, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de}, + {0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc}}, + {{0x9c102fb732a61161, 0xe48e10dd34d520a8, 0x365c63546f9a9176, 0x32f6fe4c046f6006}, + {0x81c29f1bd708ee3f, 0xddcb5a05ae6407d0, 0x97aec1d7d2a3eba7, 0x1590521a91d50831}, + {0x40a3a11ec7910acc, 0x9013dff8f16d27ae, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463}}, + {{0xe9d1d950b3d54f9e, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9}, + {0xcf5e6c95cc36747c, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9}, + {0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698}}, + {{0xa2b072e95c8c2ace, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3}, + {0xb4f23c425ef83207, 0xabf894d3c9a934b5, 0xd0708c1339fd87f7, 0x1876789117166130}, + {0x925b5ef0670c507c, 0x819bc842b93c33bf, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74}}, + {{0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}, + {0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}, + {0x6ead032f6015825e, 0xb57e936b4f6ca309, 0xda716555b8d7a3bf, 0xef476359fbd76c48}}, + {{0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}, + {0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}, + {0x9f5b3e662cf8caf0, 0xbf3f7a49cee9a329, 0x1dccc1dc08a67d6a, 0xb0d052fee946ff2e}}, + {{0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}, + {0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}, + {0x323a6e11797e290e, 0x31fdef63127a58ac, 0x128b7a3ea77f777c, 0xee890391d2019a1b}}, + {{0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}, + {0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}, + {0x61c3e8bc0d4373c6, 0xd125d9034a7a93c4, 0x3347d0f197580468, 0xbe985b1943a6cdbb}}, + {{0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}, + {0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}, + {0xf3c0f6bc647fa5a5, 0x17b174c89dbd5403, 0x96ebe80ca3dd6cb9, 0xf1646344ebb10f13}}, + {{0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}, + {0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}, + {0xcddffdbaf6395752, 0x2d1fc9ecb4aa768c, 0x7c1dc9dcc3ccd760, 0x8fe0da44f3513e70}}, + {{0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}, + {0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}, + {0xe56b39772153dd10, 0x46f991084451e007, 0x775273c772a6a7f0, 0xa70d65401860d357}}, + {{0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}, + {0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}, + {0x8767eb2d952362dc, 0xc3e454c074b722f4, 0x25f01e00068639f5, 0xbb9721d283d2296c}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x5f3a7562eb3dbe47, 0xf7ea38548ebda0b8, 0x00c3e53145747299, 0x1304e9e71627d551}, + {0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa}, + {0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, 0xda0fe1fff979c60a, 0x4468de2d7c2dd693}}, + {{0x51bb355e9419469e, 0x33e6dc4c23ddc754, 0x93a5b6d6447f9962, 0x6cce7c6ffb44bd63}, + {0x4b9ad8c6f86307ce, 0x21113531435d0c28, 0xd4a866c5657a772c, 0x5da6427e63247352}, + {0x1a94c688deac22ca, 0xb9066ef7bbae1ff8, 0x88ad8c388d59580f, 0x58f29abfe79f2ca8}}, + {{0xe90ecfab8de73e68, 0x54036f9f377e76a5, 0xf0495b0bbe015982, 0x577629c4a7f41e36}, + {0x4b5a64bf710ecdf6, 0xb14ce538462c293c, 0x3643d056d50b3ab9, 0x6af93724185b4870}, + {0x3220024509c6a888, 0xd2e036134b558973, 0x83e236233c33289f, 0x701f25bb0caec18f}}, + {{0xc3a8b0f8e4616ced, 0xf700660e9e25a87d, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9}, + {0x9d18f6d97cbec113, 0x844a06e674bfdbe4, 0x20f5b522ac4e60d6, 0x720a5bc050955e51}, + {0x0c3f09439b805a35, 0xe84e8b376242abfc, 0x691417f35c229346, 0x0e9b9cbb144ef0ec}}, + {{0xfbbad48ffb5720ad, 0xee81916bdbf90d0e, 0xd4813152635543bf, 0x221104eb3f337bd8}, + {0x8dee9bd55db1beee, 0xc9c3ab370a723fb9, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde}, + {0x9e3c1743f2bc8c14, 0x2eda26fcb5856c3b, 0xccb82f0e68a7fb97, 0x4167a4e6bc593244}}, + {{0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a}, + {0xc2be2665f8ce8fee, 0xe967ff14e880d62c, 0xf12e6e7e2f364eee, 0x34b33370cb7ed2f6}, + {0xcdc591ee8681d6cc, 0xce02109ced85a753, 0xed7485c158808883, 0x1176fc6e2dfe65e4}}, + {{0xb4af6cd05b9c619b, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34}, + {0xdb90e28949770eb8, 0x98fbcc2aacf440a3, 0x21354ffeded7879b, 0x1f6a3e54f26906b6}, + {0x60a4c199d30734ea, 0x40c085b631165cd6, 0xe2333e23f7598295, 0x4f2fad0116b900d1}}, + {{0x44beb24194ae4e54, 0x5f541c511857ef6c, 0xa61e6b2d368d0498, 0x445484a4972ef7ab}, + {0x962cd91db73bb638, 0xe60577aafc129c08, 0x6f619b39f3b61689, 0x3451995f2944ee81}, + {0x9152fcd09fea7d7c, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7}}, + {{0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0}, + {0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9}, + {0x8d07593c414341f2, 0xb0f035b523c57176, 0x90562b1738402085, 0xf230d298649db148}}, + {{0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda}, + {0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281}, + {0xc1b2069aa77b1d30, 0x429d0424242b9a5a, 0x28a69355f2161adb, 0x917fbd334d4e4c28}}, + {{0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8}, + {0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82}, + {0x92592170f1c66841, 0x8529e55bbf025e87, 0x4cd327efa1ca9c22, 0xea094151d51cbf51}}, + {{0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e}, + {0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a}, + {0x942b839a670411cb, 0x61b8cc1d54aa41d2, 0xef6c09dbed89ef3a, 0xb1fa1d952f5e155b}}, + {{0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861}, + {0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211}, + {0x60de6fc0fefe973c, 0x2886202c4079effa, 0x5edd11a0c214f0e4, 0xaef207b4b7a5ff2b}}, + {{0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840}, + {0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908}, + {0xc75f4ed0e230f89d, 0xb49f575c48095d89, 0x012a53da2cbfb065, 0x8d17d2a1aafa3dd6}}, + {{0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f}, + {0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e}, + {0xb7caf3f7f975b678, 0x90022facaef6d365, 0xe850b0b550903722, 0xb4faac4ac3245a74}}, + {{0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef}, + {0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75}, + {0x3bb86fe529e41481, 0x99e0e6431a2377f5, 0xdb97ab7d483597d8, 0xd6c38873101f80d9}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x9b2a426e3b646025, 0x32127190385ce4cf, 0xa25cffc2dd6dea45, 0x06409010bea8de75}, + {0xd67cded679d34aa0, 0xcc0b9ec0cc4db39f, 0xa535a456e35d190f, 0x2e05d9eaf61f6fef}, + {0xc447901ad61beb59, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26}}, + {{0x86809e7007069096, 0xaad75b15e4e50189, 0x07f35715a21a0147, 0x0487f3f112815d5e}, + {0x16c795d6a11ff200, 0xcb70d0e2b15815c9, 0x89f293209b5395b5, 0x50b8c2d031e47b4f}, + {0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b}}, + {{0x9c65fcbe1b32ff79, 0xeb75ea9f03b50f9b, 0xfced2a6c6c07e606, 0x35106cd551717908}, + {0xbf05211b27c152d4, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840}, + {0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, 0xfed5ac25d3404f9a, 0x72e82d5e5505c229}}, + {{0x6b0b697ff0d844c8, 0xbb12f85cd979cb49, 0xd2a541c6c1da0f1f, 0x7b7c242958ce7211}, + {0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861}, + {0x9f21903f0101689e, 0xd779dfd3bf861005, 0xa122ee5f3deb0f1b, 0x510df84b485a00d4}}, + {{0xa54133bb9277a1fa, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a}, + {0x24b3c887c70ac15e, 0xb0f3a557fb81b732, 0x9b2cde2fe578cc1b, 0x4cf7ed0703b54f8e}, + {0x6bd47c6598fbee0f, 0x9e4733e2ab55be2d, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4}}, + {{0xda9b6b624b531f20, 0x429a760e77509abb, 0xdbe9f522e823cb80, 0x618f1856880c8f82}, + {0x1833c773e18fe6c0, 0xe3c4711ad3c87265, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8}, + {0x6da6de8f0e399799, 0x7ad61aa440fda178, 0xb32cd8105e3563dd, 0x15f6beae2ae340ae}}, + {{0x862bcb0c31ec3a62, 0x810e2b451138f3c2, 0x788ec4b839dac2a4, 0x28f76867ae2a9281}, + {0xba9a0f7b9245e215, 0xf368612dd98c0dbb, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda}, + {0x3e4df9655884e2aa, 0xbd62fbdbdbd465a5, 0xd7596caa0de9e524, 0x6e8042ccb2b1b3d7}}, + {{0xf10d3c29ce28ca6e, 0xbad34540fcb6093d, 0xe7426ed7a2ea2d3f, 0x08af9d4e4ff298b9}, + {0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0}, + {0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7}}, + {{0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}, + {0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}, + {0xc0065479f53b8c26, 0x0f6ee211feec1bca, 0xb518af9f14393b50, 0xc079ed699378fff2}}, + {{0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}, + {0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}, + {0xcd4f3adb1eb22b58, 0x124caeabe5d45b49, 0x5c2e9fb7d7d4a50c, 0xb03f862d858cc914}}, + {{0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}, + {0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}, + {0xb2bc414dd5ef9d01, 0x8f9a048ac7ce23e9, 0xe7f2b58421d69728, 0xfa4cd3d4e34e986f}}, + {{0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}, + {0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}, + {0x218f2b0b495aa10f, 0xb7fead80a27a2466, 0x24363bbf2c11657e, 0x94d56f50e59fd612}}, + {{0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}, + {0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}, + {0xea519471ceb76272, 0x557ae35463d40f78, 0x3658a5680fb105fa, 0xff94adf894c007cd}}, + {{0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}, + {0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}, + {0xb7dbe23841f346a1, 0xcd0e64b2749ccf7f, 0x2c2036f2fdd76cf7, 0xfa1ed697b9d8e6ba}}, + {{0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}, + {0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}, + {0xdb29f7cd716afa30, 0xb8b73e2ef3ebdf11, 0x38001ba3f904da5d, 0xff458c61d51c6a19}}, + {{0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}, + {0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}, + {0xd80d50e7f8c0c170, 0x02c01ae628adef96, 0xdd1c48d3c359ffdd, 0x8ddeb09c339a3958}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e}, + {0x753941be5a45f06e, 0xd07caeed6d9c5f65, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9}, + {0x27f2af18073f3e6a, 0xfd3fe519d7521069, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7}}, + {{0xb4e37f405307a693, 0xaba714d72f336795, 0xd6fbd0a773761099, 0x5fdf48c58171cbc9}, + {0x1d9db7b9f43b29c9, 0xd605824a4f518f75, 0xf2c072bd312f9dc4, 0x1f24ac855a1545b0}, + {0x24d608328e9505aa, 0x4748c1d10c1420ee, 0xc7ffe45c06fb25a2, 0x00ba739e2ae395e6}}, + {{0x592e98de5c8790d6, 0xe5bfb7d345c2a2df, 0x115a3b60f9b49922, 0x03283a3e67ad78f3}, + {0xae4426f5ea88bb26, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226}, + {0x48241dc7be0cb939, 0x32f19b4d8b633080, 0xd3dfc90d02289308, 0x05e1296846271945}}, + {{0xba82eeb32d9c495a, 0xceefc8fcf12bb97c, 0xb02dabae93b5d1e0, 0x39c00c9c13698d9b}, + {0xadbfbbc8242c4550, 0xbcc80cecd03081d9, 0x843566a6f5c8df92, 0x78cf25d38258ce4c}, + {0x15ae6b8e31489d68, 0xaa851cab9c2bf087, 0xc9a75a97f04efa05, 0x006b52076b3ff832}}, + {{0x29e0cfe19d95781c, 0xb681df18966310e2, 0x57df39d370516b39, 0x4d57e3443bc76122}, + {0xf5cb7e16b9ce082d, 0x3407f14c417abc29, 0xd4b36bce2bf4a7ab, 0x7de2e9561a9f75ce}, + {0xde70d4f4b6a55ecb, 0x4801527f5d85db99, 0xdbc9c440d3ee9a81, 0x6b2a90af1a6029ed}}, + {{0x6923f4fc9ae61e97, 0x5735281de03f5fd1, 0xa764ae43e6edd12d, 0x5fd8f4e9d12d3e4a}, + {0x77ebf3245bb2d80a, 0xd8301b472fb9079b, 0xc647e6f24cee7333, 0x465812c8276c2109}, + {0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790}}, + {{0xc8c05eccd24da8fd, 0xa1cf1aac05dfef83, 0xdbbeeff27df9cd61, 0x3b5556a37b471e99}, + {0xf7fca42c7ad58195, 0x3214286e4333f3cc, 0xb6c29d0d340b979d, 0x31771a48567307e1}, + {0x32b0c524e14dd482, 0xedb351541a2ba4b6, 0xa3d16048282b5af3, 0x4fc079d27a7336eb}}, + {{0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, 0xffffc09c7880e453, 0x124567cecaf98e92}, + {0xdc348b440c86c50d, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08}, + {0x3ff9ab860ac473b4, 0xf0911dee0113e435, 0x4ae75060ebc6c4af, 0x3f8612966c87000d}}, + {{0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8}, + {0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b}, + {0x16e804619ef6acd9, 0x3efd206bfd5f6d07, 0x40f61d0a0599e6f4, 0x97eef6411f2301c8}}, + {{0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569}, + {0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59}, + {0xfae21fdf21634143, 0x05f803a94af4308b, 0xc8731360f0ee209a, 0xc97ac396546921b2}}, + {{0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212}, + {0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c}, + {0xc013216dc5135641, 0x4255a4ff9d173ed0, 0x9846620369677521, 0xc0ad3fd7ad99efc9}}, + {{0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11}, + {0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e}, + {0xda4a571af1083b4b, 0x149fcbee90d31acd, 0x3a18ae8c1ac21ac8, 0x8cee605f73ed44fc}}, + {{0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16}, + {0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2}, + {0x3b7454eade5628a7, 0x593d151529e544da, 0x9da393e33934bcfa, 0x8036f0156c14c598}}, + {{0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3}, + {0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb}, + {0xf187d58548c895f2, 0xfb5fa2878a4e71d3, 0xd6adadd91433151e, 0xf286b07c7c1457df}}, + {{0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8}, + {0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5}, + {0x409ebdc2dac034c3, 0xf77fc31505c614eb, 0x0e79fd2067ae3850, 0xfbff0c5fb61cbeb4}}, + {{0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed}, + {0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da}, + {0x606810d17fe525e1, 0x7c9682ab865025c5, 0x16f94c0042a694af, 0xfd98d4c822c0471f}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x0c9c5303f7957be4, 0xa3c31a20e085c145, 0xb0721d71d0850050, 0x0aba390eab0bf2da}, + {0x529fdffe638c7bf3, 0xdf2b9e60388b4995, 0xe027b34f1bad0249, 0x7bc92fc9b9fa74ed}, + {0x9f97ef2e801ad9f9, 0x83697d5479afda3a, 0xe906b3ffbd596b50, 0x02672b37dd3fb8e0}}, + {{0x48b2ca8b260885e4, 0xa4286bec82b34c1c, 0x937e1a2617f58f74, 0x741d1fcbab2ca2a5}, + {0xee9ba729398ca7f5, 0xeb9ca6257a4849db, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8}, + {0xbf61423d253fcb17, 0x08803ceafa39eb14, 0xf18602df9851c7af, 0x0400f3a049e3414b}}, + {{0xabce0476ba61c55b, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb}, + {0x2efba412a06e7b06, 0x146785452c8d2560, 0xdf9713ebd67a91c7, 0x32830ac7157eadf3}, + {0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820}}, + {{0xff35f5cb9e1516f4, 0xee805bcf648aae45, 0xf0d73c2bb93a9ef3, 0x097b0bf22092a6c2}, + {0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16}, + {0xc48bab1521a9d733, 0xa6c2eaead61abb25, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67}}, + {{0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e}, + {0xc527deb59c7cb23d, 0x955391695328404e, 0xd64392817ccf2c7a, 0x6ce97dabf7d8fa11}, + {0x25b5a8e50ef7c48f, 0xeb6034116f2ce532, 0xc5e75173e53de537, 0x73119fa08c12bb03}}, + {{0xed30129453f1a4cb, 0xbce621c9c8f53787, 0xfacb2b1338bee7b9, 0x3025798a9ea8428c}, + {0x7845b94d21f4774d, 0xbf62f16c7897b727, 0x671857c03c56522b, 0x3cd6a85295621212}, + {0x3fecde923aeca999, 0xbdaa5b0062e8c12f, 0x67b99dfc96988ade, 0x3f52c02852661036}}, + {{0xffeaa48e2a1351c6, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59}, + {0x9258bf99eec416c6, 0xac8a5017a9d2f671, 0x629549ab16dea4ab, 0x05d0e85c99091569}, + {0x051de020de9cbe97, 0xfa07fc56b50bcf74, 0x378cec9f0f11df65, 0x36853c69ab96de4d}}, + {{0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b}, + {0x4433c0b0fac5e7be, 0x724bae854c08dcbe, 0xf1f24cc446978f9b, 0x4a0aff6d62825fc8}, + {0xe917fb9e61095301, 0xc102df9402a092f8, 0xbf09e2f5fa66190b, 0x681109bee0dcfe37}}, + {{0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}, + {0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}, + {0x57901aab98263559, 0xc674838ad4d673c8, 0x2592f76d1c539dc4, 0xb51433bab8162673}}, + {{0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}, + {0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}, + {0x3d91134a7c96cca5, 0x2a57ec209c4a0102, 0x5d6c55655b4dda8c, 0x8e29d422b9a1e395}}, + {{0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}, + {0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}, + {0x9a85257a566f8380, 0xe5f1574a6e46f09d, 0x72f1e20420cb4b16, 0xd6747317510da00c}}, + {{0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}, + {0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}, + {0x4904d9ea33f560b4, 0xc5b0f1d44772331a, 0xecfeb674cc9658fa, 0xd06708eda7a6d22e}}, + {{0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}, + {0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}, + {0x795f085f9b8787fb, 0x443b9bd8f19f8360, 0x54e815da0e04ee36, 0xb3048284cfb47884}}, + {{0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}, + {0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}, + {0x7e612bcc53d26f72, 0xd77c5486a0367adc, 0x10ba8d7faa6c14c2, 0xfdf3ad958a70c934}}, + {{0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}, + {0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}, + {0xff3988662cc8a68b, 0xa1c3aebf4dc55b84, 0xbbe7d7ab1ca00c6a, 0xe4b06dcebca65fed}}, + {{0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}, + {0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}, + {0xf354d32aa9781029, 0xae7f2e9ddb850e84, 0x7a3ea5cbb0a5db98, 0xbfbe6bc26245cf96}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d}, + {0x9c18fcfa36048d13, 0x29159db373899ddd, 0xdc9f350b9f92d0aa, 0x26f57eee878a19d4}, + {0x0cab2cd55687efb1, 0x5180d162247af17b, 0x85c15a344f5a2467, 0x4041943d9dba3069}}, + {{0xc3c0eeba43ebcc96, 0x8d749c9c26ea9caf, 0xd9fa95ee1c77ccc6, 0x1420a1d97684340f}, + {0x4b217743a26caadd, 0x47a6b424648ab7ce, 0xcb1d4f7a03fbc9e3, 0x12d931429800d019}, + {0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012}}, + {{0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae}, + {0x33cf3030a49866b1, 0x251f73d2215f4859, 0xab82aa4051def4f6, 0x5ff191d56f9a23f6}, + {0x819ed433ac2d9068, 0x2883ab795fc98523, 0xef4572805593eb3d, 0x020c526a758f36cb}}, + {{0x779834f89ed8dbbc, 0xc8f2aaf9dc7ca46c, 0xa9524cdca3e1b074, 0x02aacc4615313877}, + {0xe931ef59f042cc89, 0x2c589c9d8e124bb6, 0xadc8e18aaec75997, 0x452cfe0a5602c50c}, + {0x86a0f7a0647877df, 0xbbc464270e607c9f, 0xab17ea25f1fb11c9, 0x4cfb7d7b304b877b}}, + {{0x72b43d6cb89b75fe, 0x54c694d99c6adc80, 0xb8c3aa373ee34c9f, 0x14b4622b39075364}, + {0xe28699c29789ef12, 0x2b6ecd71df57190d, 0xc343c857ecc970d0, 0x5b1d4cbc434d3ac5}, + {0xb6fb2615cc0a9f26, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1}}, + {{0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, 0x9a2acc2182300f67, 0x3a6ae249d806aaf9}, + {0x2e12ae444f54a701, 0xfcfe3ef0a9cbd7de, 0xcebf890d75835de0, 0x1d8062e9e7614554}, + {0x657ada85a9907c5a, 0x1a0ea8b591b90f62, 0x8d0e1dfbdf34b4e9, 0x298b8ce8aef25ff3}}, + {{0x2a927953eff70cb2, 0x4b89c92a79157076, 0x9418457a30a7cf6a, 0x34b8a8404d5ce485}, + {0x837a72ea0a2165de, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc}, + {0xc26eecb583693335, 0xd5a813df63b5fefd, 0xa293aa9aa4b22573, 0x71d62bdd465e1c6a}}, + {{0x6533cc28d378df80, 0xf6db43790a0fa4b4, 0xe3645ff9f701da5a, 0x74d5f317f3172ba4}, + {0xcd2db5dab1f75ef5, 0xd77f95cf16b065f5, 0x14571fea3f49f085, 0x1c333621262b2b3d}, + {0xa86fe55467d9ca81, 0x398b7c752b298c37, 0xda6d0892e3ac623b, 0x4aebcc4547e9d98c}}, + {{0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5}, + {0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5}, + {0xb3168241a2146b10, 0xc72f5bc7738f63b7, 0x3bc1312b5e962f68, 0xf5edb600081a783c}}, + {{0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59}, + {0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429}, + {0x72f34773e4c82ff9, 0xfa495a5cfac7e70c, 0x0d1643fb487826a6, 0x94145edb6522809b}}, + {{0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7}, + {0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512}, + {0xbf6c522363f83dd5, 0x3a9a41ea0acd3c81, 0x9c241302ea7cbfd5, 0x9e8dd4b510d1fcd1}}, + {{0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996}, + {0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac}, + {0x2d826504db668cb7, 0xe4481f81090fe2d1, 0xd458b8d20ad13380, 0xfcfe64b09b906237}}, + {{0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68}, + {0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c}, + {0x862a39d1503c6faf, 0x88c5dead7617f8d7, 0x3c7519bf1efedf46, 0xf651dc8e84d4e592}}, + {{0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed}, + {0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d}, + {0xe81b63e8336b809d, 0x33391259553e2d84, 0x209f6d314f0f71a9, 0xb6f64c1dd3983c94}}, + {{0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0}, + {0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019}, + {0x0c6e3ae27531af34, 0xcebd2f4651d2d6b7, 0x24b2a5e580db357f, 0xde514574a6daf157}}, + {{0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b}, + {0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c}, + {0x3e04be88fe7466ca, 0x5915df2393f01ebf, 0x299e0c18bcab3900, 0xa1348d190e5cbf85}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x53175a7205d21a77, 0xb0c04422d3b934d4, 0xadd9f24bdd5deadc, 0x074f46e69f10ff8c}, + {0x0de9b204a059a445, 0xe15cb4aa4b17ad0f, 0xe1bbec521f79c557, 0x2633f1b9d071081b}, + {0xc1fb4177018b9910, 0xa6ea20dc6c0fe140, 0xd661f3e74354c6ff, 0x5ecb72e6f1a3407a}}, + {{0xa515a31b2259fb4e, 0x0960f3972bcac52f, 0xedb52fec8d3454cb, 0x382e2720c476c019}, + {0xfeeae106e8e86997, 0x9863337f98d09383, 0x9470480eaa06ebef, 0x038b6898d4c5c2d0}, + {0xf391c51d8ace50a6, 0x3142d0b9ae2d2948, 0xdb4d5a1a7f24ca80, 0x21aeba8b59250ea8}}, + {{0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d}, + {0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed}, + {0x17e49c17cc947f3d, 0xccc6eda6aac1d27b, 0xdf6092ceb0f08e56, 0x4909b3e22c67c36b}}, + {{0x9c9c85ea63fe2e89, 0xbe1baf910e9412ec, 0x8f7baa8a86fbfe7b, 0x0fb17f9fef968b6c}, + {0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68}, + {0x79d5c62eafc3902b, 0x773a215289e80728, 0xc38ae640e10120b9, 0x09ae23717b2b1a6d}}, + {{0xbb6a192a4e4d083c, 0x34ace0630029e192, 0x98245a59aafabaeb, 0x6d9c8a9ada97faac}, + {0x10ab8fa1ad32b1d0, 0xe9aced1be2778b24, 0xa8856bc0373de90f, 0x66f35ddddda53996}, + {0xd27d9afb24997323, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8}}, + {{0x04a186b5565345cd, 0xeee76610bcc4116a, 0x689c73b478fb2a45, 0x387dcbff65697512}, + {0xaf09b214e6b3dc6b, 0x3f7573b5ad7d2f65, 0xd019d988100a23b0, 0x392b63a58b5c35f7}, + {0x4093addc9c07c205, 0xc565be15f532c37e, 0x63dbecfd1583402a, 0x61722b4aef2e032e}}, + {{0x0012aafeecbd47af, 0x55a266fb1cd46309, 0xf203eb680967c72c, 0x39633944ca3c1429}, + {0xd6b07a5581cb0e3c, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59}, + {0x8d0cb88c1b37cfe1, 0x05b6a5a3053818f3, 0xf2e9bc04b787d959, 0x6beba1249add7f64}}, + {{0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5}, + {0x5c3cecb943f5a53b, 0x9cc9a61d06c08df2, 0xcfba639a85895447, 0x5a845ae80df09fd5}, + {0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, 0xc43eced4a169d097, 0x0a1249fff7e587c3}}, + {{0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}, + {0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}, + {0xed92d86e86eaba83, 0x2a1b70a30387c5f5, 0xc942491720e86453, 0xd10ae877a457d7a6}}, + {{0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}, + {0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}, + {0xc29903c11df69c77, 0x7e29d3809e4a3494, 0xf041fbbdecbbc4e5, 0xfd5b13e6de1e5e24}}, + {{0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}, + {0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}, + {0x3c7c57de66e58c1d, 0x54d843fe20cdf385, 0x3ec2cce47b888f9c, 0xacf2b57d14f87566}}, + {{0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}, + {0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}, + {0x0d91cd589c11e5ac, 0x516e1b482da00215, 0x43c42cc42e80b296, 0xb6e499213f230095}}, + {{0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}, + {0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}, + {0xd512b9f50e352dd8, 0xb9cfacfa5b73117c, 0x6ede88bab60ee5a0, 0xdb31f6cfabd35b9c}}, + {{0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}, + {0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}, + {0x436fe63f51465fac, 0xaa38eef2e9fcb351, 0xf1920afe9a66cd13, 0xc435f2d76a35a201}}, + {{0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}, + {0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}, + {0x0819bbc6a2c27fcf, 0x6a572aaa36fe1209, 0x973287cfa6d39cc6, 0xcf2f0212d1aecf81}}, + {{0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}, + {0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}, + {0xd4aff0e101a78cfb, 0xa729a7d12bc6e73e, 0x1912d8713698c51f, 0xf91e32ec4e615ce6}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x12f0071b276d01c9, 0xe7b8bac586c48c70, 0x5308129b71d6fba9, 0x5d88fbf95a3db792}, + {0x0b408d9e7354b610, 0x806b32535ba85b6e, 0xdbe63a034a58a207, 0x173bd9ddc9a1df2c}, + {0x2b500f1efe5872df, 0x58d6582ed43918c1, 0xe6ed278ec9673ae0, 0x06e1cd13b19ea319}}, + {{0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266}, + {0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13}, + {0xf7e644395d3d800b, 0x95a8d555c901edf6, 0x68cd7830592c6339, 0x30d0fded2e51307e}}, + {{0xe0594d1af21233b3, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868}, + {0x9cb4971e68b84750, 0xa09572296664bbcf, 0x5c8de72672fa412b, 0x4615084351c589d9}, + {0xbc9019c0aeb9a02e, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe}}, + {{0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, 0x98183da2130fb545, 0x5631deddae8f13cd}, + {0x9c688eb69ecc01bf, 0xf0bc83ada644896f, 0xca2d955f5f7a9fe2, 0x4ea8b4038df28241}, + {0x2aed460af1cad202, 0x46305305a48cee83, 0x9121774549f11a5f, 0x24ce0930542ca463}}, + {{0x1fe890f5fd06c106, 0xb5c468355d8810f2, 0x827808fe6e8caf3e, 0x41d4e3c28a06d74b}, + {0x3fcfa155fdf30b85, 0xd2f7168e36372ea4, 0xb2e064de6492f844, 0x549928a7324f4280}, + {0xf26e32a763ee1a2e, 0xae91e4b7d25ffdea, 0xbc3bd33bd17f4d69, 0x491b66dec0dcff6a}}, + {{0x98f5b13dc7ea32a7, 0xe3d5f8cc7e16db98, 0xac0abf52cbf8d947, 0x08f338d0c85ee4ac}, + {0x75f04a8ed0da64a1, 0xed222caf67e2284b, 0x8234a3791f7b7ba4, 0x4cf6b8b0b7018b67}, + {0xc383a821991a73bd, 0xab27bc01df320c7a, 0xc13d331b84777063, 0x530d4a82eb078a99}}, + {{0x004c3630e1f94825, 0x7e2d78268cab535a, 0xc7482323cc84ff8b, 0x65ea753f101770b9}, + {0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b}, + {0x3d66fc3ee2096363, 0x81d62c7f61b5cb6b, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db}}, + {{0x5ce6259a3b24b8a2, 0xb8577acc45afa0b8, 0xcccbe6e88ba07037, 0x3d143c51127809bf}, + {0xf5c86162f1cf795f, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf}, + {0x126d279179154557, 0xd5e48f5cfc783a0a, 0x36bdb6e8df179bac, 0x2ef517885ba82859}}, + {{0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e}, + {0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5}, + {0xeb19abbd0fc6f91c, 0xb5fe62ab1c9d41d5, 0x97332013723dcf38, 0x830481c0509479e3}}, + {{0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0}, + {0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c}, + {0x44ac801fbb8f8efc, 0x3458bbbc922aa820, 0x2c4a5cb8c9ff2434, 0xb515441906002807}}, + {{0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438}, + {0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d}, + {0x40a95bce12fa4b52, 0x5acc199363b6a381, 0x179ad450780c9ae5, 0xfdbe7fffa62993cc}}, + {{0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401}, + {0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd}, + {0x3f48c139294ccf0d, 0x7b1bb7f8ecd0500e, 0x8cd48cad3b5a211e, 0xa283830e55832d2d}}, + {{0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d}, + {0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d}, + {0xb00a3253e14f78c3, 0x98174d6a6f0d1643, 0xbbf6c4a1dc850566, 0xf2beb41278f7474d}}, + {{0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3}, + {0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9}, + {0x9e50b6ed37107570, 0x1a705b01bc0491a1, 0x4a5033a2902bd830, 0x95ac6cd7e1e1ee14}}, + {{0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f}, + {0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3}, + {0x7114a2f8914aa2fa, 0xd03ac94055f26da5, 0x417e7cf023493917, 0xaa938fba7d8450ad}}, + {{0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52}, + {0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c}, + {0x47026c66172e613d, 0x6f7e6e3469dbdc00, 0x4d46b728b838bd5c, 0xc80ccdd92804bb3b}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x88bd438cd11e0d4a, 0x30cb610d43ccf308, 0xe09a0e3791937bcc, 0x4559135b25b1720c}, + {0x1ea436837c6da1e9, 0xf9c189af1fb9bdbe, 0x303001fcce5dd155, 0x28a7c99ebc57be52}, + {0xb8fd9399e8d19e9d, 0x908191cb962423ff, 0xb2b948d747c742a3, 0x37f33226d7fb44c4}}, + {{0x0dae8767b55f6e08, 0x4a43b3b35b203a02, 0xe3725a6e80af8c79, 0x0f7a7fd1705fa7a3}, + {0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f}, + {0x8eeb5d076eb55ce0, 0x2fc536bfaa0d925a, 0xbe81830fdcb6c6e8, 0x556c7045827baf52}}, + {{0x8e2b517302e9d8b7, 0xe3e52269248714e8, 0xbd4fbd774ca960b5, 0x6f4b4199c5ecada9}, + {0xb94b90022bf44406, 0xabd4237eff90b534, 0x7600a960faf86d3a, 0x2f45abdac2322ee3}, + {0x61af4912c8ef8a6a, 0xe58fa4fe43fb6e5e, 0xb5afcc5d6fd427cf, 0x6a5393281e1e11eb}}, + {{0xf3da5139a5d1ee89, 0x8145457cff936988, 0x3f622fed00e188c4, 0x0f513815db8b5a3d}, + {0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d}, + {0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2}}, + {{0xcfb68265fd0e75f6, 0xe45b3e28bb90e707, 0x7242a8de9ff92c7a, 0x685b3201933202dd}, + {0x81886a92294ac9e8, 0x23162b45d55547be, 0x94cfbc4403715983, 0x50eb8fdb134bc401}, + {0xc0b73ec6d6b330cd, 0x84e44807132faff1, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2}}, + {{0xaf3b46bf7a4aafa2, 0xb78705ec4d40d411, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d}, + {0x33d1013e9b73a562, 0x925cef5748ec26e1, 0xa7fce614dd468058, 0x78b0fad41e9aa438}, + {0xbf56a431ed05b488, 0xa533e66c9c495c7e, 0xe8652baf87f3651a, 0x0241800059d66c33}}, + {{0xceb077fea37a5be4, 0xdb642f02e5a5eeb7, 0xc2e6d0c5471270b8, 0x4771b65538e4529c}, + {0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, 0xace7cfbe857082f7, 0x4d2845aba2d9a1e0}, + {0xbb537fe0447070de, 0xcba744436dd557df, 0xd3b5a3473600dbcb, 0x4aeabbe6f9ffd7f8}}, + {{0x4630119e40d8f78c, 0xa01a9bc53c710e11, 0x486d2b258910dd79, 0x1e6c47b3db0324e5}, + {0x6a2134bcc4a9c8f2, 0xfbf8fd1c8ace2e37, 0x000ae3049911a0ba, 0x046e3a616bc89b9e}, + {0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c}}, + {{0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}, + {0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}, + {0x011c4add9f3a2665, 0xafcad10314be4f47, 0x77f753cf56099ac3, 0xcfd26d2dfac6dc92}}, + {{0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}, + {0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}, + {0x90f3f03acc91db3d, 0x8ba121e63cce3026, 0x0d2902fff61101e3, 0xed83ea740f05e141}}, + {{0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}, + {0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}, + {0xd771e668cc49f678, 0xdb038d4b27541ecc, 0xb7ee0812f66e2fc1, 0xc07e1c74708f2f8a}}, + {{0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}, + {0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}, + {0x105b757a221af240, 0xde65ddb1f0465db6, 0x05f6e0e226e10926, 0x94a2893415b944cb}}, + {{0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}, + {0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}, + {0xf80f2814fb17d67b, 0xef24e7dad0af0c82, 0x16ae565ce8e86728, 0x90a5658cdd535ae2}}, + {{0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}, + {0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}, + {0xd14c295ea482d6c1, 0x4f4b095f2ac57dca, 0x8ea931bc765ba2b8, 0xf8e582f531e7cb93}}, + {{0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}, + {0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}, + {0x3e20e73a56f81c01, 0xa84cc8e231b39ca6, 0x358fbacb4dfe44b6, 0x80867dc063cf22d1}}, + {{0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}, + {0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}, + {0x08e547bcf5df1ed9, 0x0c6c9a72db0f13b8, 0x308af657911d112e, 0x823bc1ca23d55c1e}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x4637974e8c58aedc, 0xb9ef22fbabf041a4, 0xe185d956e980718a, 0x2f1b78fab143a8a6}, + {0x96eebffb305b2f51, 0xd3f938ad889596b8, 0xf0f52dc746d5dd25, 0x57968290bb3a0095}, + {0xf71ab8430a20e101, 0xf393658d24f0ec47, 0xcf7509a86ee2eed1, 0x7dc43e35dc2aa3e1}}, + {{0x85966665887dd9c3, 0xc90f9b314bb05355, 0xc6e08df8ef2079b1, 0x7ef72016758cc12f}, + {0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99}, + {0xc1df18c5a907e3d9, 0x57b3371dce4c6359, 0xca704534b201bb49, 0x7f79823f9c30dd2e}}, + {{0x8334d239a3b513e8, 0xc13670d4b91fa8d8, 0x12b54136f590bd33, 0x0a4e0373d784d9b4}, + {0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0}, + {0x2eb3d6a15b7d2919, 0xb0b4f6a0d53a8235, 0x7156ce4389a45d47, 0x071a7d0ace18346c}}, + {{0xd3072daac887ba0b, 0x01262905bfa562ee, 0xcf543002c0ef768b, 0x2c3bcc7146ea7e9c}, + {0xcc0c355220e14431, 0x0d65950709b15141, 0x9af5621b209d5f36, 0x7c69bcf7617755d3}, + {0x07f0d7eb04e8295f, 0x10db18252f50f37d, 0xe951a9a3171798d7, 0x6f5a9a7322aca51d}}, + {{0x8ba1000c2f41c6c5, 0xc49f79c10cfefb9b, 0x4efa47703cc51c9f, 0x494e21a2e147afca}, + {0xe729d4eba3d944be, 0x8d9e09408078af9e, 0x4525567a47869c03, 0x02ab9680ee8d3b24}, + {0xefa48a85dde50d9a, 0x219a224e0fb9a249, 0xfa091f1dd91ef6d9, 0x6b5d76cbea46bb34}}, + {{0x8857556cec0cd994, 0x6472dc6f5cd01dba, 0xaf0169148f42b477, 0x0ae333f685277354}, + {0xe0f941171e782522, 0xf1e6ae74036936d3, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e}, + {0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075}}, + {{0x7f910fcc7ed9affe, 0x545cb8a12465874b, 0xa8397ed24b0c4704, 0x50510fc104f50993}, + {0x0adb7f355f17c824, 0x74b923c3d74299a4, 0xd57c3e8bcbf8eaf7, 0x0ad3e2d34cdedc3d}, + {0x6f0c0fc5336e249d, 0x745ede19c331cfd9, 0xf2d6fd0009eefe1c, 0x127c158bf0fa1ebe}}, + {{0xf6197c422e9879a2, 0xa44addd452ca3647, 0x9b413fc14b4eaccb, 0x354ef87d07ef4f68}, + {0xdea28fc4ae51b974, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95}, + {0xfee3b52260c5d975, 0x50352efceb41b0b8, 0x8808ac30a9f6653c, 0x302d92d20539236d}}, + {{0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9}, + {0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be}, + {0x055dc521500199e3, 0x87d9e12ba41f89b3, 0xbbe3f5e1d0e9bbfc, 0xa51571a985782c6a}}, + {{0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c}, + {0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51}, + {0xb81dbebd707c8a9e, 0x9ce8414379950668, 0x2544a4bcc2e567d6, 0xf8b272dbad7804d2}}, + {{0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141}, + {0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a}, + {0xcfcf03ccacb39c62, 0x469ca3a31abe179e, 0xea265641264d38d7, 0xb6dcc15c0c88a234}}, + {{0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902}, + {0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7}, + {0x51235996872b87e2, 0xe76745c3d6ee801e, 0x308c067c8df342a7, 0x9825ed19474a9cae}}, + {{0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a}, + {0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be}, + {0xa68fd7fb80ee96d1, 0x7d753be3e1a9bb98, 0x8fbe824219de8c78, 0x8de9d8510453bc7b}}, + {{0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed}, + {0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22}, + {0x7cdff59a93cbfba9, 0x60328e98711a63d0, 0x8a2b9ec08ecff075, 0x856ed0509f0abd06}}, + {{0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1}, + {0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975}, + {0x0dc671f6755d8058, 0x92867d44765e4fdb, 0x0596bf7bdeb22db3, 0x8e5469905cdcfe3c}}, + {{0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9}, + {0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9}, + {0x94823f2372c05382, 0xab683293191bd402, 0xabd082e40bff2cfa, 0xbea60b80fb726ec9}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, 0xba4190e2c3c7e084, 0x0e545daea51874d9}, + {0x957b8b8b0df53c30, 0x2a1c770a8e60f098, 0xbbc7a670345796de, 0x22a48f9a90c99bc9}, + {0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136}}, + {{0x20ad660839e31e32, 0xf81e1bd58405be50, 0xf8064056f4dabc69, 0x14d23dd4ce71b975}, + {0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1}, + {0xf2398e098aa27f82, 0x6d7982bb89a1b024, 0xfa694084214dd24c, 0x71ab966fa32301c3}}, + {{0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, 0xbca255434e0328da, 0x35768fbe92411b22}, + {0xb1088a0702809955, 0x43b273ea0b43c391, 0xca9b67aefe0686ed, 0x605eecbf8335f4ed}, + {0x83200a656c340431, 0x9fcd71678ee59c2f, 0x75d4613f71300f8a, 0x7a912faf60f542f9}}, + {{0xb204585e5edc1a43, 0x9f0e16ee5897c73c, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be}, + {0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a}, + {0x597028047f116909, 0x828ac41c1e564467, 0x70417dbde6217387, 0x721627aefbac4384}}, + {{0x97d03bc38736add5, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7}, + {0xfd3097bc410b2f22, 0xf1a05da7b5cfa844, 0x61289a1def57ca74, 0x245ea199bb821902}, + {0xaedca66978d477f8, 0x1898ba3c29117fe1, 0xcf73f983720cbd58, 0x67da12e6b8b56351}}, + {{0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, 0x93c6aa2f38c85a30, 0x76297d1f3d75a78a}, + {0x2b7ef3d38ec8308c, 0x828fd7ec71eb94ab, 0x807c3b36c5062abd, 0x0cb64cb831a94141}, + {0x3030fc33534c6378, 0xb9635c5ce541e861, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb}}, + {{0x629398fa8dbffc3a, 0xe12fe52dd54db455, 0xf3be11dfdaf25295, 0x628b140dce5e7b51}, + {0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, 0xceb345941adf4d62, 0x6987ff6f542de50c}, + {0x47e241428f83753c, 0x6317bebc866af997, 0xdabb5b433d1a9829, 0x074d8d245287fb2d}}, + {{0x8337d9cd440bfc31, 0x729d2ca1af318fd7, 0xa040a4a4772c2070, 0x46002ef03a7349be}, + {0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9}, + {0xfaa23adeaffe65f7, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395}}, + {{0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}, + {0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}, + {0x351186d9fca761d5, 0xd4b4bdedb9233b6d, 0xfd5e108b19fe56b0, 0xefd08c4021fbcbe5}}, + {{0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}, + {0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}, + {0xa9c266d566a4b7ac, 0xcbfa2f8391c7c7fe, 0xb7afca21d09b271a, 0x9476f964df585608}}, + {{0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}, + {0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}, + {0x4ee6dd833d72a424, 0xf81db14388b20054, 0x57c387311b5cd376, 0xede5cf88ef55db49}}, + {{0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}, + {0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}, + {0x8253ace651dcb648, 0xd3e4c26ef315c16d, 0xaac31b6bdac3eedd, 0xd5f59aceb106358a}}, + {{0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}, + {0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}, + {0xf02b53df237087c9, 0x65652d6b53b2b057, 0x3fe4d29b4cc9fbcb, 0xb081636a6fa0c424}}, + {{0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}, + {0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}, + {0x9169f6cc149e0d28, 0xabc2f0573600b6ad, 0x208d8aef85099a96, 0xecaad649dc4f1955}}, + {{0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}, + {0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}, + {0xc8f7e4430586244b, 0x9fb77ee13da0a64c, 0xf785899a637cdb78, 0xb519e6c782754a44}}, + {{0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}, + {0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}, + {0xabac4029ac257173, 0x1623e113db5609be, 0x4078d9c4fca875dc, 0xba4b93aec9e3458d}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x7813c1a2bca4283d, 0xed62f091a1863dd9, 0xaec7bcb8c268fa86, 0x10e5d3b76f1cae4c}, + {0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060}, + {0x5453bfd653da8e67, 0xe9dc1eec24a9f641, 0xbf87263b03578a23, 0x45b46c51361cba72}}, + {{0xa9402abf314f7fa1, 0xe257f1dc8e8cf450, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b}, + {0xce9d4ddd8a7fe3e4, 0xab13645676620e30, 0x4b594f7bb30e9958, 0x5c1c0aef321229df}, + {0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb}}, + {{0x8ddbf6aa5344a32e, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03}, + {0x61117e44985bfb83, 0xfce0462a71963136, 0x83ac3448d425904b, 0x75685abe5ba43d64}, + {0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, 0xdf7275107af66569, 0x135529b623b0e6aa}}, + {{0x18f0dbd7add1d518, 0x979f7888cfc11f11, 0x8732e1f07114759b, 0x79b5b81a65ca3a01}, + {0xf5c716bce22e83fe, 0xb42beb19e80985c1, 0xec9da63714254aae, 0x5972ea051590a613}, + {0x0fd4ac20dc8f7811, 0x9a9ad294ac4d4fa8, 0xc01b2d64b3360434, 0x4f7e9c95905f3bdb}}, + {{0x62674bbc5781302e, 0xd8520f3989addc0f, 0x8c2999ae53fbd9c6, 0x31993ad92e638e4c}, + {0x71c8443d355299fe, 0x8bcd3b1cdbebead7, 0x8092499ef1a49466, 0x1942eec4a144adc8}, + {0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75}}, + {{0x2db7937ff7f927c2, 0xdb741f0617d0a635, 0x5982f3a21155af76, 0x4cf6e218647c2ded}, + {0xcf361acd3c1c793a, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13}, + {0xb119227cc28d5bb6, 0x07e24ebc774dffab, 0xa83c78cee4a32c89, 0x121a307710aa24b6}}, + {{0xe4db5d5e9f034a97, 0xe153fc093034bc2d, 0x460546919551d3b1, 0x333fc76c7a40e52d}, + {0xd659713ec77483c9, 0x88bfe077b82b96af, 0x289e28231097bcd3, 0x527bb94a6ced3a9b}, + {0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7}}, + {{0x812aa0416270220d, 0x995a89faf9245b4e, 0xffadc4ce5072ef05, 0x23bc2103aa73eb73}, + {0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf}, + {0xcaee792603589e05, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a}}, + {{0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b}, + {0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619}, + {0x188d6d0c8c181550, 0xd69ac82d34fba5ce, 0xe42f9ac12cd8b021, 0xd065d3bb8942d699}}, + {{0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443}, + {0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39}, + {0xe208625959403a38, 0xfd0c5d8b6021bc96, 0x4cdc260d325c6f58, 0x841f7b84788b2c9c}}, + {{0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711}, + {0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2}, + {0xd0f8529c90f65738, 0x79681931dbdfa182, 0x3f5103fa11ca5ec6, 0xea17f6a74a062768}}, + {{0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b}, + {0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f}, + {0xedf90f482e8ec177, 0xcac01c26ea45038b, 0xe6b31468f52626b2, 0x9d052283062fc52c}}, + {{0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53}, + {0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2}, + {0xf842b8a4b8086922, 0x2d384fecabd370ab, 0xd242dc0bc4db0781, 0x9aae502884f6fe29}}, + {{0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4}, + {0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d}, + {0x75ff5138aacd248d, 0x47965b1bbc1ce44e, 0xb5f07aad2c580aea, 0xe6521483cfc283f7}}, + {{0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53}, + {0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b}, + {0x93420e8fc52fa9af, 0x7130b7cf36dade5c, 0x25142cfc027bdb18, 0x8d527d5bd1a13a90}}, + {{0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524}, + {0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba}, + {0xcc88770035ebfcae, 0x0c6defd7bb80e11c, 0x74ebf8e0dce43352, 0xb37e84b40dcbb87c}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xb5a2d50c7ec20d3e, 0xc64bdd6ea0c97263, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba}, + {0x358ecba293a36247, 0xaf8f9862b268fd65, 0x412f7e9968a01c89, 0x5786f312cd754524}, + {0x337788ffca14032c, 0xf3921028447f1ee3, 0x8b14071f231bccad, 0x4c817b4bf2344783}}, + {{0x0ff853852871b96e, 0xe13e9fab60c3f1bb, 0xeefd595325344402, 0x0a37c37075b7744b}, + {0x413ba057a40b4484, 0xba4c2e1a4f5f6a43, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53}, + {0x6cbdf1703ad0562b, 0x8ecf4830c92521a3, 0xdaebd303fd8424e7, 0x72ad82a42e5ec56f}}, + {{0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d}, + {0xc368939167024bc3, 0x8e69d16d49502fda, 0xfcf2ec3ce45f4b29, 0x065f669ea3b4cbc4}, + {0x8a00aec75532db4d, 0xb869a4e443e31bb1, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08}}, + {{0xc720cb6153ead9a3, 0x55b2c97f512b636e, 0xb1e35b5fd40290b1, 0x2fd9ccf13b530ee2}, + {0x9d05ba7d43c31794, 0x2470c8ff93322526, 0x8323dec816197438, 0x2852709881569b53}, + {0x07bd475b47f796b8, 0xd2c7b013542c8f54, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6}}, + {{0x4546baaf54aac27f, 0xf6f66fecb2a45a28, 0x582d1b5b562bcfe8, 0x44b123f3920f785f}, + {0x68a24ce3a1d5c9ac, 0xbb77a33d10ff6461, 0x0f86ce4425d3166e, 0x56507c0950b9623b}, + {0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3}}, + {{0xc6b5967b5598a074, 0x5efe91ce8e493e25, 0xd4b72c4549280888, 0x20ef1149a26740c2}, + {0x3cd7bc61e7ce4594, 0xcd6b35a9b7dd267e, 0xa080abc84366ef27, 0x6ec7c46f59c79711}, + {0x2f07ad636f09a8a2, 0x8697e6ce24205e7d, 0xc0aefc05ee35a139, 0x15e80958b5f9d897}}, + {{0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, 0xc774e1342dc5c327, 0x021354b892021f39}, + {0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443}, + {0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, 0xb323d9f2cda390a7, 0x7be0847b8774d363}}, + {{0x8c99cc5a8b3f55c3, 0x0611d7253fded2a0, 0xed2995ff36b70a36, 0x1f699a54d78a2619}, + {0x1466f5af5307fa11, 0x817fcc7ded6c0af2, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b}, + {0xe77292f373e7ea8a, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966}}, + {{0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}, + {0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}, + {0x49f0d91b82541969, 0x0e2e5e689dd0c5c8, 0xbdf731811669fc6b, 0xe9dcbe6ecc92c424}}, + {{0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}, + {0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}, + {0x29fd9cbb7a7084c1, 0xeb54cad05e15aeb5, 0x76ffbbe5df6f5628, 0x84fb8ea06edac4d9}}, + {{0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}, + {0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}, + {0x16496bbc6fc16ea9, 0x475b6b3485a9c831, 0x37832e5b45456dbb, 0x9ce150bd94518a97}}, + {{0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}, + {0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}, + {0xffedf8ac5042dcac, 0x16d431470227097c, 0x07e9964c7b18d46e, 0xcc052ad4dc975f99}}, + {{0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}, + {0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}, + {0x45e96ccec12f7dfe, 0xd6cd60527ae4cb7f, 0xfed7fec3fcfcde34, 0xfffee4bb5ce4021c}}, + {{0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}, + {0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}, + {0xd54409b1b78f34cd, 0x329a430f55ba7494, 0x6541b1458a1767a2, 0x80f437ef2aeb211b}}, + {{0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}, + {0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}, + {0x9da734f2f87689e5, 0xb6d6bdab6e760d67, 0x5f354bdc1d1c911b, 0xf1831d4f320f995e}}, + {{0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}, + {0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}, + {0x8cb27284ef9fa72e, 0x26bfa86190396fa0, 0x9b9907066dfd6cd2, 0x848133e6259f292f}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xeb18b9ab7f5745c6, 0x023a8aee5787c690, 0xb72712da2df7afa9, 0x36597d25ea5c013d}, + {0xa2b4dae0b5511c9a, 0x7ac860292bffff06, 0x981f375df5504234, 0x3f6bd725da4ea12d}, + {0x734d8d7b106058ac, 0xd940579e6fc6905f, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0}}, + {{0x78c2373c695c690d, 0xdd252e660642906e, 0x951d44444ae12bd2, 0x4235ad7601743956}, + {0x6dae4a51a77cfa9b, 0x82263654e7a38650, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba}, + {0x6258cb0d078975f5, 0x492942549189f298, 0xa0cab423e2e36ee4, 0x0e7ce2b0cdf066a1}}, + {{0xc494643ac48c85a3, 0xfd361df43c6139ad, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a}, + {0xfea6fedfd94b70f9, 0xf130c051c1fcba2d, 0x4882d47e7f2fab89, 0x615256138aeceeb5}, + {0x2abbf64e4870cb0d, 0xcd65bcf0aa458b6b, 0x9abe4eba75e8985d, 0x7f0bc810d514dee4}}, + {{0xb9006ba426f4136f, 0x8d67369e57e03035, 0xcbc8dfd94f463c28, 0x0d1f8dbcf8eedbf5}, + {0x83ac9dad737213a0, 0x9ff6f8ba2ef72e98, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75}, + {0xba1693313ed081dc, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3}}, + {{0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1}, + {0x16561f696a0aa75c, 0xc1bf725c5852bd6a, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026}, + {0x00120753afbd232e, 0xe92bceb8fdd8f683, 0xf81669b384e72b91, 0x33fad52b2368a066}}, + {{0x540649c6c5e41e16, 0x0af86430333f7735, 0xb2acfcd2f305e746, 0x16c0f429a256dca7}, + {0x8d2cc8d0c422cfe8, 0x072b4f7b05a13acb, 0xa3feb6e6ecf6a56f, 0x3cc355ccb90a71e2}, + {0xe9b69443903e9131, 0xb8a494cb7a5637ce, 0xc87cd1a4baba9244, 0x631eaf426bae7568}}, + {{0xb3e90410da66fe9f, 0x85dd4b526c16e5a6, 0xbc3d97611ef9bf83, 0x5599648b1ea919b5}, + {0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5}, + {0xd6026344858f7b19, 0x14ab352fa1ea514a, 0x8900441a2090a9d7, 0x7b04715f91253b26}}, + {{0x83edbd28acf6ae43, 0x86357c8b7d5c7ab4, 0xc0404769b7eb2c44, 0x59b37bf5c2f6583f}, + {0xb376c280c4e6bac6, 0x970ed3dd6d1d9b0b, 0xb09a9558450bf944, 0x48d0acfa57cde223}, + {0xb60f26e47dabe671, 0xf1d1a197622f3a37, 0x4208ce7ee9960394, 0x16234191336d3bdb}}, + {{0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e}, + {0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1}, + {0xe439b9ce1a9409bb, 0x2c8654ef91ac7d5c, 0xb2a73a81fabfe972, 0xa99da99d7bbd271b}}, + {{0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8}, + {0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4}, + {0x470bcf71807f4187, 0xa0c34734cb562c68, 0xe7569e42cc33d4d3, 0x8effba04c565098e}}, + {{0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412}, + {0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501}, + {0xe38b47723d819c7a, 0xf8b7abd972eb7af3, 0x5eba0484c1f234cf, 0xef7bc0e4bc7fc4dc}}, + {{0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f}, + {0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5}, + {0x1a9b3022a382d2ef, 0x7d11502128c83346, 0x9ef8249d2e064f54, 0xf494553c4bca7244}}, + {{0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345}, + {0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a}, + {0x2d2beb7e0e34501b, 0xdce2d2498e9e8b1a, 0xf48289a91d5aa367, 0xc16aa327d55b6a09}}, + {{0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188}, + {0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5}, + {0x1bb5dcead2f697da, 0xa3f73aa68f799669, 0x20d249f5b9500491, 0xa86eaa3e07a90276}}, + {{0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4}, + {0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23}, + {0x34ce68ffe44c996e, 0xccff9fadb4001346, 0xd6c8ee66e577dcc3, 0xd6e77bc9c2b12c9b}}, + {{0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40}, + {0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5}, + {0x5854968672b69b64, 0x7ede5521034a5437, 0x5a23ed1084ac6b8d, 0xf802b8f9a1bacae5}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xf19aeac733a63aef, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5}, + {0x852dd1fd3d578bbe, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40}, + {0xa7ab69798d496476, 0x8121aadefcb5abc8, 0xa5dc12ef7b539472, 0x07fd47065e45351a}}, + {{0xc8583c3d258d2bcd, 0x17029a4daf60b73f, 0xfa0fc9d6416a3781, 0x1c1e5fba38b3fb23}, + {0x304211559ae8e7c3, 0xf281b229944882a5, 0x8a13ac2e378250e4, 0x014afa0954ba48f4}, + {0xcb3197001bb3666c, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364}}, + {{0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5}, + {0xfb9d37c3bc1ab6eb, 0x02be14534d57a240, 0xf4d73415f8a5e1f6, 0x5964f4300ccc8188}, + {0xe44a23152d096800, 0x5c08c55970866996, 0xdf2db60a46affb6e, 0x579155c1f856fd89}}, + {{0x96324edd12e0c9ef, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a}, + {0xb5f16b630817e7a6, 0x808c69233c351026, 0x324a983b54cef201, 0x53c092084a485345}, + {0xd2d41481f1cbafbf, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6}}, + {{0xe48f535e3ed15433, 0xd075692a0d7270a3, 0x40fbd21daade6387, 0x14264887cf4495f5}, + {0xab39f3ef61bb3a3f, 0x8eb400652eb9193e, 0xb5de6ecc38c11f74, 0x654d7e9626f3c49f}, + {0xe564cfdd5c7d2ceb, 0x82eeafded737ccb9, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb}}, + {{0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501}, + {0x204abad63700a93b, 0xbe0023d3da779373, 0xd85f0346633ab709, 0x00496dc490820412}, + {0x1c74b88dc27e6360, 0x074854268d14850c, 0xa145fb7b3e0dcb30, 0x10843f1b43803b23}}, + {{0xc5f90455376276dd, 0xce59158dd7645cd9, 0x92f65d511d366b39, 0x11574b6e526996c4}, + {0xd56f672de324689b, 0xd1da8aedb394a981, 0xdd7b58fe9168cfed, 0x7ce246cd4d56c1e8}, + {0xb8f4308e7f80be53, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671}}, + {{0x73f93d36101b95eb, 0xfaef33794f6f4486, 0x5651735f8f15e562, 0x7fa3f19058b40da1}, + {0xa03fc862059d699e, 0x2370cfa19a619e69, 0xc4fe3b122f823deb, 0x1d1b056fa7f0844e}, + {0x1bc64631e56bf61f, 0xd379ab106e5382a3, 0x4d58c57e0540168d, 0x566256628442d8e4}}, + {{0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}, + {0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}, + {0x936f29b7b5b8cd1a, 0x2adebc0235a9cd66, 0x4c41d73c6ea2391e, 0x98c697818cd8e6e4}}, + {{0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}, + {0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}, + {0x5ccbb152e4170804, 0x82e1af1453158670, 0x8839a961adf21fad, 0xba77d01eacb292c1}}, + {{0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}, + {0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}, + {0x99595b2c6dad2e81, 0x1a221e4378e537f8, 0x47d394bf593e3690, 0xe92785bee5deddeb}}, + {{0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}, + {0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}, + {0x0d9ed0a390ec935e, 0x50152ef80922ee41, 0xad81652dec2190cc, 0xe18634ca7e7708a2}}, + {{0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}, + {0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}, + {0x5e75a07dcc2b7678, 0x99673b4a1387da80, 0x5871905ac8c1be00, 0x89a9d876af1067e0}}, + {{0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}, + {0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}, + {0x1d542a1686d3775c, 0xe5fdffe7346d92a2, 0x404596324551a0e1, 0x8cfab74ca51770a0}}, + {{0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}, + {0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}, + {0x668d8939b6d4f39d, 0xb8333d3b201dfa03, 0x232d647b229dc5c3, 0xc13d54a6fd77385d}}, + {{0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}, + {0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}, + {0xd5489975ac091270, 0xcfbdbda7e22e8f5e, 0xbfffebb3c51dfe9e, 0xa8de7692db71b603}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xb9e499def6267ff6, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006}, + {0xdd499cd61ff38640, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231}, + {0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc}}, + {{0x0b6e5517fd181bae, 0x9022629f2bb963b4, 0x5509bce932064625, 0x578edd74f63c13da}, + {0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd}, + {0x997276c6492b0c3d, 0x47ccc2c4dfe205fc, 0xdcd29b84dd623a3c, 0x3ec2ab590288c7a2}}, + {{0xa1a0d27be4d87bb9, 0xa98b4deb61391aed, 0x99a0ddd073cb9b83, 0x2dd5c25a200fcace}, + {0xa7213a09ae32d1cb, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e}, + {0xe2abd5e9792c887e, 0x1a020018cb926d5d, 0xbfba69cdbaae5f1e, 0x730548b35ae88f5f}}, + {{0xc43551a3cba8b8ee, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca}, + {0x805b094ba1d6e334, 0xbf3ef17709353f19, 0x423f06cb0622702b, 0x585a2277d87845dd}, + {0xa18a5f8233d48962, 0x6698c4b5ec78257f, 0xa78e6fa5373e41ff, 0x7656278950ef981f}}, + {{0x38c3cf59d51fc8c0, 0x9bedd2fd0506b6f2, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6}, + {0xe17073a3ea86cf9d, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616}, + {0xf2612f5c6f136c7c, 0xafead107f6dd11be, 0x527e9ad213de6f33, 0x1e79cb358188f75d}}, + {{0x013436c3eef7e3f1, 0x828b6a7ffe9e10f8, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831}, + {0x77e953d8f5e08181, 0x84a50c44299dded9, 0xdc6c2d0c864525e5, 0x478ab52d39d1f2f4}, + {0x66a6a4d39252d159, 0xe5dde1bc871ac807, 0xb82c6b40a6c1c96f, 0x16d87a411a212214}}, + {{0xb3bd7e5a42066215, 0x879be3cd0c5a24c1, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6}, + {0xfba4d5e2d54e0583, 0xe21fafd72ebd99fa, 0x497ac2736ee9778f, 0x1f990b577a5a6dde}, + {0xa3344ead1be8f7d6, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e}}, + {{0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd}, + {0xd8ac9929943c6fe4, 0xb5f9f161a38392a2, 0x2699db13bec89af3, 0x7dcf843ce405f074}, + {0x6c90d6484a4732c0, 0xd52143fdca563299, 0xb3be28c3915dc6e1, 0x6739687e7327191b}}, + {{0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e}, + {0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408}, + {0xe69b842eeb57ad49, 0xa848934defcb2c50, 0x9cd624bbf0629205, 0xa10bc1a795a8eb6c}}, + {{0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662}, + {0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4}, + {0xd744ed11fb58befa, 0xebcec44264317e8b, 0x8d0a4a1b173ef3bf, 0x83404e66c95232a4}}, + {{0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e}, + {0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1}, + {0xce4968d2674f41f2, 0x826df8f9535921a4, 0x198cef076f759a60, 0xaf053d591020fdca}}, + {{0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf}, + {0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39}, + {0x2711e4e7ce615930, 0xffb277f7c5de0f25, 0xc42955e277c5b0b4, 0xb2465c59202602eb}}, + {{0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278}, + {0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb}, + {0xe53671b075aeddf1, 0x82516abb2405d01f, 0x7cdf55f229bcf206, 0x998d7d9ad3b5d04a}}, + {{0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258}, + {0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443}, + {0xa653c43a298f3fb8, 0x151983ef64ee6bf9, 0x6867420f4c87d025, 0x9ae1cdfe02f8bf6d}}, + {{0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7}, + {0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d}, + {0x4cfe448394e41337, 0xaac6c0923914ec8a, 0x6ef2d7ef68491b14, 0xe52bab7262b8615c}}, + {{0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa}, + {0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d}, + {0x8d5e7b70c3f337b0, 0xc73a9f3d788361ab, 0xaffb1dd731aabebf, 0xfbdbe75efcbd628e}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x9f65c5ea200814cf, 0x840536e169a31740, 0x8b0ed13925c8b4ad, 0x0080dbafe936361d}, + {0x8ce5aad0c9cb971f, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa}, + {0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71}}, + {{0x899dea51abf3ff5f, 0x9b93a8672fc2d8ba, 0x2c38cb97be6ebd5c, 0x114d578497263b5d}, + {0x58e84c6f20816247, 0x8db2b2b6e36fd793, 0x977182561d484d85, 0x0822024f8632abd7}, + {0xb301bb7c6b1beca3, 0x55393f6dc6eb1375, 0x910d281097b6e4eb, 0x1ad4548d9d479ea3}}, + {{0xcd5a7da0389a48fd, 0xb38fa4aa9a78371e, 0xc6d9761b2cdb8e6c, 0x35cf51dbc97e1443}, + {0xa06fe66d0fe9fed3, 0xa8733a401c587909, 0x30d14d800df98953, 0x41ce5876c7b30258}, + {0x59ac3bc5d670c022, 0xeae67c109b119406, 0x9798bdf0b3782fda, 0x651e3201fd074092}}, + {{0xd63d8483ef30c5cf, 0x4cd4b4962361cc0c, 0xee90e500a48426ac, 0x0af51d7d18c14eeb}, + {0xa57ba4a01efcae9e, 0x769f4beedc308a94, 0xd1f10eeb3603cb2e, 0x4099ce5e7e441278}, + {0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, 0x8320aa0dd6430df9, 0x667282652c4a2fb5}}, + {{0x874621f4d86bc9ab, 0xb54c7bbe56fe6fea, 0x077a24257fadc22c, 0x1ab53be419b90d39}, + {0xada8b6e02946db23, 0x1c0ce51a7b253ab7, 0x8448c85a66dd485b, 0x7f1fc025d0675adf}, + {0xd8ee1b18319ea6aa, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14}}, + {{0x8ce7b23bb99c0755, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1}, + {0xd95b00bbcbb77c68, 0xddbc846a91f17849, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e}, + {0x31b6972d98b0bde8, 0x7d920706aca6de5b, 0xe67310f8908a659f, 0x50fac2a6efdf0235}}, + {{0xf3d3a9f35b880f5a, 0xedec050cdb03e7c2, 0xa896981ff9f0b1a2, 0x49a4ae2bac5e34a4}, + {0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, 0xc001cb30aa8e551d, 0x6a28d35944f43662}, + {0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b}}, + {{0xa311ddc26b89792d, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408}, + {0x8e793a7acc36e6e0, 0xf9fab7a37d586eed, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e}, + {0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493}}, + {{0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}, + {0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}, + {0x50a441e510ae6a33, 0xeb73ed886e84ea12, 0xd66e0804851a25d1, 0xb982dfe40722d798}}, + {{0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}, + {0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}, + {0x1cbfedc202484d40, 0xb784681e5de54d6e, 0x066982fd02196b61, 0x87f218d1372c2168}}, + {{0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}, + {0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}, + {0x41aeec3aaaeed38e, 0x9977bdc56577e032, 0xbb99887aa1afc4b8, 0xf1cbc670b5f9bfb5}}, + {{0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}, + {0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}, + {0x208e8123da4d27e5, 0xde068f24664acfbf, 0x256dcb483c12b39d, 0xa18dc9a38411f6c1}}, + {{0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}, + {0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}, + {0x630d7646445abbec, 0x0c89f162a5368ebd, 0xe27d1a39b06c9f55, 0x9d2adde4806b9870}}, + {{0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}, + {0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}, + {0x5924f772a10786cf, 0xad870f239ef6c81a, 0x53fcb62d9e5e9147, 0xf1504fc86f1ade86}}, + {{0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}, + {0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}, + {0xc781c0f912591ea7, 0x98cfe2ae665ec53f, 0x42a52707c9d9c7ee, 0x95de1932b02a1641}}, + {{0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}, + {0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}, + {0x2bf0e6ac3c4a2564, 0xe253908cdeee6164, 0xfc339fde014da69f, 0xa5a077817c98b4b4}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xef782014385675a6, 0xa2649f30aafda9e8, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3}, + {0xa66dcc9dc80c1ac0, 0x97a05cf41b38a436, 0xa7ebf3be95dbd7c6, 0x7da0b8f68d7e7dab}, + {0xd40f1953c3b5da76, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b}}, + {{0x8f6301cf70a13d11, 0xcfceb815350dd0c4, 0xf70297d4a4bca47e, 0x3669b656e44d1434}, + {0x9e9628d3a0a643b9, 0xb5c3cb00e6c32064, 0x9b5302897c2dec32, 0x43e37ae2d5d1c70c}, + {0x387e3f06eda6e133, 0x67301d5199a13ac0, 0xbd5ad8f836263811, 0x6a21e6cd4fd5e9be}}, + {{0xf1c6170a3046e65f, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57}, + {0xef4129126699b2e3, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36}, + {0xa6db088d5ef8790b, 0x5278f0dc610937e5, 0xac0349d261a16eb8, 0x0eafb03790e52179}}, + {{0x960555c13748042f, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661}, + {0x5140805e0f75ae1d, 0xec02fbe32662cc30, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3}, + {0x9cf289b9bba543ee, 0xf3760e9d5ac97142, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f}}, + {{0x524c299c18d0936d, 0xc86bb56c8a0c1a0c, 0xa375052edb4a8631, 0x5c0efde4bc754562}, + {0x7585d4263af77a3c, 0xdfae7b11fee9144d, 0xa506708059f7193d, 0x14f29a5383922037}, + {0xdf717edc25b2d7f5, 0x21f970db99b53040, 0xda9234b7c3ed4c62, 0x5e72365c7bee093e}}, + {{0x575bfc074571217f, 0x3779675d0694d95b, 0x9a0a37bbf4191e33, 0x77f1104c47b4eabc}, + {0x7d9339062f08b33e, 0x5b9659e5df9f32be, 0xacff3dad1f9ebdfd, 0x70b20555cb7349b7}, + {0xbe5113c555112c4c, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a}}, + {{0xb67d22d93ecebde8, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372}, + {0x18930b093e4b1928, 0x7de3e10e73f3f640, 0xf43217da73395d6f, 0x6f8aded6ca379c3e}, + {0xe340123dfdb7b29a, 0x487b97e1a21ab291, 0xf9967d02fde6949e, 0x780de72ec8d3de97}}, + {{0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4}, + {0x671feaf300f42772, 0x8f72eb2a2a8c41aa, 0x29a17fd797373292, 0x1defc6ad32b587a6}, + {0xaf5bbe1aef5195a7, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867}}, + {{0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d}, + {0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2}, + {0x2259626cf5c12bf7, 0xc2c7910e329f58dd, 0x37e852a74255b119, 0xdc4172aab018c8d5}}, + {{0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64}, + {0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180}, + {0x61a11171cc24d8ca, 0xe767ab21293bc35a, 0x5be3dd3a6d8e7ec7, 0xd852aac75bc5a164}}, + {{0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee}, + {0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102}, + {0x02d2a2cae682416c, 0xdf83d115741b005c, 0xd9ec2724cda516e7, 0x85cda2e8d88be2c1}}, + {{0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9}, + {0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630}, + {0xe569ea5649d5cb7b, 0xddfaf3a9b5ad0133, 0x585d877ad743f201, 0xa17d88f5e5e118e2}}, + {{0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c}, + {0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276}, + {0xc8277197041bacb9, 0x79f68ab73f28afcd, 0xb164ec1076b5f2ca, 0xda57c353a8ac2cda}}, + {{0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c}, + {0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20}, + {0x0dcab9841a43ea6a, 0xfc2d26fdf2454c73, 0xd8ad655d03061f61, 0xf7bf410d62cb43af}}, + {{0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42}, + {0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9}, + {0x649a370e82f8ad00, 0x77e31cc7388117ff, 0x3c4aeb0fa49d061c, 0x9912a22a413ef2b7}}, + {{0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0}, + {0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287}, + {0xe4702ee86a1d564e, 0xe3b1a11ed4949d6e, 0xa4cf18ef8bdb4a8d, 0x91946217b3b0b539}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, 0x8d5cfe45b941a8a4, 0x44c218671c974287}, + {0x745f9d56296bc318, 0x993580d4d8152e65, 0xb0e5b13f5839e9ce, 0x51fc2b28d43921c0}, + {0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6}}, + {{0xdff25fce4b1de151, 0xd841c0c7e11c4025, 0x2554b3c854749c87, 0x2d292459908e0df9}, + {0x6b7c5f10f80cb088, 0x736b54dc56e42151, 0xc2b620a5c6ef99c4, 0x5f4c802cc3a06f42}, + {0x9b65c8f17d0752da, 0x881ce338c77ee800, 0xc3b514f05b62f9e3, 0x66ed5dd5bec10d48}}, + {{0x7d38a1c20bb2089d, 0x808334e196ccd412, 0xc4a70b8c6c97d313, 0x2eacf8bc03007f20}, + {0xf0adf3c9cbca047d, 0x81c3b2cbf4552f6b, 0xcfda112d44735f93, 0x1f23a0c77e20048c}, + {0xf235467be5bc1570, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50}}, + {{0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276}, + {0xcd54e06b7f37e4eb, 0x8cc15f87f5e96cca, 0xb8248bb0d3597dce, 0x246affa06074400c}, + {0x37d88e68fbe45321, 0x86097548c0d75032, 0x4e9b13ef894a0d35, 0x25a83cac5753d325}}, + {{0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630}, + {0x9f0f66293952b6e2, 0x33db5e0e0934267b, 0xff45252bd609fedc, 0x06be10f5c506e0c9}, + {0x1a9615a9b62a345f, 0x22050c564a52fecc, 0xa7a2788528bc0dfe, 0x5e82770a1a1ee71d}}, + {{0x35425183ad896a5c, 0xe8673afbe78d52f6, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102}, + {0xe802e80a42339c74, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee}, + {0xfd2d5d35197dbe6e, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e}}, + {{0xd036b9bbd16dfde2, 0xa2055757c497a829, 0x8e6cc966a7f12667, 0x4d3b1a791239c180}, + {0xecd27d017e2a076a, 0xd788689f1636495e, 0x52a61af0919233e5, 0x2a479df17bb1ae64}, + {0x9e5eee8e33db2710, 0x189854ded6c43ca5, 0xa41c22c592718138, 0x27ad5538a43a5e9b}}, + {{0x2746dd4b15350d61, 0xd03fcbc8ee9521b7, 0xe86e365a138672ca, 0x510e987f7e7d89e2}, + {0xcb5a7d638e47077c, 0x8db7536120a1c059, 0x549e1e4d8bedfdcc, 0x080153b7503b179d}, + {0xdda69d930a3ed3e3, 0x3d386ef1cd60a722, 0xc817ad58bdaa4ee6, 0x23be8d554fe7372a}}, + {{0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}, + {0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}, + {0xf239d2c9e5cdce00, 0x05b8a7cd6bdffd8f, 0xfd27feaec06a6b31, 0xc2243d5ece3fa2a3}}, + {{0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}, + {0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}, + {0x11c4982a47d4adb0, 0xc90e9cb9605a3e14, 0x5a4b2d0d913e602c, 0x9d134d4558856bf7}}, + {{0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}, + {0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}, + {0x4858402ef5b17214, 0x41a8ff81bb364cc6, 0x9f3edf80eaa85105, 0xd9fa776ed99de724}}, + {{0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}, + {0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}, + {0xfb1e9fe61b1aa52c, 0x1884bc8581d06d16, 0x3831d23e90ea655b, 0xba15023e0b28f33f}}, + {{0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}, + {0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}, + {0x50d30934617ae1d4, 0x70a6c6ec39ddc73b, 0x2575476966040c8c, 0xc24a9cd015cb4361}}, + {{0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}, + {0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}, + {0x6556b953f90b47af, 0xe35d7b5a57f93b0c, 0xc12cd9a03932b878, 0x94bc02fe32e02de8}}, + {{0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}, + {0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}, + {0x67f0b5d0a8001e0e, 0xff98f2f21e7c67bc, 0xefa3c0b5b604ea02, 0xd967359caed95963}}, + {{0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}, + {0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}, + {0x4902920905618b0d, 0x0e7d87431b50d985, 0x7daa4c2f0e1066f1, 0xa58a735c6f3a0d6c}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x95fe919a74ef4fad, 0x3a827becf6a308a2, 0x964e01d309a47b01, 0x71c43c4f5ba3c797}, + {0xbc1ef4bd567ae7a9, 0x3f624cb2d64498bd, 0xe41064d22c1f4ec8, 0x2ef9c5a5ba384001}, + {0xb6fd6df6fa9e74cd, 0xf18278bce4af267a, 0x8255b3d0f1ef990e, 0x5a758ca390c5f293}}, + {{0xa2b72710d9462495, 0x3aa8c6d2d57d5003, 0xe3d400bfa0b487ca, 0x2dbae244b3eb72ec}, + {0x8ce0918b1d61dc94, 0x8ded36469a813066, 0xd4e6a829afe8aad3, 0x0a738027f639d43f}, + {0x980f4a2f57ffe1cc, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c}}, + {{0xe765318832b0ba78, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07}, + {0x2e3d702f5e3dd90e, 0x9e3f0918e4d25386, 0x5e773ef6024da96a, 0x3c004b0c4afa3332}, + {0x9aa946ac06f4b82b, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217}}, + {{0xc7a75d4b4697c544, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714}, + {0xb5c742583e760ef3, 0x75dc52b9ee0ab990, 0xbf1427c2072b923f, 0x73420b2d6ff0d9f0}, + {0xaf2cf6cb9e851e06, 0x8f593913c62238c4, 0xda8ab89699fbf373, 0x3db5632fea34bc9e}}, + {{0xf46eee2bf75dd9d8, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13}, + {0x2e4990b1829825d5, 0xedeaeb873e9a8991, 0xeef03d394c704af8, 0x59197ea495df2b0e}, + {0x04e16019e4e55aae, 0xe77b437a7e2f92e9, 0xc7ce2dc16f159aa4, 0x45eafdc1f4d70cc0}}, + {{0x698401858045d72b, 0x4c22faa2cf2f0651, 0x941a36656b222dc6, 0x5a5eebc80362dade}, + {0xb60e4624cfccb1ed, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940}, + {0xb7a7bfd10a4e8dc6, 0xbe57007e44c9b339, 0x60c1207f1557aefa, 0x26058891266218db}}, + {{0x59f704a68360ff04, 0xc3d93fde7661e6f4, 0x831b2a7312873551, 0x54ad0c2e4e615d57}, + {0x4c818e3cc676e542, 0x5e422c9303ceccad, 0xec07cccab4129f08, 0x0dedfa10b24443b8}, + {0xee3b67d5b82b522a, 0x36f163469fa5c1eb, 0xa5b4d2f26ec19fd3, 0x62ecb2baa77a9408}}, + {{0xe5ed795261152b3d, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be}, + {0x92072836afb62874, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98}, + {0x0dc62d361a3231da, 0xfa47583294200270, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c}}, + {{0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224}, + {0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68}, + {0x374db849a4350e3e, 0xb688623c4e4d39ad, 0x765e7f442a131d1d, 0xec0f675c31371fc6}}, + {{0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19}, + {0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7}, + {0xfbe0816da7cf0bcc, 0xffd293568699e3f9, 0x79236006d4fb95d1, 0x89fc9f6d74fb6c2e}}, + {{0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66}, + {0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959}, + {0xe05245245abc6a33, 0x4be5fd5f51f25995, 0x40e60a67445c83f8, 0x95ed475321b7bcf2}}, + {{0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192}, + {0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788}, + {0x7025f0c85fe9ae41, 0xf5252488375f1cbc, 0xdf040203378a17df, 0xe30d4157f3ddf918}}, + {{0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b}, + {0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b}, + {0x34a73701bcc276a1, 0x765f34d1957281af, 0x86356aacf60441a5, 0xf39d99e932803ef9}}, + {{0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972}, + {0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6}, + {0x167edf79018113fa, 0xb3459418d0aeabc8, 0xe2fbe974ae910516, 0xa15ec6efbc67d346}}, + {{0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e}, + {0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb}, + {0xa13333b0d3d8c825, 0xbc4861f3d23348fc, 0xcc1ff743b13bc20c, 0xf93e47bf0f8a993f}}, + {{0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c}, + {0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40}, + {0xf2ffa532cc24c21b, 0xfeee4c837f53ca1d, 0xb76d299390771414, 0x88f1524e9af70432}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x3f50a50a4ffb81ef, 0xb1e035093bf420bf, 0x9baa8e1cc6aa2cd0, 0x32239861fa237a40}, + {0xfb735ac2004a35d1, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c}, + {0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd}}, + {{0x8451f9e05e4e89dd, 0xc06302ffbc793937, 0x5d22749556a6495c, 0x09a6755ca05603fb}, + {0xf1d3b681a05071b9, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e}, + {0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0}}, + {{0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6}, + {0x69ee9e7f9b02805c, 0xcbff828a547d1640, 0x3d93a869b2430968, 0x46b7b8cd3fe26972}, + {0xe9812086fe7eebe0, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9}}, + {{0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b}, + {0x6f2b3be4d5d3b002, 0xafec33d96a09c880, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b}, + {0xcb58c8fe433d8939, 0x89a0cb2e6a8d7e50, 0x79ca955309fbbe5a, 0x0c626616cd7fc106}}, + {{0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788}, + {0x8fdfc379fbf454b1, 0x45a5a970f1a4b771, 0xac921ef7bad35915, 0x42d088dca81c2192}, + {0x8fda0f37a0165199, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7}}, + {{0xc2ddf1deb36202ac, 0x92a5fe09d2e27aa5, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959}, + {0x982d6e1a02c0412f, 0x90fa4c83db58e8fe, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66}, + {0x1fadbadba54395a7, 0xb41a02a0ae0da66a, 0xbf19f598bba37c07, 0x6a12b8acde48430d}}, + {{0xf8daea1f39d495d9, 0x592c190e525f1dfc, 0xdb8cbd04c9991d1b, 0x11f7fda3d88f0cb7}, + {0x793bdd801aaeeb5f, 0x00a2a0aac1518871, 0xe8a373a31f2136b4, 0x48aab888fc91ef19}, + {0x041f7e925830f40e, 0x002d6ca979661c06, 0x86dc9ff92b046a2e, 0x760360928b0493d1}}, + {{0x21bb41c6120cf9c6, 0xeab2aa12decda59b, 0xc1a72d020aa48b34, 0x215d4d27e87d3b68}, + {0xb43108e5695a0b05, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224}, + {0xc8b247b65bcaf19c, 0x49779dc3b1b2c652, 0x89a180bbd5ece2e2, 0x13f098a3cec8e039}}, + {{0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}, + {0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}, + {0xcdc3f0021a899c0a, 0xfa3c20c75dd159ef, 0x423875425366b065, 0xd9ab605b101c2366}}, + {{0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}, + {0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}, + {0x60b107de66ce8fe2, 0xd0b62d7d155872b0, 0xf68e5a54a510ce8b, 0x91a1cefda696149a}}, + {{0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}, + {0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}, + {0x985d2763173de85d, 0x99625a09976a2f3e, 0x0a9a671a4d7d5d4f, 0xa93f770e121df58c}}, + {{0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}, + {0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}, + {0x23252b41aee41513, 0x5bac7f8a12d9330d, 0x1e630060ffa0659a, 0xcb0308bb8ab7e09c}}, + {{0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}, + {0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}, + {0x7a92d87d3a8a689a, 0x05ecba9606634133, 0x77bb038c3f15b18e, 0x9cd265e5a6c0db96}}, + {{0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}, + {0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}, + {0x8f7e9604f3bd6686, 0x1eb9ff5328913098, 0xd15546758f19ba45, 0xc67e0c61a75b050d}}, + {{0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}, + {0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}, + {0x652d46ac117fad5f, 0x1770e65505219272, 0xf18ee8fbeaf17d30, 0x86464446226a2123}}, + {{0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}, + {0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}, + {0xac720234bebb954c, 0x5a530256bcb6c806, 0xb9506f72d9c37387, 0x9e2f9cc36435f2f6}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x9adc0ff9ce5ec54b, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b}, + {0xf3aa57a22796bb14, 0x883abab79b07da21, 0xe54be21831a0391c, 0x5ee7fb38d83205f9}, + {0x538dfdcb41446a8e, 0xa5acfda9434937f9, 0x46af908d263c8c78, 0x61d0633c9bca0d09}}, + {{0x63744935ffdb2566, 0xc5bd6b89780b68bb, 0x6f1b3280553eec03, 0x6e965fd847aed7f5}, + {0xada328bcf8fc73df, 0xee84695da6f037fc, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc}, + {0x9ad2b953ee80527b, 0xe88f19aafade6d8d, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc}}, + {{0xebb355406a3126c2, 0xd26383a868c8c393, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147}, + {0xd1997dae8e9f7374, 0xa032a2f8cfbb0816, 0xcd6cba126d445f0a, 0x1ba811460accb834}, + {0x708169fb0c429954, 0xe14600acd76ecf67, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2}}, + {{0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd}, + {0xc845dfa56de66fde, 0xe152a5002c40483a, 0xe9d2e163c7b4f632, 0x30f4452edcbc1b65}, + {0x856d2782c5759740, 0xfa134569f99cbecc, 0x8844fc73c0ea4e71, 0x632d9a1a593f2469}}, + {{0xf6bb6b15b807cba6, 0x1823c7dfbc54f0d7, 0xbb1d97036e29670b, 0x0b24f48847ed4a57}, + {0xbf09fd11ed0c84a7, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2}, + {0xdcdad4be511beac7, 0xa4538075ed26ccf2, 0xe19cff9f005f9a65, 0x34fcf74475481f63}}, + {{0xc197e04c789767ca, 0xb8714dcb38d9467d, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7}, + {0xa5bb1dab78cfaa98, 0x5ceda267190b72f2, 0x9309c9110a92608e, 0x0119a3042fb374b0}, + {0x67a2d89ce8c2177d, 0x669da5f66895d0c1, 0xf56598e5b282a2b0, 0x56c088f1ede20a73}}, + {{0x336d3d1110a86e17, 0xd7f388320b75b2fa, 0xf915337625072988, 0x09674c6b99108b87}, + {0x581b5fac24f38f02, 0xa90be9febae30cbd, 0x9a2169028acf92f0, 0x038b7ea48359038f}, + {0x9f4ef82199316ff8, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65}}, + {{0xb16c62f587e593fb, 0x4999eddeca5d3e71, 0xb491c1e014cc3e6d, 0x08f5114789a8dba8}, + {0x3304fb0e63066222, 0xfb35068987acba3f, 0xbd1924778c1061a3, 0x3058ad43d1838620}, + {0x323c0ffde57663d0, 0x05c3df38a22ea610, 0xbdc78abdac994f9a, 0x26549fa4efe3dc99}}, + {{0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b}, + {0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da}, + {0x2e3efe2af47ecc59, 0x2119f0ee891197d7, 0xf349776cc7c09bf6, 0x9e7c3a9a0900b7b5}}, + {{0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f}, + {0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2}, + {0x733eab33161c66d6, 0xa4c5fbf47b2197b9, 0x3b2759e34e41a291, 0xbf0476842779e0fd}}, + {{0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068}, + {0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d}, + {0xc11470432dd78226, 0x8d382c5cfe5fc16c, 0xab8c17734267d9a5, 0x8cdb55aea6de4bfc}}, + {{0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147}, + {0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532}, + {0x2288a26657aa636b, 0x0bd5debf20ffc1db, 0xaddc1dd6256d7599, 0xf9c0b94592c70dd3}}, + {{0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5}, + {0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e}, + {0x03bea583a69b9b95, 0x2ddb4d283ed749ea, 0x9fca3636fa0446ed, 0xbd2856ed8bbd6054}}, + {{0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee}, + {0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097}, + {0x172a236056945247, 0x1a704e8221e6b823, 0x97eacd159ae7a05c, 0xe02293c4fcb587cf}}, + {{0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2}, + {0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58}, + {0x7104dc3ccd733465, 0x50bd5df822789116, 0xdf042523a2051869, 0xdbe1db94f94060ae}}, + {{0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2}, + {0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9}, + {0xbfdec8f10abf17fd, 0xf6ef290a5e0e2f5a, 0xb9cb5532a4f947f8, 0x95c619ca96bb0dca}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x738b38d787ce8f89, 0xb62658e24179a88d, 0x30738c9cf151316d, 0x49128c7f727275c9}, + {0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, 0xc6409d99f53eabc6, 0x606175f6332e25d2}, + {0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235}}, + {{0x96cd5640df90f3e7, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58}, + {0x1da1965774049e9d, 0xfbcd6ea198fe352b, 0xb1cbcd50cc5236a6, 0x1f5ec83d3f9846e2}, + {0x8efb23c3328ccb75, 0xaf42a207dd876ee9, 0x20fbdadc5dfae796, 0x241e246b06bf9f51}}, + {{0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097}, + {0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee}, + {0xe8d5dc9fa96bad93, 0xe58fb17dde1947dc, 0x681532ea65185fa3, 0x1fdd6c3b034a7830}}, + {{0x0a64e28c55dc18fe, 0xe3df9e993399ebdd, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e}, + {0x9c13a6a52dd8f7a9, 0x2dbb1f8c3efdcabf, 0x961e32405e08f7b5, 0x48c8a121bbe6c9e5}, + {0xfc415a7c59646445, 0xd224b2d7c128b615, 0x6035c9c905fbb912, 0x42d7a91274429fab}}, + {{0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, 0xff547cde6eb508cb, 0x6fed19dd10fcb532}, + {0xa9a48947933da5bc, 0x4a58920ec2e979ec, 0x96d8800013e5ac4c, 0x453692d74b48b147}, + {0xdd775d99a8559c6f, 0xf42a2140df003e24, 0x5223e229da928a66, 0x063f46ba6d38f22c}}, + {{0xd2d242895f536694, 0xca33a2c542939b2c, 0x986fada6c7ddb95c, 0x5a152c042f712d5d}, + {0x39843cb737346921, 0xa747fb0738c89447, 0xcb8d8031a245307e, 0x67810f8e6d82f068}, + {0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403}}, + {{0x857942f46c3cbe8e, 0xa1d364b14730c046, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2}, + {0xad23f6dae82354cb, 0x6962502ab6571a6d, 0x9b651636e38e37d1, 0x5cac5005d1a3312f}, + {0x8cc154cce9e39904, 0x5b3a040b84de6846, 0xc4d8a61cb1be5d6e, 0x40fb897bd8861f02}}, + {{0x84c5aa9062de37a1, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da}, + {0xe57ed8475ab10761, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b}, + {0xd1c101d50b813381, 0xdee60f1176ee6828, 0x0cb68893383f6409, 0x6183c565f6ff484a}}, + {{0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}, + {0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}, + {0x12ae6d19f3f8bb8b, 0xbd3ab1d28bbde2ef, 0xcad4b37d024a379b, 0xec16ffb57589799b}}, + {{0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}, + {0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}, + {0x4ef2db0197fa67b1, 0x8a8cf98d2450dc1a, 0xec98dac54ba853d6, 0xd0a64343794b8f5b}}, + {{0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}, + {0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}, + {0x56613f34e0f2fe0b, 0xf22e1033c5cb0851, 0xaa358ade2f63b1dd, 0xa02eb016a7145a15}}, + {{0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}, + {0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}, + {0x0cf958dca6b90e0e, 0x6de8e74a331a2682, 0xd7322db87e4b168a, 0xae350cf3903226f8}}, + {{0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}, + {0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}, + {0x93eb37166b77ab85, 0x7bc5a2999a512b1a, 0xe7e448c14329a50e, 0xc6726c1a3b39e0af}}, + {{0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}, + {0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}, + {0xf7473e06806d6c3f, 0x41988e342bbb5491, 0xdd1a9b9c66447fe8, 0x849229e1488d56aa}}, + {{0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}, + {0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}, + {0xf94e16f79cec6327, 0x5b6c25983a5fc132, 0x72883137529c76cd, 0xe0bd948fe479b0bb}}, + {{0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}, + {0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}, + {0x1f80b17515e8313a, 0xd02aeab9c5e03e02, 0xe8acdd02ce0d3f0e, 0xe05e2fe279e1a2ea}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x741d5a461e6bf9d6, 0x2305b3fc7777a581, 0xd45574a26474d3d9, 0x1926e1dc6401e0ff}, + {0xdb468549af3f666e, 0xd77fcf04f14a0ea5, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85}, + {0xe07f4e8aea17cea0, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15}}, + {{0xcc8055947d599832, 0x1e4656da37f15520, 0x99f6f7744e059320, 0x773563bc6a75cf33}, + {0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5}, + {0x06b1e90863139cb3, 0xa493da67c5a03ecd, 0x8d77cec8ad638932, 0x1f426b701b864f44}}, + {{0xefc9264c41911c01, 0xf1a3b7b817a22c25, 0x5875da6bf30f1447, 0x4e1af5271d31b090}, + {0xf17e35c891a12552, 0xb76b8153575e9c76, 0xfa83406f0d9b723e, 0x0b76bb1b3fa7e438}, + {0x08b8c1f97f92939b, 0xbe6771cbd444ab6e, 0x22e5646399bb8017, 0x7b6dd61eb772a955}}, + {{0xb7adc1e850f33d92, 0x7998fa4f608cd5cf, 0xad962dbd8dfc5bdb, 0x703e9bceaf1d2f4f}, + {0x5730abf9ab01d2c7, 0x16fb76dc40143b18, 0x866cbe65a0cbb281, 0x53fa9b659bff6afe}, + {0x6c14c8e994885455, 0x843a5d6665aed4e5, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50}}, + {{0x1c4bd16733e248f3, 0xbd9e128715bf0a5f, 0xd43f8cf0a10b0376, 0x53b09b5ddf191b13}, + {0xc3877c60d2e7e3f2, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577}, + {0xf306a7235946f1cc, 0x921718b5cce5d97d, 0x28cdd24781b4e975, 0x51caf30c6fcdd907}}, + {{0xa60ba7427674e00a, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa}, + {0x737af99a18ac54c7, 0x903378dcc51cb30f, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a}, + {0xa99ec0cb1f0d01cf, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea}}, + {{0xb5dc2ddf2845ab2c, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1}, + {0x3c42fe5ebf93cb8e, 0xbedfa85136d4565f, 0xe0f0859e884220e8, 0x7dd73f960725d128}, + {0xb10d24fe68059829, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4}}, + {{0x83847d429917135f, 0xad1b911f567d03d7, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a}, + {0x7041d560b691c301, 0x85201b3fadd7e71e, 0x16c2e16311335585, 0x2aa55e3d010828b1}, + {0xed5192e60c07444f, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664}}, + {{0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d}, + {0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8}, + {0x10a30eff30481566, 0xdd7689cc5e34bd53, 0x2b31f3ab310d7a1d, 0xcfbf73fb75eb95aa}}, + {{0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff}, + {0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a}, + {0x0da953135bc92086, 0xef749e9751962917, 0xdf26793494a2fc93, 0x9aa6a846011d50af}}, + {{0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00}, + {0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0}, + {0xd2660620eb03b6ba, 0x893349f33bb6601a, 0x5becd3441a30fffc, 0xc06c27dcab0fff15}}, + {{0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29}, + {0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d}, + {0x2569444c5312c82e, 0x85dbdc4a16df7315, 0xdb33a3cfc751451d, 0xaf3ca95023a251d0}}, + {{0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6}, + {0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7}, + {0x75af8881e990fcc0, 0xf984c60ef0485cd7, 0xe6da3659fef04289, 0x92064a8a338bf6fa}}, + {{0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059}, + {0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89}, + {0xad1efa09ebe9c880, 0x136850c97a54145b, 0xd9194af9dc5983c9, 0xa30f17a90c2b04fe}}, + {{0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb}, + {0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd}, + {0xdd4e5a75164f7e57, 0x026a2f8e3ea3c774, 0x567edc897af5fae8, 0xccc7b3454480cca1}}, + {{0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70}, + {0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5}, + {0x7489856cdfb12851, 0x89d03534605f51d5, 0x88e014339231b778, 0xcbcf9dea700fa04c}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xcbb5b5556c032bff, 0xdf7191b729297a3a, 0xc1ff7326aded81bb, 0x71ade8bb68be03f5}, + {0x1e6284c5806b467c, 0xc5f6997be75d607b, 0x8b67d958b378d262, 0x3d88d66a81cd8b70}, + {0x8b767a93204ed789, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3}}, + {{0xe05da1a7e1f5bf49, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd}, + {0xfce219072a7b31b4, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb}, + {0x22b1a58ae9b08183, 0xfd95d071c15c388b, 0xa9812376850a0517, 0x33384cbabb7f335e}}, + {{0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, 0xeb53349c5431d6de, 0x5278b38f6b879c89}, + {0x33bc627a26218b8d, 0xea80b21fc7a80c61, 0x9458b12b173e9ee6, 0x076247be0e2f3059}, + {0x52e105f61416375a, 0xec97af3685abeba4, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01}}, + {{0xf6c968731ae8cab4, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7}, + {0xbeaece313db342a8, 0xcba3635b842db7ee, 0xe88c6620817f13ef, 0x1b9438aa4e76d5c6}, + {0x8a50777e166f031a, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905}}, + {{0x42c1192927f6bdcf, 0x8f91917a403d61ca, 0xdc1c5a668b9e1f61, 0x1596047804ec0f8d}, + {0xecdfc35b48cade41, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29}, + {0xda96bbb3aced37ac, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f}}, + {{0x09dcbf4341c30318, 0xeeba061183181dce, 0xc179c0cedc1e29a1, 0x1dbf7b89073f35b0}, + {0xcfed9cdf1b31b964, 0xf486a9858ca51af3, 0x14897265ea8c1f84, 0x784a53dd932acc00}, + {0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, 0xa4132cbbe5cf0003, 0x3f93d82354f000ea}}, + {{0x8183e7689e04ce85, 0x678fb71e04465341, 0xad92058f6688edac, 0x5da350d3532b099a}, + {0xeaac12d179e14978, 0xff923ff3bbebff5e, 0x4af663e40663ce27, 0x0fd381a811a5f5ff}, + {0xf256aceca436df54, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50}}, + {{0xaea8b07fa902030f, 0xf88c766af463d143, 0x15b083663c787a60, 0x08eab1148267a4a8}, + {0xbdc1409bd002d0ac, 0x66660245b5ccd9a6, 0x82317dc4fade85ec, 0x02fe934b6ad7df0d}, + {0xef5cf100cfb7ea74, 0x22897633a1cb42ac, 0xd4ce0c54cef285e2, 0x30408c048a146a55}}, + {{0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}, + {0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}, + {0x2d2aaeed1d259512, 0x1642fcce4e17ae12, 0x69f8b92271398d9d, 0xfa6ee46091083a2f}}, + {{0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}, + {0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}, + {0x49370fb5209d5c1a, 0xc10fff10f8925ba2, 0x636346a7b60f2d56, 0xe33c80bcbbe4d051}}, + {{0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}, + {0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}, + {0x3dfdcd325d4b1a86, 0x612f02bdeea2e780, 0xd1544b41822b8626, 0xfd38f40ad49713b3}}, + {{0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}, + {0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}, + {0xc0b50cba549368be, 0x1d77148d66bc8ce0, 0xcca69575fcbbe792, 0x84b6e8ff81299d6c}}, + {{0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}, + {0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}, + {0xd33ec740d5ccf9e5, 0xb7a7c0705d16d93c, 0xf7c54e5daab62d14, 0xcd035591b9785c93}}, + {{0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}, + {0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}, + {0x2e10aad74d67860f, 0x22e551c32b816f6d, 0xed81fbbde760dcad, 0xeaa694c51a8efe0e}}, + {{0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}, + {0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}, + {0x82f6027295651091, 0x0f119f41a4c246f4, 0xb3de4ad3ae61402b, 0x9fee55203aba6be2}}, + {{0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}, + {0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}, + {0x46fc8ee9d6840b4d, 0x562ec4dd2b0f97cb, 0x1e68eaa8b9694239, 0xd3075b176e2a17ca}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x739d8845832fcedb, 0xfa38d6c9ae6bf863, 0x32bc0dcab74ffef7, 0x73937e8814bce45e}, + {0xbb2e00c9193b877f, 0xece3a890e0dc506b, 0xecf3b7c036de649f, 0x5f46040898de9e1a}, + {0xb9037116297bf48d, 0xa9d13b22d4f06834, 0xe19715574696bdc6, 0x2cf8a4e891d5e835}}, + {{0x6d93fd8707110f67, 0xdd4c09d37c38b549, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09}, + {0x2cb5487e17d06ba2, 0x24d2381c3950196b, 0xd7659c8185978a30, 0x7a6f7f2891d6a4f6}, + {0x7d09fd8d6a9aef49, 0xf0ee60be5b3db90b, 0x4c21b52c519ebfd4, 0x6011aadfc545941d}}, + {{0x5f67926dcf95f83c, 0x7c7e856171289071, 0xd6a1e7f3998f7a5b, 0x6fc5cc1b0b62f9e0}, + {0x63ded0c802cbf890, 0xfbd098ca0dff6aaa, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e}, + {0xd1ef5528b29879cb, 0xdd1aae3cd47e9092, 0x127e0442189f2352, 0x15596b3ae57101f1}}, + {{0x462739d23f9179a2, 0xff83123197d6ddcf, 0x1307deb553f2148a, 0x0d2237687b5f4dda}, + {0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138}, + {0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c}}, + {{0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, 0xaac014de22efe4a3, 0x4627e9cefebd6a5c}, + {0x3207a4732787ccdf, 0x17e31908f213e3f8, 0xd5b2ecd7f60d964e, 0x746f6336c2600be9}, + {0x3f4af345ab6c971c, 0xe288eb729943731f, 0x33596a8a0344186d, 0x7b4917007ed66293}}, + {{0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b}, + {0x54341b28dd53a2dd, 0xaa17905bdf42fc3f, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d}, + {0xc20232cda2b4e554, 0x9ed0fd42115d187f, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c}}, + {{0xa287ec4b5d0b2fbb, 0x415c5790074882ca, 0xe044a61ec1d0815c, 0x26334f0a409ef5e0}, + {0xace532bf458d72e1, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03}, + {0xb6c8f04adf62a3c0, 0x3ef000ef076da45d, 0x9c9cb95849f0d2a9, 0x1cc37f43441b2fae}}, + {{0x508f565a5cc7324f, 0xd061c4c0e506a922, 0xfb18abdb5c45ac19, 0x6c6809c10380314a}, + {0xd76656f1c9ceaeb9, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838}, + {0xd2d55112e2da6ac8, 0xe9bd0331b1e851ed, 0x960746dd8ec67262, 0x05911b9f6ef7c5d0}}, + {{0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f}, + {0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142}, + {0xc5fe489b6912e617, 0xce1ff54f12cd8dcf, 0xadf577a87c35ea4e, 0xf9554678a5334138}}, + {{0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b}, + {0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21}, + {0x7ebe18d0d2b221f0, 0x191501679d39f837, 0xdc3d7ba7a8c3502f, 0xb946b890b0068cb9}}, + {{0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8}, + {0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a}, + {0xe7c15481875eae2f, 0x44166f3666f6c89c, 0x008e8291b5381cca, 0xb3a3224cda0c6077}}, + {{0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93}, + {0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9}, + {0x99645c4853ca1e7a, 0xd13308c0457bdfa9, 0xe513e0e83f7fb0f8, 0xf26943fce7a90b18}}, + {{0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f}, + {0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c}, + {0x5ab22f8bd6b3f446, 0x0aa2b94720e70049, 0x0f90133a72517c99, 0xa779a8997e6f2e9a}}, + {{0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75}, + {0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e}, + {0x88371eba881de73e, 0x5c1b909500663bba, 0xcebb203792ccacbc, 0xc569aa6183bde956}}, + {{0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d}, + {0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea}, + {0x23201f5fd33e217a, 0xfcd99a00ae3aa8a4, 0xd3f3cd0ef8c54114, 0x9577dfeb328479f9}}, + {{0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982}, + {0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87}, + {0x337fdb97083ca94b, 0x6216457de668b34c, 0x5448dd634a47ec9f, 0xbb1dfe859041459d}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xe9dcd756b637ff2d, 0xec4c348fc987f0c4, 0xced59285f3fbc7b7, 0x3305354793e1ea87}, + {0x01c18980c5fe9f94, 0xcd656769716fd5c8, 0x816045c3d195a086, 0x6e2b7f3266cc7982}, + {0xcc802468f7c3568f, 0x9de9ba8219974cb3, 0xabb7229cb5b81360, 0x44e2017a6fbeba62}}, + {{0xc4c2a74354dab774, 0x8e5d4c3c4eaf031a, 0xb76c23d242838f17, 0x749a098f68dce4ea}, + {0x87f82cf3b6ca6ecd, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d}, + {0xdcdfe0a02cc1de60, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606}}, + {{0xa52a92fea4747fb5, 0xdc12a4491fa5ab89, 0xd82da94bb847a4ce, 0x4d77edce9512cc4e}, + {0xd111d17caf4feb6e, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75}, + {0x77c8e14577e2189c, 0xa3e46f6aff99c445, 0x3144dfc86d335343, 0x3a96559e7c4216a9}}, + {{0x12550d37f42ad2ee, 0x8b78e00498a1fbf5, 0x5d53078233894cb2, 0x02c84e4e3e498d0c}, + {0x4493896880baaa52, 0x4c98afc4f285940e, 0xef4aa79ba45448b6, 0x5278c510a57aae7f}, + {0xa54dd074294c0b94, 0xf55d46b8df18ffb6, 0xf06fecc58dae8366, 0x588657668190d165}}, + {{0xd47712311aef7117, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9}, + {0xbf5834f03de25cc3, 0xb887c8aed6815496, 0x5105221a9481e892, 0x6760ed19f7723f93}, + {0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7}}, + {{0x3318be7775c52d82, 0x4cb764b554d0aab9, 0xabcf3d27cc773d91, 0x3bf4d1848123288a}, + {0xb1d534b0cc7505e1, 0x32cd003416c35288, 0xcb36a5800762c29d, 0x5bfe69b9237a0bf8}, + {0x183eab7e78a151ab, 0xbbe990c999093763, 0xff717d6e4ac7e335, 0x4c5cddb325f39f88}}, + {{0xc0f6b74d6190a6eb, 0x20ea81a42db8f4e4, 0xa8bd6f7d97315760, 0x33b1d60262ac7c21}, + {0x57750967e7a9f902, 0x2c37fdfc4f5b467e, 0xb261663a3177ba46, 0x3a375e78dc2d532b}, + {0x8141e72f2d4dddea, 0xe6eafe9862c607c8, 0x23c28458573cafd0, 0x46b9476f4ff97346}}, + {{0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, 0xe587ff910114db88, 0x37130f364785a142}, + {0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f}, + {0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7}}, + {{0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}, + {0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}, + {0x0869e6285d927f50, 0x44e02b61e261ea92, 0x8c283c93245e20d8, 0xd94bb326e0d78882}}, + {{0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}, + {0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}, + {0x67d1007beee68b8c, 0x0696a169d4f8b8db, 0x3a753eb04036ac04, 0xc3ce41e4c960e30a}}, + {{0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}, + {0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}, + {0xa2d7eb5465f1ad83, 0x6f70df7b36354c03, 0x50350a77a4d2e135, 0xe34b4a59870782ee}}, + {{0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}, + {0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}, + {0x62db38ec196cd88c, 0xa09c7a8897242c8a, 0x8fadaa9f14754c65, 0x97bc95f99a363b32}}, + {{0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}, + {0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}, + {0x210216c602a67907, 0x0bd8d376aef5c7f3, 0x48d45bf844cee646, 0x9caaf5ccb5dab20b}}, + {{0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}, + {0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}, + {0x5f55559af205a2f3, 0x063b61d5b74ab873, 0xb0f633828ffc8da4, 0xc8c352c5d9f6e541}}, + {{0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}, + {0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}, + {0xfeb4a13cde1a3f10, 0xb034963628e6405d, 0xb1a0e3e78affdc5f, 0xe3f92161aa12537f}}, + {{0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}, + {0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}, + {0xc9588f45c48c42d2, 0x9db510f75c5040f3, 0xa8c800674bf6b90d, 0x98a0b21ecc7e8b62}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xc1339983f5df0ebb, 0xc0f3758f512c4cac, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62}, + {0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17}, + {0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d}}, + {{0x0e2c52036b1782fc, 0x64816c816cad83b4, 0xd0dcbdd96964073e, 0x13d99df70164c520}, + {0xa12ff6d93bdab31d, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43}, + {0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80}}, + {{0x990f7ad6a33ec4e2, 0x6608f938be2ee08e, 0x9ca143c563284515, 0x4cf38a1fec2db60d}, + {0xffd52b40ff6d69aa, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d}, + {0xa0aaaa650dfa5ce7, 0xf9c49e2a48b5478c, 0x4f09cc7d7003725b, 0x373cad3a26091abe}}, + {{0xb294634d82c9f57c, 0x1fcbfde124934536, 0x9e9c4db3418cdb5a, 0x0040f3d9454419fc}, + {0xf1bea8fb89ddbbad, 0x3bcb2cbc61aeaecb, 0x8f58a7bb1f9b8d9d, 0x21547eda5112a686}, + {0xdefde939fd5986d3, 0xf4272c89510a380c, 0xb72ba407bb3119b9, 0x63550a334a254df4}}, + {{0x6507d6edb569cf37, 0x178429b00ca52ee1, 0xea7c0090eb6bd65d, 0x3eea62c7daf78f51}, + {0x9bba584572547b49, 0xf305c6fae2c408e0, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a}, + {0x9d24c713e693274e, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd}}, + {{0xbc0235e8202f3f27, 0xc75c00e264f975b0, 0x91a4e9d5a38c2416, 0x17b6e7f68ab789f9}, + {0x1e56d317e820107c, 0xc5266844840ae965, 0xc1e0a1c6320ffc7a, 0x5373669c91611472}, + {0x5d2814ab9a0e5257, 0x908f2084c9cab3fc, 0xafcaf5885b2d1eca, 0x1cb4b5a678f87d11}}, + {{0xb664c06b394afc6c, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2}, + {0x6b74aa62a2a007e7, 0xf311e0b0f071c7b1, 0x5707e438000be223, 0x2dc0fd2d82ef6eac}, + {0x982eff841119744e, 0xf9695e962b074724, 0xc58ac14fbfc953fb, 0x3c31be1b369f1cf5}}, + {{0xb0f4864d08948aee, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb}, + {0xc168bc93f9cb4272, 0xaeb8711fc7cedb98, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb}, + {0xf79619d7a26d808a, 0xbb1fd49e1d9e156d, 0x73d7c36cdba1df27, 0x26b44cd91f28777d}}, + {{0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748}, + {0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8}, + {0x38fb00b6bd4244f4, 0xa1de521d4d21e086, 0x16a24c0ca9ad0527, 0xf7dd4ac870f7143e}}, + {{0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7}, + {0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602}, + {0x3e2ad7addff995a2, 0x6a9fc1adca8f510c, 0x7cd9a658dd9475b2, 0xa22976f6e0711236}}, + {{0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2}, + {0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d}, + {0xdcdc2558ba6a06f6, 0x219773747a85414b, 0xc03b7169e3a6cd91, 0xf4d18c35ea364745}}, + {{0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89}, + {0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45}, + {0xb07cc0951996682e, 0x97b689d5c9e7c65b, 0x967a213e68f54ada, 0xacfba176234e0ab9}}, + {{0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd}, + {0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0}, + {0xedbf86155ab30d20, 0x28db9a14ffe4d918, 0x97bc430236850802, 0xfadb4bd4aa1532fd}}, + {{0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d}, + {0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947}, + {0x11ccd2b21c4bd4d0, 0x27b1a5d4e95b9fe3, 0x87dbc788f8745c1b, 0x8812e14be7b11bc8}}, + {{0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9}, + {0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8}, + {0x0c98702f1336f486, 0x0ffeba64edfbca66, 0xd98da043c8a74764, 0xbcda1b558c58e651}}, + {{0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579}, + {0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad}, + {0x26056e8e7cf8a585, 0xb424a52d94ff6023, 0x87d652d329c210f1, 0xf8703ab68a02c788}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad}, + {0xaf44842db0285f37, 0x8753189047efc8df, 0x9574e091f820979a, 0x0e378d6069615579}, + {0xd9fa917183075a55, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877}}, + {{0x87dfbd1428878f2d, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8}, + {0xe2004b5bb833a98a, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9}, + {0xf3678fd0ecc90b54, 0xf001459b12043599, 0x26725fbc3758b89b, 0x4325e4aa73a719ae}}, + {{0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947}, + {0xed24629acf69f59d, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d}, + {0xee332d4de3b42b0a, 0xd84e5a2b16a4601c, 0x78243877078ba3e4, 0x77ed1eb4184ee437}}, + {{0xbfd4e13f201839a0, 0xaeefffe23e3df161, 0xb65b04f06b5d1fe3, 0x52e085fb2b62fbc0}, + {0x185d43f89e92ed1a, 0xb04a1eeafe4719c6, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd}, + {0x124079eaa54cf2ba, 0xd72465eb001b26e7, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02}}, + {{0xfd0d5dbee45447b0, 0x6cec351a092005ee, 0x99a47844567579cb, 0x59d242a216e7fa45}, + {0xbc18dcad9b829eac, 0x23ae7d28b5f579d0, 0xc346122a69384233, 0x1a6110b2e7d4ac89}, + {0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546}}, + {{0xcb8bb346d75353db, 0xfcfcb24bae511e22, 0xcba48d40d50ae6ef, 0x26e3bae5f4f7cb5d}, + {0x84da3cde8d45fe12, 0xbd42c218e444e2d2, 0xa85196781f7e3598, 0x7642c93f5616e2b2}, + {0x2323daa74595f8e4, 0xde688c8b857abeb4, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba}}, + {{0xd6bb4428c17f5026, 0x9eb27223fb5a9ca7, 0xe37ba5031919c644, 0x21ce380db59a6602}, + {0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, 0xd5c55245db3de39f, 0x015e68c1476a4af7}, + {0xc1d5285220066a38, 0x95603e523570aef3, 0x832659a7226b8a4d, 0x5dd689091f8eedc9}}, + {{0xcbac84debfd3c856, 0x1624c348b35ff244, 0xb7f88dca5d9cad07, 0x3b0e574da2c2ebe8}, + {0x1d022591a5313084, 0xca2d4aaed6270872, 0x86a12b852f0bfd20, 0x56e6c439ad7da748}, + {0xc704ff4942bdbae6, 0x5e21ade2b2de1f79, 0xe95db3f35652fad8, 0x0822b5378f08ebc1}}, + {{0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}, + {0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}, + {0x034b9a7629c4a0a1, 0xa35195c0a834309e, 0x01453d2d6ac505fa, 0xe3f05fe5c9c8ebc9}}, + {{0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}, + {0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}, + {0xd5abe1123fea0717, 0xee5b01818396c083, 0x0f5099ecb15d8729, 0xaba4a7a2eb225f6b}}, + {{0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}, + {0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}, + {0x337a072612034c70, 0xdd433d70c8b91a06, 0x1b621cc7061a2c32, 0xb7f5a1043ec1d233}}, + {{0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}, + {0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}, + {0x77f4aa1aa53762b1, 0xeb7cdbe0ba5f589c, 0xc2c910203d1893e0, 0xf750a487b1b45217}}, + {{0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}, + {0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}, + {0xbec1e5e832197e50, 0xa8ea925612965f7b, 0xd340d970b935334e, 0x94cb41643cc53a0d}}, + {{0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}, + {0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}, + {0x7aacd2af6ccb4c26, 0xb902eeb49f7e9a8c, 0x33a0a0cfbda37c8a, 0xbedd6a5d478054a3}}, + {{0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}, + {0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}, + {0x087b738a1aea4990, 0x5a6afe4524b56fc7, 0x3df2cec0c08ae4af, 0xe65e1cac3f51d117}}, + {{0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}, + {0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}, + {0x349d509578991160, 0x993413fbaaac32f1, 0xa77ffec7f0f41b4a, 0xf719716009d31d15}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0x51f048478f387475, 0xb25dbcf49cbecb3c, 0x9aab1244d99f2055, 0x2c709e6c1c10a5d6}, + {0xe1b7f29362730383, 0x4b5279ffebca8a2c, 0xdafc778abfd41314, 0x7deb10149c72610f}, + {0xcb62af6a8766ee7a, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea}}, + {{0x34ad500a4bc130ad, 0x8d38db493d0bd49c, 0xa25c3d98500a89be, 0x2f1f3f87eeba3b09}, + {0x2f2d09d50ab8f2f9, 0xacb9218dc55923df, 0x4a8f342673766cb9, 0x4cb13bd738f719f5}, + {0xf7848c75e515b64a, 0xa59501badb4a9038, 0xc20d313f3f751b50, 0x19a1e353c0ae2ee8}}, + {{0x7d1c7560bafa05c3, 0xb3e1a0a0c6e55e61, 0xe3529718c0d66473, 0x41546b11c20c3486}, + {0xb42172cdd596bdbd, 0x93e0454398eefc40, 0x9fb15347b44109b5, 0x736bd3990266ae34}, + {0x85532d509334b3b4, 0x46fd114b60816573, 0xcc5f5f30425c8375, 0x412295a2b87fab5c}}, + {{0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34}, + {0x2e655261e293eac6, 0x845a92032133acdb, 0x460975cb7900996b, 0x0760bb8d195add80}, + {0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2}}, + {{0xf3df2f643a78c0b2, 0x4c3e971ef22e027c, 0xec7d1c5e49c1b5a3, 0x2012c18f0922dd2d}, + {0x11fc69656571f2d3, 0xc6c9e845530e737a, 0xe33ae7a2d4fe5035, 0x01b9c7b62e6dd30b}, + {0x880b55e55ac89d29, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8}}, + {{0x283499dc881f2533, 0x9d0525da779323b6, 0x897addfb673441f4, 0x32b79d71163a168d}, + {0xe27314d289cc2c4b, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e}, + {0xcc85f8d9edfcb36a, 0x22bcc28f3746e5f9, 0xe49de338f9e5d3cd, 0x480a5efbc13e2dcc}}, + {{0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31}, + {0xb6614ce442ce221f, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06}, + {0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, 0xf0af66134ea278d6, 0x545b585d14dda094}}, + {{0x67bf275ea0d43a0f, 0xade68e34089beebe, 0x4289134cd479e72e, 0x0f62f9c332ba5454}, + {0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071}, + {0xfcb46589d63b5f39, 0x5cae6a3f57cbcf61, 0xfebac2d2953afa05, 0x1c0fa01a36371436}}, + {{0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18}, + {0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9}, + {0xdcd5fc3ca3da7135, 0x790dc5d39434f30e, 0xc25272f2d1bbde99, 0xfb576cc3548979d4}}, + {{0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec}, + {0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2}, + {0x8611938ddc1a4a93, 0x90a0af897ccf2986, 0x128c1e1692752316, 0xd83c25e1e27333fc}}, + {{0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51}, + {0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95}, + {0xb7cd66addec03655, 0xef7830f2c975e8b9, 0x71ad9e4e993ea55a, 0xd2a4d27bd12db3de}}, + {{0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892}, + {0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac}, + {0x667fc5d8377034a0, 0xcba59876d8a13f4f, 0xba68762f0093d41a, 0x9d077d9ae18f574d}}, + {{0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1}, + {0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c}, + {0x90dfc22abfa4b498, 0xcd8139fbef4dbaf6, 0x63cb8dcf53d577b9, 0x8821d603ee001495}}, + {{0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435}, + {0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080}, + {0x4dddd7e6f2910928, 0x56b5994db931b405, 0xb93e5885b0f49338, 0xbdc93300148cc730}}, + {{0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00}, + {0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9}, + {0x63b61caa366be50a, 0x468cb5218bb6707b, 0xbe3c012f9999c1a3, 0xf13012071718ef4c}}, + {{0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef}, + {0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183}, + {0xcd8af89c4fd70b4e, 0xf9fdf8bfaa95f9a0, 0x2ac427ed3cb6a4a7, 0xf78f936479a0af72}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xe7547449bc7cd692, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183}, + {0xc11ee5e854c53fae, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef}, + {0x32750763b028f48c, 0x06020740556a065f, 0xd53bd812c3495b58, 0x08706c9b865f508d}}, + {{0xf37ca2ab3d343dff, 0x1a8c6a2d80abc617, 0x8e49e035d4ccffca, 0x48b46beebaa1d1b9}, + {0xcc991b4138b41246, 0x243b9c526f9ac26b, 0xb9ef494db7cbabbd, 0x5fba433dd082ed00}, + {0x9c49e355c9941ad0, 0xb9734ade74498f84, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3}}, + {{0x76430f9f9cd470d9, 0xb62acc9ba42f6008, 0x1898297c59adad5e, 0x7789dd2db78c5080}, + {0x744f7463e9403762, 0xf79a8dee8dfcc9c9, 0x163a649655e4cde3, 0x3b61788db284f435}, + {0xb22228190d6ef6b2, 0xa94a66b246ce4bfa, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf}}, + {{0x8497404d0d55e274, 0x6c6663d9c4ad2b53, 0xec2fb0d9ada95734, 0x2617e120cdb8f73c}, + {0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1}, + {0x6f203dd5405b4b42, 0x327ec60410b24509, 0x9c347230ac2a8846, 0x77de29fc11ffeb6a}}, + {{0xb0ac57c983b778a8, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac}, + {0x835e138fecced2ca, 0x8c9eaf13ea963b9a, 0xc95fbfc0b2160ea6, 0x575e66f3ad877892}, + {0x99803a27c88fcb3a, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2}}, + {{0x085ae2c759ff1be4, 0x149145c93b0e40b7, 0xc467e7fa7ff27379, 0x4eeecf0ad5c73a95}, + {0x6d822986698a19e0, 0xdc9821e174d78a71, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51}, + {0x48329952213fc985, 0x1087cf0d368a1746, 0x8e5261b166c15aa5, 0x2d5b2d842ed24c21}}, + {{0x02cfebd9ebd3ded1, 0xd45b217739021974, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2}, + {0x5eb7d13d196ac533, 0x377234ecdb80be2b, 0xe144cffc7cf5ae24, 0x5226bcf9c441acec}, + {0x79ee6c7223e5b547, 0x6f5f50768330d679, 0xed73e1e96d8adce9, 0x27c3da1e1d8ccc03}}, + {{0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9}, + {0x28302e71630ef9f6, 0xc2d4a2032b64cee0, 0x090820304b6292be, 0x5fca747aa82adf18}, + {0x232a03c35c258ea5, 0x86f23a2c6bcb0cf1, 0x3dad8d0d2e442166, 0x04a8933cab76862b}}, + {{0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}, + {0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}, + {0x1c546f2fbd37bd74, 0x147b71f080e6ab81, 0xdafc5e2f9a5b6846, 0xf0106eee6e2076a0}}, + {{0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}, + {0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}, + {0xda2bb7cd846a2a97, 0x8f2c7cff5ccbf0e2, 0x21e3ace39f1e3ad4, 0xd8dddbaed382161b}}, + {{0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}, + {0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}, + {0x14f5a2739c02d510, 0x2dd43e99d196b100, 0xd8dc0c9107344fc5, 0x8f0fd6130f37ece0}}, + {{0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}, + {0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}, + {0xc74b36f10c283dca, 0xcf7191db4852fbf3, 0xc79f260e4818c1dc, 0xa6a89f2a4af70a68}}, + {{0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}, + {0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}, + {0xee72e76fbe1cd244, 0x46121c3d27cea7b7, 0xe154bd8e27cdba26, 0xb5c69e1d36e75eab}}, + {{0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}, + {0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}, + {0x1d2e43996f01c6d9, 0xb34ab5e75f66852a, 0x68e296eb507b9f2b, 0xaa62afb08094841b}}, + {{0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}, + {0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}, + {0xb342cb16c175ca2b, 0xd1f87ebba77817e9, 0xe6ce63890d654f54, 0xda1e801b2af53ec4}}, + {{0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}, + {0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}, + {0x5ffc014246417cea, 0xdf763e50c5bb536f, 0x07b6606ee6ab0571, 0xe045de7510bf54bd}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xd2c604b622943dff, 0xbc8cbece44cfb3a0, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf}, + {0x69082b0e8c936a50, 0xf9c9a035c1dac5b6, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140}, + {0xa003febdb9be82f0, 0x2089c1af3a44ac90, 0xf8499f911954fa8e, 0x1fba218aef40ab42}}, + {{0xab549448fac8f53e, 0x81f6e89a7ba63741, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42}, + {0x4f3e57043e7b0194, 0xa81d3eee08daaf7f, 0xc839c6ab99dcdef1, 0x6c535d13ff7761d5}, + {0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b}}, + {{0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351}, + {0x915f7ff576f121a7, 0xc34a32272fcd87e3, 0xccba2fde4d1be526, 0x6bba828f8969899b}, + {0xe2d1bc6690fe3901, 0x4cb54a18a0997ad5, 0x971d6914af8460d4, 0x559d504f7f6b7be4}}, + {{0xa7738378b3eb54d5, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217}, + {0x9c4891e7f6d266fd, 0x0744a19b0307781b, 0x88388f1d6061e23b, 0x123ea6a3354bd50e}, + {0x118d189041e32d96, 0xb9ede3c2d8315848, 0x1eab4271d83245d9, 0x4a3961e2c918a154}}, + {{0x71dc3be0f8e6bba0, 0xd6cef8347effe30a, 0xa992425fe13a476a, 0x2cd6bce3fb1db763}, + {0x0327d644f3233f1e, 0x499a260e34fcf016, 0x83b5a716f2dab979, 0x68aceead9bd4111f}, + {0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597}}, + {{0x6129bfe104aa6397, 0x8f960008a4a7fccb, 0x3f8bc0897d909458, 0x709fa43edcb291a9}, + {0x882acbebfd022790, 0x89af3305c4115760, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b}, + {0xeb0a5d8c63fd2aca, 0xd22bc1662e694eff, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f}}, + {{0x461307b32eed3e33, 0xae042f33a45581e7, 0xc94449d3195f0366, 0x0b7d5d8a6c314858}, + {0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1}, + {0x25d448327b95d543, 0x70d38300a3340f1d, 0xde1c531c60e1c52b, 0x272224512c7de9e4}}, + {{0x1abc92af49c5342e, 0xffeed811b2e6fad0, 0xefa28c8dfcc84e29, 0x11b5df18a44cc543}, + {0xbf7bbb8a42a975fc, 0x8c5c397796ada358, 0xe27fc76fcdedaa48, 0x19735fd7f6bc20a6}, + {0xe3ab90d042c84266, 0xeb848e0f7f19547e, 0x2503a1d065a497b9, 0x0fef911191df895f}}, + {{0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54}, + {0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1}, + {0x62b0d8fb997672d0, 0xc2f67866f500c085, 0x2f610c9d982545ba, 0x889ebaa184e39963}}, + {{0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b}, + {0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f}, + {0x42b1561ef0ac3b24, 0xe98c23a07536e5eb, 0x5707e5b1d533e545, 0xcc56d586dbccd5da}}, + {{0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad}, + {0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24}, + {0x1d897db5e08cc8bb, 0x80830fe3b0a498c9, 0x81dfe01cfb05b918, 0x87a5c95ca87f7369}}, + {{0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b}, + {0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0}, + {0xde6108ec27ea4519, 0x0ebeb9a2b7a41da3, 0x92abb833b1aec3ae, 0xe8b6d941a10bbc6c}}, + {{0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363}, + {0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48}, + {0x5093b558ad06ed21, 0xa199a09327988f37, 0xb3ca537c5c3732a7, 0xd485d63fef5a7581}}, + {{0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f}, + {0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6}, + {0xa4264b89c9d917be, 0x766996c9435fd122, 0xf5bee6c29e0f884c, 0xcf685dbdff31ab8e}}, + {{0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe}, + {0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9}, + {0x37c35c1c6f454278, 0x7f121c98fd6e37cc, 0x377fc7332c86ff3b, 0xd3a03fdce13ce05e}}, + {{0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa}, + {0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1}, + {0x130b91ad85457483, 0xea5f73b8742e9b84, 0x850e3959a08f9010, 0x9cba05870fc5cf2a}}, + {{0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}, + {0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000}}, + {{0xb1507ca1ab1c6eb9, 0xbd448f3e16b687b3, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1}, + {0x6ab5dcb85b1c16b7, 0x94c0fce83c7b27a5, 0xa4b11c1a735517be, 0x499238d0ba0eafaa}, + {0xecf46e527aba8b57, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5}}, + {{0xdf02f95f1015e7a1, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9}, + {0x93d3cbe9bdd8f0a4, 0xdb152c1bfd177302, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe}, + {0xc83ca3e390babd62, 0x80ede3670291c833, 0xc88038ccd37900c4, 0x2c5fc0231ec31fa1}}, + {{0xfeba911717038b4f, 0xe5123721c9deef81, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6}, + {0xc422e4d102456e65, 0x87414ac1cad47b91, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f}, + {0x5bd9b4763626e81c, 0x89966936bca02edd, 0x0a41193d61f077b3, 0x3097a24200ce5471}}, + {{0x57427734c7f8b84c, 0xf141a13e01b270e9, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48}, + {0xa162e7246695c486, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363}, + {0xaf6c4aa752f912b9, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e}}, + {{0xc4007f77d0c1cec3, 0x8d1020b6bac492f8, 0x32ec29d57e69daaf, 0x599408759d95fce0}, + {0x33810a23bf00086e, 0xafce925ee736ff7c, 0x3d60e670e24922d4, 0x11ce9e714f96061b}, + {0x219ef713d815bac1, 0xf141465d485be25c, 0x6d5447cc4e513c51, 0x174926be5ef44393}}, + {{0xb5deb2f9fc5bd5bb, 0x92daa72ae1d810e1, 0xafc4cfdcb72a1c59, 0x497d78813fc22a24}, + {0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, 0x8fd24ecf07382c8c, 0x6fa42ead06d8e1ad}, + {0xe276824a1f73371f, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96}}, + {{0x825fbdfd63014d2b, 0xc852369c6ca7578b, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f}, + {0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b}, + {0xbd4ea9e10f53c4b6, 0x1673dc5f8ac91a14, 0xa8f81a4e2acc1aba, 0x33a92a7924332a25}}, + {{0x9dd1f49927996c02, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1}, + {0x7ba95ba0218f2ada, 0xcff42287330fb9ca, 0xdada496d56c6d907, 0x5380c296f4beee54}, + {0x9d4f270466898d0a, 0x3d0987990aff3f7a, 0xd09ef36267daba45, 0x7761455e7b1c669c}}}; diff --git a/src/crypto/ecops64/ecops64.asm b/src/crypto/ecops64/ecops64.asm new file mode 100755 index 00000000..2459a745 --- /dev/null +++ b/src/crypto/ecops64/ecops64.asm @@ -0,0 +1,4774 @@ +; Copyright (c) 2019, Ryo Currency Project +; +; Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +; All rights reserved. +; +; Authors and copyright holders give permission for following: +; +; 1. Redistribution and use in source and binary forms WITHOUT modification. +; +; 2. Modification of the source form for your own personal use. +; +; As long as the following conditions are met: +; +; 3. You must not distribute modified copies of the work to third parties. This includes +; posting the work online, or hosting copies of the modified work for download. +; +; 4. Any derivative version of this work is also covered by this license, including point 8. +; +; 5. Neither the name of the copyright holders nor the names of the authors may be +; used to endorse or promote products derived from this software without specific +; prior written permission. +; +; 6. You agree that this licence is governed by and shall be construed in accordance +; with the laws of England and Wales. +; +; 7. You agree to submit all disputes arising out of or in connection with this licence +; to the exclusive jurisdiction of the Courts of England and Wales. +; +; Authors and copyright holders agree that: +; +; 8. This licence expires and the work covered by it is released into the +; public domain on 1st of February 2020 +; +; 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. + + +; Based on Dr Bernstein's public domain code. +; https://bench.cr.yp.to/supercop.html + +DEFAULT REL + +section .data +const_38 dq 38 +const_EC2D0 dq 0xEBD69B9426B2F146 +const_EC2D1 dq 0x00E0149A8283B156 +const_EC2D2 dq 0x198E80F2EEF3D130 +const_EC2D3 dq 0xA406D9DC56DFFCE7 + +section .text +global sV_fe64_mul +global sV_fe64_square +global sV_fe64_add +global sV_fe64_sub +global sV_fe64_reduce +global sV_ge64_add +global sV_ge64_p1p1_to_p3 +global sV_ge64_p1p1_to_p2 +global sV_ge64_nielsadd2 +global sV_ge64_pnielsadd_p1p1 +global sV_ge64_p2_dbl +global win64_wrapper + +win64_wrapper: +sub rsp,0x10 +mov QWORD [rsp+0x00],rdi +mov QWORD [rsp+0x08],rsi +mov rdi,rdx +mov rsi,r8 +mov rdx,r9 +call rcx +mov rdi,QWORD [rsp+0x00] +mov rsi,QWORD [rsp+0x08] +add rsp,0x10 +ret + +sV_fe64_mul: +mov r11,rsp +and r11,0x1f +add r11,0x40 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,rdx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsi] +mov rax,QWORD [rcx] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsi+0x8] +mov rax,QWORD [rcx] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsi+0x10] +mov rax,QWORD [rcx] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov rsi,QWORD [rsi+0x18] +mov rax,QWORD [rcx] +mul rsi +add rbx,rax +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x8] +mul rsi +add r8,rax +adc rdx,0x0 +add r8,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x10] +mul rsi +add r9,rax +adc rdx,0x0 +add r9,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x18] +mul rsi +add r10,rax +adc rdx,0x0 +add r10,r12 +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov rsi,rax +mov rax,r9 +mov rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,r10 +mov r8,0x0 +adc r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r11 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,0x0 +adc rax,rdx +add r13,rsi +adc r14,rcx +adc r15,r8 +adc rbx,r9 +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r13,rdx +adc r14,rsi +adc r15,rsi +adc rbx,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r13,rsi +mov QWORD [rdi+0x8],r14 +mov QWORD [rdi+0x10],r15 +mov QWORD [rdi+0x18],rbx +mov QWORD [rdi],r13 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_fe64_square: +mov r11,rsp +and r11,0x1f +add r11,0x40 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,0x0 +mov rax,QWORD [rsi+0x8] +mul QWORD [rsi] +mov r8,rax +mov r9,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi+0x8] +mov r10,rax +mov r11,rdx +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x10] +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi] +add r9,rax +adc r10,rdx +adc r11,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x8] +add r11,rax +adc r12,rdx +adc r13,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi] +add r10,rax +adc r11,rdx +adc r12,0x0 +adc r13,0x0 +adc rcx,0x0 +add r8,r8 +adc r9,r9 +adc r10,r10 +adc r11,r11 +adc r12,r12 +adc r13,r13 +adc rcx,rcx +mov rax,QWORD [rsi] +mul QWORD [rsi] +mov r14,rax +mov r15,rdx +mov rax,QWORD [rsi+0x8] +mul QWORD [rsi+0x8] +mov rbx,rax +mov rbp,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi+0x10] +add r8,r15 +adc r9,rbx +adc r10,rbp +adc r11,rax +adc r12,rdx +adc r13,0x0 +adc rcx,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x18] +add r13,rax +adc rcx,rdx +mov rax,r11 +mul QWORD [const_38] +mov rsi,rax +mov rax,r12 +mov r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,r13 +mov r12,0x0 +adc r12,rdx +mul QWORD [const_38] +add r12,rax +mov rax,rcx +mov rcx,0x0 +adc rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,0x0 +adc rax,rdx +add r14,rsi +adc r8,r11 +adc r9,r12 +adc r10,rcx +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r14,rdx +adc r8,rsi +adc r9,rsi +adc r10,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r14,rsi +mov QWORD [rdi+0x8],r8 +mov QWORD [rdi+0x10],r9 +mov QWORD [rdi+0x18],r10 +mov QWORD [rdi],r14 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_fe64_add: +mov r11,rsp +and r11,0x1f +add r11,0x0 +sub rsp,r11 +mov rcx,QWORD [rsi] +mov r8,QWORD [rsi+0x8] +mov r9,QWORD [rsi+0x10] +mov rsi,QWORD [rsi+0x18] +add rcx,QWORD [rdx] +adc r8,QWORD [rdx+0x8] +adc r9,QWORD [rdx+0x10] +adc rsi,QWORD [rdx+0x18] +mov rdx,0x0 +mov rax,0x26 +cmovae rax,rdx +add rcx,rax +adc r8,rdx +adc r9,rdx +adc rsi,rdx +cmovb rdx,rax +add rcx,rdx +mov QWORD [rdi],rcx +mov QWORD [rdi+0x8],r8 +mov QWORD [rdi+0x10],r9 +mov QWORD [rdi+0x18],rsi +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_fe64_sub: +mov r11,rsp +and r11,0x1f +add r11,0x0 +sub rsp,r11 +mov rcx,QWORD [rsi] +mov r8,QWORD [rsi+0x8] +mov r9,QWORD [rsi+0x10] +mov rsi,QWORD [rsi+0x18] +sub rcx,QWORD [rdx] +sbb r8,QWORD [rdx+0x8] +sbb r9,QWORD [rdx+0x10] +sbb rsi,QWORD [rdx+0x18] +mov rdx,0x0 +mov rax,0x26 +cmovae rax,rdx +sub rcx,rax +sbb r8,rdx +sbb r9,rdx +sbb rsi,rdx +cmovb rdx,rax +sub rcx,rdx +mov QWORD [rdi],rcx +mov QWORD [rdi+0x8],r8 +mov QWORD [rdi+0x10],r9 +mov QWORD [rdi+0x18],rsi +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_fe64_reduce: +mov r11,rsp +and r11,0x1f +add r11,0x40 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rsi,QWORD [rdi] +mov rdx,QWORD [rdi+0x8] +mov rcx,QWORD [rdi+0x10] +mov r8,QWORD [rdi+0x18] +mov r9,rsi +mov rax,rdx +mov r10,rcx +mov r11,r8 +mov r12,0x1 +shl r12,0x3f +add r9,0x13 +adc rax,0x0 +adc r10,0x0 +adc r11,r12 +cmovb rsi,r9 +cmovb rdx,rax +cmovb rcx,r10 +cmovb r8,r11 +mov r9,rsi +mov rax,rdx +mov r10,rcx +mov r11,r8 +add r9,0x13 +adc rax,0x0 +adc r10,0x0 +adc r11,r12 +cmovb rsi,r9 +cmovb rdx,rax +cmovb rcx,r10 +cmovb r8,r11 +mov QWORD [rdi],rsi +mov QWORD [rdi+0x8],rdx +mov QWORD [rdi+0x10],rcx +mov QWORD [rdi+0x18],r8 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_add: +mov r11,rsp +and r11,0x1f +add r11,0xc0 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,rdx +mov rdx,QWORD [rsi+0x20] +mov r8,QWORD [rsi+0x28] +mov r9,QWORD [rsi+0x30] +mov rax,QWORD [rsi+0x38] +mov r10,rdx +mov r11,r8 +mov r12,r9 +mov r13,rax +sub rdx,QWORD [rsi] +sbb r8,QWORD [rsi+0x8] +sbb r9,QWORD [rsi+0x10] +sbb rax,QWORD [rsi+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +sub rdx,r15 +sbb r8,r14 +sbb r9,r14 +sbb rax,r14 +cmovb r14,r15 +sub rdx,r14 +add r10,QWORD [rsi] +adc r11,QWORD [rsi+0x8] +adc r12,QWORD [rsi+0x10] +adc r13,QWORD [rsi+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +add r10,r15 +adc r11,r14 +adc r12,r14 +adc r13,r14 +cmovb r14,r15 +add r10,r14 +mov QWORD [rsp+0x38],rdx +mov QWORD [rsp+0x40],r8 +mov QWORD [rsp+0x48],r9 +mov QWORD [rsp+0x50],rax +mov QWORD [rsp+0x58],r10 +mov QWORD [rsp+0x60],r11 +mov QWORD [rsp+0x68],r12 +mov QWORD [rsp+0x70],r13 +mov rdx,QWORD [rcx+0x20] +mov r8,QWORD [rcx+0x28] +mov r9,QWORD [rcx+0x30] +mov rax,QWORD [rcx+0x38] +mov r10,rdx +mov r11,r8 +mov r12,r9 +mov r13,rax +sub rdx,QWORD [rcx] +sbb r8,QWORD [rcx+0x8] +sbb r9,QWORD [rcx+0x10] +sbb rax,QWORD [rcx+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +sub rdx,r15 +sbb r8,r14 +sbb r9,r14 +sbb rax,r14 +cmovb r14,r15 +sub rdx,r14 +add r10,QWORD [rcx] +adc r11,QWORD [rcx+0x8] +adc r12,QWORD [rcx+0x10] +adc r13,QWORD [rcx+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +add r10,r15 +adc r11,r14 +adc r12,r14 +adc r13,r14 +cmovb r14,r15 +add r10,r14 +mov QWORD [rsp+0x78],rdx +mov QWORD [rsp+0x80],r8 +mov QWORD [rsp+0x88],r9 +mov QWORD [rsp+0x90],rax +mov QWORD [rsp+0x98],r10 +mov QWORD [rsp+0xa0],r11 +mov QWORD [rsp+0xa8],r12 +mov QWORD [rsp+0xb0],r13 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsp+0x38] +mov rax,QWORD [rsp+0x78] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rsp+0x80] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0x88] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsp+0x90] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsp+0x40] +mov rax,QWORD [rsp+0x78] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x80] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x88] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x90] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsp+0x48] +mov rax,QWORD [rsp+0x78] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x80] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x88] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x90] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsp+0x50] +mov rax,QWORD [rsp+0x78] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x80] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x88] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0x90] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov QWORD [rsp+0x38],r13 +mov QWORD [rsp+0x40],r14 +mov QWORD [rsp+0x48],r15 +mov QWORD [rsp+0x50],rbx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsp+0x58] +mov rax,QWORD [rsp+0x98] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rsp+0xa0] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0xa8] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsp+0xb0] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsp+0x60] +mov rax,QWORD [rsp+0x98] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa0] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa8] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xb0] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsp+0x68] +mov rax,QWORD [rsp+0x98] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa0] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa8] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xb0] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsp+0x70] +mov rax,QWORD [rsp+0x98] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa0] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xa8] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rsp+0xb0] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov rdx,r13 +mov r8,r14 +mov r9,r15 +mov rax,rbx +add rdx,QWORD [rsp+0x38] +adc r8,QWORD [rsp+0x40] +adc r9,QWORD [rsp+0x48] +adc rax,QWORD [rsp+0x50] +mov r10,0x0 +mov r11,0x26 +cmovae r11,r10 +add rdx,r11 +adc r8,r10 +adc r9,r10 +adc rax,r10 +cmovb r10,r11 +add rdx,r10 +sub r13,QWORD [rsp+0x38] +sbb r14,QWORD [rsp+0x40] +sbb r15,QWORD [rsp+0x48] +sbb rbx,QWORD [rsp+0x50] +mov r10,0x0 +mov r11,0x26 +cmovae r11,r10 +sub r13,r11 +sbb r14,r10 +sbb r15,r10 +sbb rbx,r10 +cmovb r10,r11 +sub r13,r10 +mov QWORD [rdi],r13 +mov QWORD [rdi+0x8],r14 +mov QWORD [rdi+0x10],r15 +mov QWORD [rdi+0x18],rbx +mov QWORD [rdi+0x40],rdx +mov QWORD [rdi+0x48],r8 +mov QWORD [rdi+0x50],r9 +mov QWORD [rdi+0x58],rax +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsi+0x60] +mov rax,QWORD [rcx+0x60] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsi+0x68] +mov rax,QWORD [rcx+0x60] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsi+0x70] +mov rax,QWORD [rcx+0x60] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsi+0x78] +mov rax,QWORD [rcx+0x60] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov QWORD [rsp+0x38],r13 +mov QWORD [rsp+0x40],r14 +mov QWORD [rsp+0x48],r15 +mov QWORD [rsp+0x50],rbx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsp+0x38] +mov rax,QWORD [const_EC2D0] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [const_EC2D1] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [const_EC2D2] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [const_EC2D3] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsp+0x40] +mov rax,QWORD [const_EC2D0] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D1] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D2] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D3] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsp+0x48] +mov rax,QWORD [const_EC2D0] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D1] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D2] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D3] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsp+0x50] +mov rax,QWORD [const_EC2D0] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D1] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D2] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [const_EC2D3] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov QWORD [rsp+0x38],r13 +mov QWORD [rsp+0x40],r14 +mov QWORD [rsp+0x48],r15 +mov QWORD [rsp+0x50],rbx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsi+0x40] +mov rax,QWORD [rcx+0x40] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsi+0x48] +mov rax,QWORD [rcx+0x40] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsi+0x50] +mov rax,QWORD [rcx+0x40] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov rsi,QWORD [rsi+0x58] +mov rax,QWORD [rcx+0x40] +mul rsi +add rbx,rax +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x48] +mul rsi +add r8,rax +adc rdx,0x0 +add r8,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x50] +mul rsi +add r9,rax +adc rdx,0x0 +add r9,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x58] +mul rsi +add r10,rax +adc rdx,0x0 +add r10,r12 +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov rsi,rax +mov rax,r9 +mov rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,r10 +mov r8,0x0 +adc r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r11 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,0x0 +adc rax,rdx +add r13,rsi +adc r14,rcx +adc r15,r8 +adc rbx,r9 +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r13,rdx +adc r14,rsi +adc r15,rsi +adc rbx,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r13,rsi +add r13,r13 +adc r14,r14 +adc r15,r15 +adc rbx,rbx +mov rsi,0x0 +mov rdx,0x26 +cmovae rdx,rsi +add r13,rdx +adc r14,rsi +adc r15,rsi +adc rbx,rsi +cmovb rsi,rdx +add r13,rsi +mov rsi,r13 +mov rdx,r14 +mov rcx,r15 +mov r8,rbx +add rsi,QWORD [rsp+0x38] +adc rdx,QWORD [rsp+0x40] +adc rcx,QWORD [rsp+0x48] +adc r8,QWORD [rsp+0x50] +mov r9,0x0 +mov rax,0x26 +cmovae rax,r9 +add rsi,rax +adc rdx,r9 +adc rcx,r9 +adc r8,r9 +cmovb r9,rax +add rsi,r9 +sub r13,QWORD [rsp+0x38] +sbb r14,QWORD [rsp+0x40] +sbb r15,QWORD [rsp+0x48] +sbb rbx,QWORD [rsp+0x50] +mov r9,0x0 +mov rax,0x26 +cmovae rax,r9 +sub r13,rax +sbb r14,r9 +sbb r15,r9 +sbb rbx,r9 +cmovb r9,rax +sub r13,r9 +mov QWORD [rdi+0x20],rsi +mov QWORD [rdi+0x28],rdx +mov QWORD [rdi+0x30],rcx +mov QWORD [rdi+0x38],r8 +mov QWORD [rdi+0x60],r13 +mov QWORD [rdi+0x68],r14 +mov QWORD [rdi+0x70],r15 +mov QWORD [rdi+0x78],rbx +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_p1p1_to_p3: +mov r11,rsp +and r11,0x1f +add r11,0x40 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi] +mov rax,QWORD [rsi+0x60] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x8] +mov rax,QWORD [rsi+0x60] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x10] +mov rax,QWORD [rsi+0x60] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x18] +mov rax,QWORD [rsi+0x60] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r9 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,0x0 +adc rax,rdx +add r12,rcx +adc r13,r8 +adc r14,r9 +adc r15,r10 +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r12,rcx +adc r13,rdx +adc r14,rdx +adc r15,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r12,rdx +mov QWORD [rdi],r12 +mov QWORD [rdi+0x8],r13 +mov QWORD [rdi+0x10],r14 +mov QWORD [rdi+0x18],r15 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi+0x40] +mov rax,QWORD [rsi+0x20] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x48] +mov rax,QWORD [rsi+0x20] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x50] +mov rax,QWORD [rsi+0x20] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x58] +mov rax,QWORD [rsi+0x20] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r9 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,0x0 +adc rax,rdx +add r12,rcx +adc r13,r8 +adc r14,r9 +adc r15,r10 +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r12,rcx +adc r13,rdx +adc r14,rdx +adc r15,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r12,rdx +mov QWORD [rdi+0x20],r12 +mov QWORD [rdi+0x28],r13 +mov QWORD [rdi+0x30],r14 +mov QWORD [rdi+0x38],r15 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi+0x20] +mov rax,QWORD [rsi+0x60] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x28] +mov rax,QWORD [rsi+0x60] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x30] +mov rax,QWORD [rsi+0x60] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x38] +mov rax,QWORD [rsi+0x60] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r9 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,0x0 +adc rax,rdx +add r12,rcx +adc r13,r8 +adc r14,r9 +adc r15,r10 +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r12,rcx +adc r13,rdx +adc r14,rdx +adc r15,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r12,rdx +mov QWORD [rdi+0x40],r12 +mov QWORD [rdi+0x48],r13 +mov QWORD [rdi+0x50],r14 +mov QWORD [rdi+0x58],r15 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi] +mov rax,QWORD [rsi+0x40] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x48] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x8] +mov rax,QWORD [rsi+0x40] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x48] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x10] +mov rax,QWORD [rsi+0x40] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x48] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x18] +mov rax,QWORD [rsi+0x40] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x48] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rsi,rax +mov rax,r8 +mov rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,r9 +mov r8,0x0 +adc r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r10 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,0x0 +adc rax,rdx +add r12,rsi +adc r13,rcx +adc r14,r8 +adc r15,r9 +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r12,rdx +adc r13,rsi +adc r14,rsi +adc r15,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r12,rsi +mov QWORD [rdi+0x60],r12 +mov QWORD [rdi+0x68],r13 +mov QWORD [rdi+0x70],r14 +mov QWORD [rdi+0x78],r15 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_p1p1_to_p2: +mov r11,rsp +and r11,0x1f +add r11,0x40 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi] +mov rax,QWORD [rsi+0x60] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x8] +mov rax,QWORD [rsi+0x60] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x10] +mov rax,QWORD [rsi+0x60] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x18] +mov rax,QWORD [rsi+0x60] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r9 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,0x0 +adc rax,rdx +add r12,rcx +adc r13,r8 +adc r14,r9 +adc r15,r10 +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r12,rcx +adc r13,rdx +adc r14,rdx +adc r15,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r12,rdx +mov QWORD [rdi],r12 +mov QWORD [rdi+0x8],r13 +mov QWORD [rdi+0x10],r14 +mov QWORD [rdi+0x18],r15 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi+0x40] +mov rax,QWORD [rsi+0x20] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x48] +mov rax,QWORD [rsi+0x20] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x50] +mov rax,QWORD [rsi+0x20] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x58] +mov rax,QWORD [rsi+0x20] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r9 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,0x0 +adc rax,rdx +add r12,rcx +adc r13,r8 +adc r14,r9 +adc r15,r10 +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r12,rcx +adc r13,rdx +adc r14,rdx +adc r15,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r12,rdx +mov QWORD [rdi+0x20],r12 +mov QWORD [rdi+0x28],r13 +mov QWORD [rdi+0x30],r14 +mov QWORD [rdi+0x38],r15 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,QWORD [rsi+0x20] +mov rax,QWORD [rsi+0x60] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsi+0x28] +mov rax,QWORD [rsi+0x60] +mul r11 +add r13,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsi+0x30] +mov rax,QWORD [rsi+0x60] +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsi+0x38] +mov rax,QWORD [rsi+0x60] +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x68] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x70] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x78] +mul r11 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mul QWORD [const_38] +mov rsi,rax +mov rax,r8 +mov rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,r9 +mov r8,0x0 +adc r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r10 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,0x0 +adc rax,rdx +add r12,rsi +adc r13,rcx +adc r14,r8 +adc r15,r9 +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r12,rdx +adc r13,rsi +adc r14,rsi +adc r15,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r12,rsi +mov QWORD [rdi+0x40],r12 +mov QWORD [rdi+0x48],r13 +mov QWORD [rdi+0x50],r14 +mov QWORD [rdi+0x58],r15 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_nielsadd2: +mov r11,rsp +and r11,0x1f +add r11,0xc0 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov r11,QWORD [rdi+0x20] +mov r8,QWORD [rdi+0x28] +mov r9,QWORD [rdi+0x30] +mov r10,QWORD [rdi+0x38] +mov rax,r11 +mov rcx,r8 +mov rdx,r9 +mov r12,r10 +xor r13,r13 +mov r14,0x26 +sub r11,QWORD [rdi] +sbb r8,QWORD [rdi+0x8] +sbb r9,QWORD [rdi+0x10] +sbb r10,QWORD [rdi+0x18] +cmovae r14,r13 +sub r11,r14 +sbb r8,r13 +sbb r9,r13 +sbb r10,r13 +cmovb r13,r14 +sub r11,r13 +xor r13,r13 +mov r14,0x26 +add rax,QWORD [rdi] +adc rcx,QWORD [rdi+0x8] +adc rdx,QWORD [rdi+0x10] +adc r12,QWORD [rdi+0x18] +cmovae r14,r13 +add rax,r14 +adc rcx,r13 +adc rdx,r13 +adc r12,r13 +cmovb r13,r14 +add rax,r13 +mov QWORD [rsp+0x58],rax +mov QWORD [rsp+0x60],rcx +mov QWORD [rsp+0x68],rdx +mov QWORD [rsp+0x70],r12 +xor rcx,rcx +mov rax,QWORD [rsi] +mul r11 +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x8] +mul r11 +xor r14,r14 +add r13,rax +adc r14,rdx +mov rax,QWORD [rsi+0x10] +mul r11 +xor r15,r15 +add r14,rax +adc r15,rdx +mov rax,QWORD [rsi+0x18] +mul r11 +add r15,rax +adc rcx,rdx +mov rax,QWORD [rsi] +mul r8 +xor rbx,rbx +xor r11,r11 +add r13,rax +adc rbx,rdx +mov rax,QWORD [rsi+0x8] +mul r8 +add r14,rax +adc rdx,r11 +add r14,rbx +adc r11,rdx +mov rax,QWORD [rsi+0x10] +mul r8 +xor rbx,rbx +add r15,rax +adc rdx,rbx +add r15,r11 +adc rbx,rdx +mov rax,QWORD [rsi+0x18] +mul r8 +xor r11,r11 +add rcx,rax +adc rdx,r11 +add rcx,rbx +adc r11,rdx +mov rax,QWORD [rsi] +mul r9 +xor r8,r8 +xor rbx,rbx +add r14,rax +adc rbx,rdx +mov rax,QWORD [rsi+0x8] +mul r9 +add r15,rax +adc rdx,r8 +add r15,rbx +adc r8,rdx +mov rax,QWORD [rsi+0x10] +mul r9 +xor rbx,rbx +add rcx,rax +adc rdx,rbx +add rcx,r8 +adc rbx,rdx +mov rax,QWORD [rsi+0x18] +mul r9 +xor r9,r9 +add r11,rax +adc rdx,r9 +add r11,rbx +adc r9,rdx +mov rax,QWORD [rsi] +mul r10 +xor r8,r8 +xor rbx,rbx +add r15,rax +adc rbx,rdx +mov rax,QWORD [rsi+0x8] +mul r10 +add rcx,rax +adc rdx,r8 +add rcx,rbx +adc r8,rdx +mov rax,QWORD [rsi+0x10] +mul r10 +xor rbx,rbx +add r11,rax +adc rdx,rbx +add r11,r8 +adc rbx,rdx +mov rax,QWORD [rsi+0x18] +mul r10 +xor r10,r10 +add r9,rax +adc rdx,r10 +add r9,rbx +adc r10,rdx +mov rax,rcx +mov rbp,0x26 +mul rbp +mov rcx,rax +mov rax,r11 +mov r8,rdx +mul rbp +xor rbx,rbx +add r8,rax +mov rax,r9 +adc rbx,rdx +mul rbp +xor r9,r9 +add rbx,rax +mov rax,r10 +adc r9,rdx +mul rbp +xor r10,r10 +add r9,rax +adc r10,rdx +xor rax,rax +add r12,rcx +adc r13,r8 +adc r14,rbx +adc r15,r9 +adc r10,rax +imul rcx,r10,0x26 +add r12,rcx +adc r13,rax +adc r14,rax +adc r15,rax +adc rax,rax +imul rax,rax,0x26 +add r12,rax +mov QWORD [rsp+0x38],r12 +mov QWORD [rsp+0x40],r13 +mov QWORD [rsp+0x48],r14 +mov QWORD [rsp+0x50],r15 +xor rcx,rcx +mov r10,QWORD [rsi+0x20] +mov r9,QWORD [rsi+0x28] +mov r8,QWORD [rsi+0x30] +mov r11,QWORD [rsp+0x58] +mov rax,r10 +mul r11 +mov r12,rax +mov r13,rdx +mov rax,r9 +mul r11 +xor r14,r14 +add r13,rax +adc r14,rdx +mov rax,r8 +mul r11 +xor r15,r15 +add r14,rax +adc r15,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rsp+0x60] +mov rax,r10 +mul r11 +xor rbx,rbx +add r13,rax +adc rbx,rdx +mov rax,r9 +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,r8 +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +xor r8,r8 +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rsp+0x68] +mov rax,r10 +mul r11 +xor rbx,rbx +add r14,rax +adc rbx,rdx +mov rax,r9 +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +xor r9,r9 +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rsp+0x70] +mov rax,r10 +mul r11 +xor rbx,rbx +add r15,rax +adc rbx,rdx +mov rax,QWORD [rsi+0x28] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x30] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x38] +mul r11 +xor r10,r10 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mov rbp,0x26 +mul rbp +mov rcx,rax +mov rax,r8 +mov r8,rdx +mul rbp +xor rbx,rbx +add r8,rax +mov rax,r9 +adc rbx,rdx +mul rbp +xor r9,r9 +add rbx,rax +mov rax,r10 +adc r9,rdx +mul rbp +xor r10,r10 +add r9,rax +adc r10,rdx +xor rax,rax +add r12,rcx +adc r13,r8 +adc r14,rbx +adc r15,r9 +adc r10,rax +imul rcx,r10,0x26 +add r12,rcx +adc r13,rax +adc r14,rax +adc r15,rax +adc rax,rax +imul rax,rax,0x26 +add r12,rax +mov rdx,r12 +mov rcx,r13 +mov r8,r14 +mov r9,r15 +mov r10,QWORD [rsp+0x38] +mov r11,QWORD [rsp+0x40] +mov rbx,QWORD [rsp+0x48] +xor rax,rax +sub r12,r10 +sbb r13,r11 +sbb r14,rbx +sbb r15,QWORD [rsp+0x50] +cmovae rbp,rax +sub r12,rbp +sbb r13,rax +sbb r14,rax +sbb r15,rax +cmovb rax,rbp +sub r12,rax +xor rax,rax +add rdx,r10 +adc rcx,r11 +adc r8,rbx +adc r9,QWORD [rsp+0x50] +mov r10,0x26 +cmovae r10,rax +add rdx,r10 +adc rcx,rax +adc r8,rax +adc r9,rax +cmovb rax,r10 +add rdx,rax +mov QWORD [rsp+0x38],rdx +mov QWORD [rsp+0x40],rcx +mov QWORD [rsp+0x48],r8 +mov QWORD [rsp+0x50],r9 +mov QWORD [rsp+0x58],r12 +mov QWORD [rsp+0x60],r13 +mov QWORD [rsp+0x68],r14 +mov QWORD [rsp+0x70],r15 +xor rcx,rcx +xor r8,r8 +xor r9,r9 +mov r10,QWORD [rsi+0x40] +mov rbp,QWORD [rsi+0x48] +mov r11,QWORD [rdi+0x60] +mov rax,r10 +mul r11 +mov r12,rax +mov r13,rdx +mov rax,rbp +mul r11 +xor r14,r14 +add r13,rax +adc r14,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +xor r15,r15 +add r14,rax +adc r15,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add r15,rax +adc rcx,rdx +mov r11,QWORD [rdi+0x68] +mov rax,r10 +mul r11 +xor rbx,rbx +add r13,rax +adc rbx,rdx +mov rax,rbp +mul r11 +add r14,rax +adc rdx,0x0 +add r14,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +adc r8,rdx +mov r11,QWORD [rdi+0x70] +mov rax,r10 +mul r11 +add r14,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,rbp +mul r11 +add r15,rax +adc rdx,0x0 +add r15,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +adc r9,rdx +mov r11,QWORD [rdi+0x78] +mov rax,r10 +mul r11 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,rbp +mul r11 +add rcx,rax +adc rdx,0x0 +add rcx,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x50] +mul r11 +add r8,rax +adc rdx,0x0 +add r8,rbx +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rsi+0x58] +mul r11 +xor r10,r10 +add r9,rax +adc rdx,0x0 +add r9,rbx +adc r10,rdx +mov rax,rcx +mov rbp,0x26 +mul rbp +mov rsi,rax +mov rax,r8 +mov rcx,rdx +mul rbp +xor rbx,rbx +add rcx,rax +mov rax,r9 +adc rbx,rdx +mul rbp +xor r8,r8 +add rbx,rax +mov rax,r10 +adc r8,rdx +mul rbp +xor r9,r9 +add r8,rax +adc r9,rdx +xor rax,rax +add r12,rsi +adc r13,rcx +adc r14,rbx +adc r15,r8 +adc r9,rax +imul rdx,r9,0x26 +add r12,rdx +adc r13,rax +adc r14,rax +adc r15,rax +adc rax,rax +imul rax,rax,0x26 +add r12,rax +mov r9,QWORD [rdi+0x40] +mov rbx,QWORD [rdi+0x48] +mov rcx,QWORD [rdi+0x50] +mov r8,QWORD [rdi+0x58] +xor rsi,rsi +add r9,r9 +adc rbx,rbx +adc rcx,rcx +adc r8,r8 +mov rax,rbp +cmovae rax,rsi +add r9,rax +adc rbx,rsi +adc rcx,rsi +adc r8,rsi +cmovb rsi,rax +add r9,rsi +mov rsi,r9 +mov rax,rbx +mov r10,rcx +mov r11,r8 +xor rdx,rdx +sub r9,r12 +sbb rbx,r13 +sbb rcx,r14 +sbb r8,r15 +cmovae rbp,rdx +sub r9,rbp +sbb rbx,rdx +sbb rcx,rdx +sbb r8,rdx +cmovb rdx,rbp +sub r9,rdx +add rsi,r12 +adc rax,r13 +adc r10,r14 +adc r11,r15 +mov r12,0x0 +mov r13,0x26 +cmovae r13,r12 +add rsi,r13 +adc rax,r12 +adc r10,r12 +adc r11,r12 +cmovb r12,r13 +add rsi,r12 +mov QWORD [rsp+0x78],rsi +mov QWORD [rsp+0x80],rax +mov QWORD [rsp+0x88],r10 +mov QWORD [rsp+0x90],r11 +mov QWORD [rsp+0x98],r9 +mov QWORD [rsp+0xa0],rbx +mov QWORD [rsp+0xa8],rcx +mov QWORD [rsp+0xb0],r8 +mov rbp,rcx +xor rsi,rsi +xor rcx,rcx +mov r10,QWORD [rsp+0x58] +mov rax,r9 +mul r10 +mov r11,rax +mov r12,rdx +mov rax,rbx +mul r10 +add r12,rax +mov r13,0x0 +adc r13,rdx +mov rax,rbp +mul r10 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,r8 +mul r10 +add r14,rax +adc rsi,rdx +mov r10,QWORD [rsp+0x60] +mov rax,r9 +mul r10 +xor r15,r15 +add r12,rax +adc r15,rdx +mov rax,rbx +mul r10 +add r13,rax +adc rdx,0x0 +add r13,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +adc rcx,rdx +mov r10,QWORD [rsp+0x68] +mov rax,r9 +mul r10 +add r13,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +xor r8,r8 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +adc r8,rdx +mov r10,QWORD [rsp+0x70] +mov rax,r9 +mul r10 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0xb0] +mul r10 +xor r9,r9 +add r8,rax +adc rdx,0x0 +add r8,r15 +adc r9,rdx +mov rax,rsi +mov rbp,0x26 +mul rbp +mov rsi,rax +mov rax,rcx +mov rcx,rdx +mul rbp +xor rbx,rbx +add rcx,rax +mov rax,r8 +adc rbx,rdx +mul rbp +xor r8,r8 +add rbx,rax +mov rax,r9 +adc r8,rdx +mul rbp +xor r9,r9 +add r8,rax +adc r9,rdx +xor rax,rax +add r11,rsi +adc r12,rcx +adc r13,rbx +adc r14,r8 +adc r9,rax +imul rdx,r9,0x26 +add r11,rdx +adc r12,rax +adc r13,rax +adc r14,rax +adc rax,rax +imul rax,rax,0x26 +add r11,rax +mov QWORD [rdi],r11 +mov QWORD [rdi+0x8],r12 +mov QWORD [rdi+0x10],r13 +mov QWORD [rdi+0x18],r14 +xor rsi,rsi +xor rcx,rcx +mov r9,QWORD [rsp+0x78] +mov rbx,QWORD [rsp+0x80] +mov rbp,QWORD [rsp+0x88] +mov r8,QWORD [rsp+0x90] +mov r10,QWORD [rsp+0x38] +mov rax,r9 +mul r10 +mov r11,rax +mov r12,rdx +mov rax,rbx +mul r10 +add r12,rax +mov r13,0x0 +adc r13,rdx +mov rax,rbp +mul r10 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,r8 +mul r10 +add r14,rax +adc rsi,rdx +mov r10,QWORD [rsp+0x40] +mov rax,r9 +mul r10 +add r12,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r13,rax +adc rdx,0x0 +add r13,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +adc rcx,rdx +mov r10,QWORD [rsp+0x48] +mov rax,r9 +mul r10 +add r13,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +xor r8,r8 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +adc r8,rdx +mov r10,QWORD [rsp+0x50] +mov rax,r9 +mul r10 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0x90] +mul r10 +xor r9,r9 +add r8,rax +adc rdx,0x0 +add r8,r15 +adc r9,rdx +mov rax,rsi +mov rbp,0x26 +mul rbp +mov rsi,rax +mov rax,rcx +mov rcx,rdx +mul rbp +xor rbx,rbx +add rcx,rax +mov rax,r8 +adc rbx,rdx +mul rbp +xor r8,r8 +add rbx,rax +mov rax,r9 +adc r8,rdx +mul rbp +xor r9,r9 +add r8,rax +adc r9,rdx +xor rax,rax +add r11,rsi +adc r12,rcx +adc r13,rbx +adc r14,r8 +adc r9,rax +imul rdx,r9,0x26 +add r11,rdx +adc r12,rax +adc r13,rax +adc r14,rax +adc rax,rax +imul rax,rax,0x26 +add r11,rax +mov QWORD [rdi+0x20],r11 +mov QWORD [rdi+0x28],r12 +mov QWORD [rdi+0x30],r13 +mov QWORD [rdi+0x38],r14 +xor rsi,rsi +xor rcx,rcx +mov r9,QWORD [rsp+0x98] +mov rbx,QWORD [rsp+0xa0] +mov rbp,QWORD [rsp+0xa8] +mov r8,QWORD [rsp+0xb0] +mov r10,QWORD [rsp+0x78] +mov rax,r9 +mul r10 +mov r11,rax +mov r12,rdx +mov rax,rbx +mul r10 +add r12,rax +mov r13,0x0 +adc r13,rdx +mov rax,rbp +mul r10 +add r13,rax +mov r14,0x0 +adc r14,rdx +mov rax,r8 +mul r10 +add r14,rax +adc rsi,rdx +mov r10,QWORD [rsp+0x80] +mov rax,r9 +mul r10 +add r12,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r13,rax +adc rdx,0x0 +add r13,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +adc rcx,rdx +mov r10,QWORD [rsp+0x88] +mov rax,r9 +mul r10 +add r13,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +xor r8,r8 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +adc r8,rdx +mov r10,QWORD [rsp+0x90] +mov rax,r9 +mul r10 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0xb0] +mul r10 +xor r9,r9 +add r8,rax +adc rdx,0x0 +add r8,r15 +adc r9,rdx +mov rax,rsi +mov rbp,0x26 +mul rbp +mov rsi,rax +mov rax,rcx +mov rcx,rdx +mul rbp +xor rbx,rbx +add rcx,rax +mov rax,r8 +adc rbx,rdx +mul rbp +xor r8,r8 +add rbx,rax +mov rax,r9 +adc r8,rdx +mul rbp +xor r9,r9 +add r8,rax +adc r9,rdx +xor rax,rax +add r11,rsi +adc r12,rcx +adc r13,rbx +adc r14,r8 +adc r9,rax +imul rdx,r9,0x26 +add r11,rdx +adc r12,rax +adc r13,rax +adc r14,rax +adc rax,rax +imul rax,rax,0x26 +add r11,rax +mov QWORD [rdi+0x40],r11 +mov QWORD [rdi+0x48],r12 +mov QWORD [rdi+0x50],r13 +mov QWORD [rdi+0x58],r14 +xor rsi,rsi +xor rcx,rcx +mov r9,QWORD [rsp+0x38] +mov rbx,QWORD [rsp+0x40] +mov rbp,QWORD [rsp+0x48] +mov r8,QWORD [rsp+0x50] +mov r10,QWORD [rsp+0x58] +mov rax,r9 +mul r10 +mov r11,rax +mov r12,rdx +mov rax,rbx +mul r10 +xor r13,r13 +add r12,rax +adc r13,rdx +mov rax,rbp +mul r10 +xor r14,r14 +add r13,rax +adc r14,rdx +mov rax,r8 +mul r10 +add r14,rax +adc rsi,rdx +mov r10,QWORD [rsp+0x60] +mov rax,r9 +mul r10 +xor r15,r15 +add r12,rax +adc r15,rdx +mov rax,rbx +mul r10 +add r13,rax +adc rdx,0x0 +add r13,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +adc rcx,rdx +mov r10,QWORD [rsp+0x68] +mov rax,r9 +mul r10 +add r13,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add r14,rax +adc rdx,0x0 +add r14,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,r8 +mul r10 +xor r8,r8 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +adc r8,rdx +mov r10,QWORD [rsp+0x70] +mov rax,r9 +mul r10 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,rbx +mul r10 +add rsi,rax +adc rdx,0x0 +add rsi,r15 +mov r15,0x0 +adc r15,rdx +mov rax,rbp +mul r10 +add rcx,rax +adc rdx,0x0 +add rcx,r15 +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rsp+0x50] +mul r10 +xor r9,r9 +add r8,rax +adc rdx,0x0 +add r8,r15 +adc r9,rdx +mov rax,rsi +mov rbp,0x26 +mul rbp +mov rsi,rax +mov rax,rcx +mov rcx,rdx +mul rbp +xor rbx,rbx +add rcx,rax +mov rax,r8 +adc rbx,rdx +mul rbp +xor r8,r8 +add rbx,rax +mov rax,r9 +adc r8,rdx +mul rbp +xor r9,r9 +add r8,rax +adc r9,rdx +xor rax,rax +add r11,rsi +adc r12,rcx +adc r13,rbx +adc r14,r8 +adc r9,rax +imul rdx,r9,0x26 +add r11,rdx +adc r12,rax +adc r13,rax +adc r14,rax +adc rax,rax +imul rax,rax,0x26 +add r11,rax +mov QWORD [rdi+0x60],r11 +mov QWORD [rdi+0x68],r12 +mov QWORD [rdi+0x70],r13 +mov QWORD [rdi+0x78],r14 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_pnielsadd_p1p1: +mov r11,rsp +and r11,0x1f +add r11,0x80 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,rdx +mov rdx,QWORD [rsi+0x20] +mov r8,QWORD [rsi+0x28] +mov r9,QWORD [rsi+0x30] +mov rax,QWORD [rsi+0x38] +mov r10,rdx +mov r11,r8 +mov r12,r9 +mov r13,rax +sub rdx,QWORD [rsi] +sbb r8,QWORD [rsi+0x8] +sbb r9,QWORD [rsi+0x10] +sbb rax,QWORD [rsi+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +sub rdx,r15 +sbb r8,r14 +sbb r9,r14 +sbb rax,r14 +cmovb r14,r15 +sub rdx,r14 +add r10,QWORD [rsi] +adc r11,QWORD [rsi+0x8] +adc r12,QWORD [rsi+0x10] +adc r13,QWORD [rsi+0x18] +mov r14,0x0 +mov r15,0x26 +cmovae r15,r14 +add r10,r15 +adc r11,r14 +adc r12,r14 +adc r13,r14 +cmovb r14,r15 +add r10,r14 +mov QWORD [rsp+0x38],rdx +mov QWORD [rsp+0x40],r8 +mov QWORD [rsp+0x48],r9 +mov QWORD [rsp+0x50],rax +mov QWORD [rsp+0x58],r10 +mov QWORD [rsp+0x60],r11 +mov QWORD [rsp+0x68],r12 +mov QWORD [rsp+0x70],r13 +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsp+0x38] +mov rax,QWORD [rcx] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsp+0x40] +mov rax,QWORD [rcx] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsp+0x48] +mov rax,QWORD [rcx] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsp+0x50] +mov rax,QWORD [rcx] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x8] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x10] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x18] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov QWORD [rsp+0x38],r13 +mov QWORD [rsp+0x40],r14 +mov QWORD [rsp+0x48],r15 +mov QWORD [rsp+0x50],rbx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsp+0x58] +mov rax,QWORD [rcx+0x20] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x28] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x30] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x38] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsp+0x60] +mov rax,QWORD [rcx+0x20] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x28] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x30] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x38] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsp+0x68] +mov rax,QWORD [rcx+0x20] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x28] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x30] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x38] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsp+0x70] +mov rax,QWORD [rcx+0x20] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x28] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x30] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x38] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov rdx,r13 +mov r8,r14 +mov r9,r15 +mov rax,rbx +add rdx,QWORD [rsp+0x38] +adc r8,QWORD [rsp+0x40] +adc r9,QWORD [rsp+0x48] +adc rax,QWORD [rsp+0x50] +mov r10,0x0 +mov r11,0x26 +cmovae r11,r10 +add rdx,r11 +adc r8,r10 +adc r9,r10 +adc rax,r10 +cmovb r10,r11 +add rdx,r10 +sub r13,QWORD [rsp+0x38] +sbb r14,QWORD [rsp+0x40] +sbb r15,QWORD [rsp+0x48] +sbb rbx,QWORD [rsp+0x50] +mov r10,0x0 +mov r11,0x26 +cmovae r11,r10 +sub r13,r11 +sbb r14,r10 +sbb r15,r10 +sbb rbx,r10 +cmovb r10,r11 +sub r13,r10 +mov QWORD [rdi],r13 +mov QWORD [rdi+0x8],r14 +mov QWORD [rdi+0x10],r15 +mov QWORD [rdi+0x18],rbx +mov QWORD [rdi+0x40],rdx +mov QWORD [rdi+0x48],r8 +mov QWORD [rdi+0x50],r9 +mov QWORD [rdi+0x58],rax +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsi+0x60] +mov rax,QWORD [rcx+0x60] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsi+0x68] +mov rax,QWORD [rcx+0x60] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsi+0x70] +mov rax,QWORD [rcx+0x60] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov r12,QWORD [rsi+0x78] +mov rax,QWORD [rcx+0x60] +mul r12 +add rbx,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x68] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x70] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x78] +mul r12 +add r10,rax +adc rdx,0x0 +add r10,rbp +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov r8,rax +mov rax,r9 +mov r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,r10 +mov r10,0x0 +adc r10,rdx +mul QWORD [const_38] +add r10,rax +mov rax,r11 +mov r11,0x0 +adc r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,0x0 +adc rax,rdx +add r13,r8 +adc r14,r9 +adc r15,r10 +adc rbx,r11 +mov rdx,0x0 +adc rax,rdx +imul r8,rax,0x26 +add r13,r8 +adc r14,rdx +adc r15,rdx +adc rbx,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r13,rdx +mov QWORD [rsp+0x38],r13 +mov QWORD [rsp+0x40],r14 +mov QWORD [rsp+0x48],r15 +mov QWORD [rsp+0x50],rbx +mov r8,0x0 +mov r9,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,QWORD [rsi+0x40] +mov rax,QWORD [rcx+0x40] +mul r12 +mov r13,rax +mov r14,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add r14,rax +mov r15,0x0 +adc r15,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add r15,rax +mov rbx,0x0 +adc rbx,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add rbx,rax +adc r8,rdx +mov r12,QWORD [rsi+0x48] +mov rax,QWORD [rcx+0x40] +mul r12 +add r14,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add r15,rax +adc rdx,0x0 +add r15,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +adc r9,rdx +mov r12,QWORD [rsi+0x50] +mov rax,QWORD [rcx+0x40] +mul r12 +add r15,rax +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x48] +mul r12 +add rbx,rax +adc rdx,0x0 +add rbx,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x50] +mul r12 +add r8,rax +adc rdx,0x0 +add r8,rbp +mov rbp,0x0 +adc rbp,rdx +mov rax,QWORD [rcx+0x58] +mul r12 +add r9,rax +adc rdx,0x0 +add r9,rbp +adc r10,rdx +mov rsi,QWORD [rsi+0x58] +mov rax,QWORD [rcx+0x40] +mul rsi +add rbx,rax +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x48] +mul rsi +add r8,rax +adc rdx,0x0 +add r8,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x50] +mul rsi +add r9,rax +adc rdx,0x0 +add r9,r12 +mov r12,0x0 +adc r12,rdx +mov rax,QWORD [rcx+0x58] +mul rsi +add r10,rax +adc rdx,0x0 +add r10,r12 +adc r11,rdx +mov rax,r8 +mul QWORD [const_38] +mov rsi,rax +mov rax,r9 +mov rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,r10 +mov r8,0x0 +adc r8,rdx +mul QWORD [const_38] +add r8,rax +mov rax,r11 +mov r9,0x0 +adc r9,rdx +mul QWORD [const_38] +add r9,rax +mov rax,0x0 +adc rax,rdx +add r13,rsi +adc r14,rcx +adc r15,r8 +adc rbx,r9 +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r13,rdx +adc r14,rsi +adc r15,rsi +adc rbx,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r13,rsi +add r13,r13 +adc r14,r14 +adc r15,r15 +adc rbx,rbx +mov rsi,0x0 +mov rdx,0x26 +cmovae rdx,rsi +add r13,rdx +adc r14,rsi +adc r15,rsi +adc rbx,rsi +cmovb rsi,rdx +add r13,rsi +mov rsi,r13 +mov rdx,r14 +mov rcx,r15 +mov r8,rbx +add rsi,QWORD [rsp+0x38] +adc rdx,QWORD [rsp+0x40] +adc rcx,QWORD [rsp+0x48] +adc r8,QWORD [rsp+0x50] +mov r9,0x0 +mov rax,0x26 +cmovae rax,r9 +add rsi,rax +adc rdx,r9 +adc rcx,r9 +adc r8,r9 +cmovb r9,rax +add rsi,r9 +sub r13,QWORD [rsp+0x38] +sbb r14,QWORD [rsp+0x40] +sbb r15,QWORD [rsp+0x48] +sbb rbx,QWORD [rsp+0x50] +mov r9,0x0 +mov rax,0x26 +cmovae rax,r9 +sub r13,rax +sbb r14,r9 +sbb r15,r9 +sbb rbx,r9 +cmovb r9,rax +sub r13,r9 +mov QWORD [rdi+0x20],rsi +mov QWORD [rdi+0x28],rdx +mov QWORD [rdi+0x30],rcx +mov QWORD [rdi+0x38],r8 +mov QWORD [rdi+0x60],r13 +mov QWORD [rdi+0x68],r14 +mov QWORD [rdi+0x70],r15 +mov QWORD [rdi+0x78],rbx +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret + +sV_ge64_p2_dbl: +mov r11,rsp +and r11,0x1f +add r11,0xc0 +sub rsp,r11 +mov QWORD [rsp],r11 +mov QWORD [rsp+0x8],r12 +mov QWORD [rsp+0x10],r13 +mov QWORD [rsp+0x18],r14 +mov QWORD [rsp+0x20],r15 +mov QWORD [rsp+0x28],rbx +mov QWORD [rsp+0x30],rbp +mov rcx,0x0 +mov rax,QWORD [rsi+0x8] +mul QWORD [rsi] +mov r8,rax +mov r9,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi+0x8] +mov r10,rax +mov r11,rdx +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x10] +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi] +add r9,rax +adc r10,rdx +adc r11,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x8] +add r11,rax +adc r12,rdx +adc r13,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi] +add r10,rax +adc r11,rdx +adc r12,0x0 +adc r13,0x0 +adc rcx,0x0 +add r8,r8 +adc r9,r9 +adc r10,r10 +adc r11,r11 +adc r12,r12 +adc r13,r13 +adc rcx,rcx +mov rax,QWORD [rsi] +mul QWORD [rsi] +mov r14,rax +mov r15,rdx +mov rax,QWORD [rsi+0x8] +mul QWORD [rsi+0x8] +mov rbx,rax +mov rbp,rdx +mov rax,QWORD [rsi+0x10] +mul QWORD [rsi+0x10] +add r8,r15 +adc r9,rbx +adc r10,rbp +adc r11,rax +adc r12,rdx +adc r13,0x0 +adc rcx,0x0 +mov rax,QWORD [rsi+0x18] +mul QWORD [rsi+0x18] +add r13,rax +adc rcx,rdx +mov rax,r11 +mul QWORD [const_38] +mov r11,rax +mov rax,r12 +mov r12,rdx +mul QWORD [const_38] +add r12,rax +mov rax,r13 +mov r13,0x0 +adc r13,rdx +mul QWORD [const_38] +add r13,rax +mov rax,rcx +mov rcx,0x0 +adc rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,0x0 +adc rax,rdx +add r14,r11 +adc r8,r12 +adc r9,r13 +adc r10,rcx +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r14,rcx +adc r8,rdx +adc r9,rdx +adc r10,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r14,rdx +mov QWORD [rsp+0x38],r14 +mov QWORD [rsp+0x40],r8 +mov QWORD [rsp+0x48],r9 +mov QWORD [rsp+0x50],r10 +mov rcx,0x0 +mov rax,QWORD [rsi+0x28] +mul QWORD [rsi+0x20] +mov r8,rax +mov r9,rdx +mov rax,QWORD [rsi+0x30] +mul QWORD [rsi+0x28] +mov r10,rax +mov r11,rdx +mov rax,QWORD [rsi+0x38] +mul QWORD [rsi+0x30] +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x30] +mul QWORD [rsi+0x20] +add r9,rax +adc r10,rdx +adc r11,0x0 +mov rax,QWORD [rsi+0x38] +mul QWORD [rsi+0x28] +add r11,rax +adc r12,rdx +adc r13,0x0 +mov rax,QWORD [rsi+0x38] +mul QWORD [rsi+0x20] +add r10,rax +adc r11,rdx +adc r12,0x0 +adc r13,0x0 +adc rcx,0x0 +add r8,r8 +adc r9,r9 +adc r10,r10 +adc r11,r11 +adc r12,r12 +adc r13,r13 +adc rcx,rcx +mov rax,QWORD [rsi+0x20] +mul QWORD [rsi+0x20] +mov r14,rax +mov r15,rdx +mov rax,QWORD [rsi+0x28] +mul QWORD [rsi+0x28] +mov rbx,rax +mov rbp,rdx +mov rax,QWORD [rsi+0x30] +mul QWORD [rsi+0x30] +add r8,r15 +adc r9,rbx +adc r10,rbp +adc r11,rax +adc r12,rdx +adc r13,0x0 +adc rcx,0x0 +mov rax,QWORD [rsi+0x38] +mul QWORD [rsi+0x38] +add r13,rax +adc rcx,rdx +mov rax,r11 +mul QWORD [const_38] +mov r11,rax +mov rax,r12 +mov r12,rdx +mul QWORD [const_38] +add r12,rax +mov rax,r13 +mov r13,0x0 +adc r13,rdx +mul QWORD [const_38] +add r13,rax +mov rax,rcx +mov rcx,0x0 +adc rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,0x0 +adc rax,rdx +add r14,r11 +adc r8,r12 +adc r9,r13 +adc r10,rcx +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r14,rcx +adc r8,rdx +adc r9,rdx +adc r10,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r14,rdx +mov QWORD [rsp+0x58],r14 +mov QWORD [rsp+0x60],r8 +mov QWORD [rsp+0x68],r9 +mov QWORD [rsp+0x70],r10 +mov rcx,0x0 +mov rax,QWORD [rsi+0x48] +mul QWORD [rsi+0x40] +mov r8,rax +mov r9,rdx +mov rax,QWORD [rsi+0x50] +mul QWORD [rsi+0x48] +mov r10,rax +mov r11,rdx +mov rax,QWORD [rsi+0x58] +mul QWORD [rsi+0x50] +mov r12,rax +mov r13,rdx +mov rax,QWORD [rsi+0x50] +mul QWORD [rsi+0x40] +add r9,rax +adc r10,rdx +adc r11,0x0 +mov rax,QWORD [rsi+0x58] +mul QWORD [rsi+0x48] +add r11,rax +adc r12,rdx +adc r13,0x0 +mov rax,QWORD [rsi+0x58] +mul QWORD [rsi+0x40] +add r10,rax +adc r11,rdx +adc r12,0x0 +adc r13,0x0 +adc rcx,0x0 +add r8,r8 +adc r9,r9 +adc r10,r10 +adc r11,r11 +adc r12,r12 +adc r13,r13 +adc rcx,rcx +mov rax,QWORD [rsi+0x40] +mul QWORD [rsi+0x40] +mov r14,rax +mov r15,rdx +mov rax,QWORD [rsi+0x48] +mul QWORD [rsi+0x48] +mov rbx,rax +mov rbp,rdx +mov rax,QWORD [rsi+0x50] +mul QWORD [rsi+0x50] +add r8,r15 +adc r9,rbx +adc r10,rbp +adc r11,rax +adc r12,rdx +adc r13,0x0 +adc rcx,0x0 +mov rax,QWORD [rsi+0x58] +mul QWORD [rsi+0x58] +add r13,rax +adc rcx,rdx +mov rax,r11 +mul QWORD [const_38] +mov r11,rax +mov rax,r12 +mov r12,rdx +mul QWORD [const_38] +add r12,rax +mov rax,r13 +mov r13,0x0 +adc r13,rdx +mul QWORD [const_38] +add r13,rax +mov rax,rcx +mov rcx,0x0 +adc rcx,rdx +mul QWORD [const_38] +add rcx,rax +mov rax,0x0 +adc rax,rdx +add r14,r11 +adc r8,r12 +adc r9,r13 +adc r10,rcx +mov rdx,0x0 +adc rax,rdx +imul rcx,rax,0x26 +add r14,rcx +adc r8,rdx +adc r9,rdx +adc r10,rdx +adc rdx,rdx +imul rdx,rdx,0x26 +add r14,rdx +add r14,r14 +adc r8,r8 +adc r9,r9 +adc r10,r10 +mov rdx,0x0 +mov rcx,0x26 +cmovae rcx,rdx +add r14,rcx +adc r8,rdx +adc r9,rdx +adc r10,rdx +cmovb rdx,rcx +add r14,rdx +mov QWORD [rsp+0x78],r14 +mov QWORD [rsp+0x80],r8 +mov QWORD [rsp+0x88],r9 +mov QWORD [rsp+0x90],r10 +mov rdx,0x0 +mov rcx,0x0 +mov r8,0x0 +mov r9,0x0 +sub rdx,QWORD [rsp+0x38] +sbb rcx,QWORD [rsp+0x40] +sbb r8,QWORD [rsp+0x48] +sbb r9,QWORD [rsp+0x50] +mov rax,0x0 +mov r10,0x26 +cmovae r10,rax +sub rdx,r10 +sbb rcx,rax +sbb r8,rax +sbb r9,rax +cmovb rax,r10 +sub rdx,rax +mov QWORD [rsp+0x38],rdx +mov QWORD [rsp+0x40],rcx +mov QWORD [rsp+0x48],r8 +mov QWORD [rsp+0x50],r9 +mov rax,0x0 +mov r10,0x0 +mov r11,0x0 +mov r12,0x0 +sub rax,QWORD [rsp+0x58] +sbb r10,QWORD [rsp+0x60] +sbb r11,QWORD [rsp+0x68] +sbb r12,QWORD [rsp+0x70] +mov r13,0x0 +mov r14,0x26 +cmovae r14,r13 +sub rax,r14 +sbb r10,r13 +sbb r11,r13 +sbb r12,r13 +cmovb r13,r14 +sub rax,r13 +mov QWORD [rsp+0x98],rax +mov QWORD [rsp+0xa0],r10 +mov QWORD [rsp+0xa8],r11 +mov QWORD [rsp+0xb0],r12 +mov rax,rdx +mov r10,rcx +mov r11,r8 +mov r12,r9 +add rax,QWORD [rsp+0x58] +adc r10,QWORD [rsp+0x60] +adc r11,QWORD [rsp+0x68] +adc r12,QWORD [rsp+0x70] +mov r13,0x0 +mov r14,0x26 +cmovae r14,r13 +add rax,r14 +adc r10,r13 +adc r11,r13 +adc r12,r13 +cmovb r13,r14 +add rax,r13 +mov QWORD [rdi+0x20],rax +mov QWORD [rdi+0x28],r10 +mov QWORD [rdi+0x30],r11 +mov QWORD [rdi+0x38],r12 +sub rdx,QWORD [rsp+0x58] +sbb rcx,QWORD [rsp+0x60] +sbb r8,QWORD [rsp+0x68] +sbb r9,QWORD [rsp+0x70] +mov r13,0x0 +mov r14,0x26 +cmovae r14,r13 +sub rdx,r14 +sbb rcx,r13 +sbb r8,r13 +sbb r9,r13 +cmovb r13,r14 +sub rdx,r13 +mov QWORD [rdi+0x40],rdx +mov QWORD [rdi+0x48],rcx +mov QWORD [rdi+0x50],r8 +mov QWORD [rdi+0x58],r9 +sub rax,QWORD [rsp+0x78] +sbb r10,QWORD [rsp+0x80] +sbb r11,QWORD [rsp+0x88] +sbb r12,QWORD [rsp+0x90] +mov rdx,0x0 +mov rcx,0x26 +cmovae rcx,rdx +sub rax,rcx +sbb r10,rdx +sbb r11,rdx +sbb r12,rdx +cmovb rdx,rcx +sub rax,rdx +mov QWORD [rdi+0x60],rax +mov QWORD [rdi+0x68],r10 +mov QWORD [rdi+0x70],r11 +mov QWORD [rdi+0x78],r12 +mov rdx,QWORD [rsi] +mov rcx,QWORD [rsi+0x8] +mov r8,QWORD [rsi+0x10] +mov r9,QWORD [rsi+0x18] +add rdx,QWORD [rsi+0x20] +adc rcx,QWORD [rsi+0x28] +adc r8,QWORD [rsi+0x30] +adc r9,QWORD [rsi+0x38] +mov rsi,0x0 +mov rax,0x26 +cmovae rax,rsi +add rdx,rax +adc rcx,rsi +adc r8,rsi +adc r9,rsi +cmovb rsi,rax +add rdx,rsi +mov QWORD [rsp+0x58],rdx +mov QWORD [rsp+0x60],rcx +mov QWORD [rsp+0x68],r8 +mov QWORD [rsp+0x70],r9 +mov rsi,0x0 +mov rax,QWORD [rsp+0x60] +mul QWORD [rsp+0x58] +mov rcx,rax +mov r8,rdx +mov rax,QWORD [rsp+0x68] +mul QWORD [rsp+0x60] +mov r9,rax +mov r10,rdx +mov rax,QWORD [rsp+0x70] +mul QWORD [rsp+0x68] +mov r11,rax +mov r12,rdx +mov rax,QWORD [rsp+0x68] +mul QWORD [rsp+0x58] +add r8,rax +adc r9,rdx +adc r10,0x0 +mov rax,QWORD [rsp+0x70] +mul QWORD [rsp+0x60] +add r10,rax +adc r11,rdx +adc r12,0x0 +mov rax,QWORD [rsp+0x70] +mul QWORD [rsp+0x58] +add r9,rax +adc r10,rdx +adc r11,0x0 +adc r12,0x0 +adc rsi,0x0 +add rcx,rcx +adc r8,r8 +adc r9,r9 +adc r10,r10 +adc r11,r11 +adc r12,r12 +adc rsi,rsi +mov rax,QWORD [rsp+0x58] +mul QWORD [rsp+0x58] +mov r13,rax +mov r14,rdx +mov rax,QWORD [rsp+0x60] +mul QWORD [rsp+0x60] +mov r15,rax +mov rbx,rdx +mov rax,QWORD [rsp+0x68] +mul QWORD [rsp+0x68] +add rcx,r14 +adc r8,r15 +adc r9,rbx +adc r10,rax +adc r11,rdx +adc r12,0x0 +adc rsi,0x0 +mov rax,QWORD [rsp+0x70] +mul QWORD [rsp+0x70] +add r12,rax +adc rsi,rdx +mov rax,r10 +mul QWORD [const_38] +mov r10,rax +mov rax,r11 +mov r11,rdx +mul QWORD [const_38] +add r11,rax +mov rax,r12 +mov r12,0x0 +adc r12,rdx +mul QWORD [const_38] +add r12,rax +mov rax,rsi +mov rsi,0x0 +adc rsi,rdx +mul QWORD [const_38] +add rsi,rax +mov rax,0x0 +adc rax,rdx +add r13,r10 +adc rcx,r11 +adc r8,r12 +adc r9,rsi +mov rsi,0x0 +adc rax,rsi +imul rdx,rax,0x26 +add r13,rdx +adc rcx,rsi +adc r8,rsi +adc r9,rsi +adc rsi,rsi +imul rsi,rsi,0x26 +add r13,rsi +add r13,QWORD [rsp+0x38] +adc rcx,QWORD [rsp+0x40] +adc r8,QWORD [rsp+0x48] +adc r9,QWORD [rsp+0x50] +mov rsi,0x0 +mov rdx,0x26 +cmovae rdx,rsi +add r13,rdx +adc rcx,rsi +adc r8,rsi +adc r9,rsi +cmovb rsi,rdx +add r13,rsi +add r13,QWORD [rsp+0x98] +adc rcx,QWORD [rsp+0xa0] +adc r8,QWORD [rsp+0xa8] +adc r9,QWORD [rsp+0xb0] +mov rsi,0x0 +mov rdx,0x26 +cmovae rdx,rsi +add r13,rdx +adc rcx,rsi +adc r8,rsi +adc r9,rsi +cmovb rsi,rdx +add r13,rsi +mov QWORD [rdi],r13 +mov QWORD [rdi+0x8],rcx +mov QWORD [rdi+0x10],r8 +mov QWORD [rdi+0x18],r9 +mov r11,QWORD [rsp] +mov r12,QWORD [rsp+0x8] +mov r13,QWORD [rsp+0x10] +mov r14,QWORD [rsp+0x18] +mov r15,QWORD [rsp+0x20] +mov rbx,QWORD [rsp+0x28] +mov rbp,QWORD [rsp+0x30] +add rsp,r11 +mov rax,rdi +mov rdx,rsi +ret diff --git a/src/crypto/ecops64/ecops64.h b/src/crypto/ecops64/ecops64.h new file mode 100644 index 00000000..14b2ecf2 --- /dev/null +++ b/src/crypto/ecops64/ecops64.h @@ -0,0 +1,152 @@ +// Copyright (c) 2019, Ryo Currency Project +// +// Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details +// All rights reserved. +// +// Authors and copyright holders give permission for following: +// +// 1. Redistribution and use in source and binary forms WITHOUT modification. +// +// 2. Modification of the source form for your own personal use. +// +// As long as the following conditions are met: +// +// 3. You must not distribute modified copies of the work to third parties. This includes +// posting the work online, or hosting copies of the modified work for download. +// +// 4. Any derivative version of this work is also covered by this license, including point 8. +// +// 5. Neither the name of the copyright holders nor the names of the authors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// 6. You agree that this licence is governed by and shall be construed in accordance +// with the laws of England and Wales. +// +// 7. You agree to submit all disputes arising out of or in connection with this licence +// to the exclusive jurisdiction of the Courts of England and Wales. +// +// Authors and copyright holders agree that: +// +// 8. This licence expires and the work covered by it is released into the +// public domain on 1st of February 2020 +// +// 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. + +// Based on Dr Bernstein's public domain code. +// https://bench.cr.yp.to/supercop.html + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + + typedef uint64_t fe64[4]; + + typedef struct + { + fe64 x; + fe64 y; + fe64 z; + fe64 t; + } ge64_p3; + + typedef struct + { + fe64 x; + fe64 z; + fe64 y; + fe64 t; + } ge64_p1p1; + + typedef struct + { + fe64 x; + fe64 y; + fe64 z; + } ge64_p2; + + typedef struct + { + fe64 ysubx; + fe64 xaddy; + fe64 t2d; + } ge64_niels; + + typedef struct + { + fe64 ysubx; + fe64 xaddy; + fe64 z; + fe64 t2d; + } ge64_pniels; + + ///// EXTERN ASM + void sV_fe64_mul(fe64 r, const fe64 x, const fe64 y); + void sV_fe64_square(fe64 r, const fe64 x); + void sV_fe64_add(fe64 r, const fe64 x, const fe64 y); + void sV_fe64_sub(fe64 r, const fe64 x, const fe64 y); + void sV_fe64_reduce(fe64 r); + void sV_ge64_add(ge64_p1p1* r, const ge64_p3* p, const ge64_p3* q); + void sV_ge64_p1p1_to_p2(ge64_p2* r, const ge64_p1p1* p); + void sV_ge64_p1p1_to_p3(ge64_p3* r, const ge64_p1p1* p); + void sV_ge64_nielsadd2(ge64_p3* r, const ge64_niels* q); + void sV_ge64_pnielsadd_p1p1(ge64_p1p1* r, const ge64_p3* p, + const ge64_pniels* q); + void sV_ge64_p2_dbl(ge64_p1p1* r, const ge64_p2* p); + +#ifdef _WIN32 + void win64_wrapper(void* f, ...); +#define fe64_mul(r, x, y) win64_wrapper(sV_fe64_mul, r, x, y) +#define fe64_square(r, x) win64_wrapper(sV_fe64_square, r, x) +#define fe64_add(r, x, y) win64_wrapper(sV_fe64_add, r, x, y) +#define fe64_sub(r, x, y) win64_wrapper(sV_fe64_sub, r, x, y) +#define fe64_reduce(r) win64_wrapper(sV_fe64_reduce, r) +#define ge64_add(r, p, q) win64_wrapper(sV_ge64_add, r, p, q) +#define ge64_p1p1_to_p2(r, p) win64_wrapper(sV_ge64_p1p1_to_p2, r, p) +#define ge64_p1p1_to_p3(r, p) win64_wrapper(sV_ge64_p1p1_to_p3, r, p) +#define ge64_nielsadd2(r, q) win64_wrapper(sV_ge64_nielsadd2, r, q) +#define ge64_pnielsadd_p1p1(r, p, q) \ + win64_wrapper(sV_ge64_pnielsadd_p1p1, r, p, q) +#define ge64_p2_dbl(r, p) win64_wrapper(sV_ge64_p2_dbl, r, p) +#else +#define fe64_mul sV_fe64_mul +#define fe64_square sV_fe64_square +#define fe64_add sV_fe64_add +#define fe64_sub sV_fe64_sub +#define fe64_reduce sV_fe64_reduce +#define ge64_add sV_ge64_add +#define ge64_p1p1_to_p2 sV_ge64_p1p1_to_p2 +#define ge64_p1p1_to_p3 sV_ge64_p1p1_to_p3 +#define ge64_nielsadd2 sV_ge64_nielsadd2 +#define ge64_pnielsadd_p1p1 sV_ge64_pnielsadd_p1p1 +#define ge64_p2_dbl sV_ge64_p2_dbl +#endif // !_WIN32 + + ///// C FUNCTIONS + void ge64_p3_to_p2(ge64_p2* r, const ge64_p3* p); + void ge64_mul8(ge64_p1p1* r, const ge64_p2* t); + int ge64_frombytes_vartime(ge64_p3* h, const unsigned char p[32]); + void ge64_tobytes(unsigned char s[32], const ge64_p2* h); + void sc64_reduce32(unsigned char x[32]); + void ge64_scalarmult_base(ge64_p3* r, const unsigned char s[32]); + void ge64_scalarmult(ge64_p2* r, const unsigned char a[32], const ge64_p3* A); + + void ge64_sub(ge64_p1p1* r, const ge64_p3* p, const ge64_p3* q); + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/src/crypto/generic-ops.h b/src/crypto/generic-ops.h index 8075b353..76477987 100644 --- a/src/crypto/generic-ops.h +++ b/src/crypto/generic-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index 14dc29bb..65443f0d 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/hash.c b/src/crypto/hash.c index 74dfaddb..fc7e6845 100644 --- a/src/crypto/hash.c +++ b/src/crypto/hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/crypto/hash.h b/src/crypto/hash.h index 591f6899..a71ec71c 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,12 +20,14 @@ #pragma once +#include "fmt/format.h" #include #include #include #include "generic-ops.h" #include "hex.h" +#include "string_tools.h" #include "span.h" namespace crypto @@ -85,5 +87,17 @@ const static crypto::hash null_hash = boost::value_initialized(); const static crypto::hash8 null_hash8 = boost::value_initialized(); } +namespace fmt +{ +template <> +struct formatter : formatter +{ + template + auto format(const crypto::hash &hash, FormatContext &ctx) -> decltype(ctx.out()) + { + return formatter::format(epee::string_tools::pod_to_hex(hash), ctx); + } +}; +} CRYPTO_MAKE_HASHABLE(hash) CRYPTO_MAKE_COMPARABLE(hash8) diff --git a/src/crypto/pow_hash/cn_slow_hash.hpp b/src/crypto/pow_hash/cn_slow_hash.hpp index 57b9a7e5..c44d7e8e 100644 --- a/src/crypto/pow_hash/cn_slow_hash.hpp +++ b/src/crypto/pow_hash/cn_slow_hash.hpp @@ -71,7 +71,10 @@ inline bool check_avx2() { int32_t cpu_info[4]; cpuid(7, 0, cpu_info); - return (cpu_info[1] & (1 << 5)) != 0; + const bool has_avx2 = (cpu_info[1] & (1 << 5)) != 0; + cpuid(1, 0, cpu_info); + const bool osxsave = (cpu_info[2] & (1 << 27)) != 0; + return has_avx2 && osxsave; } #endif @@ -116,7 +119,7 @@ class cn_sptr inline int32_t& as_dword(size_t i) { return *(reinterpret_cast(base_ptr) + i); } inline uint32_t& as_udword(size_t i) { return *(reinterpret_cast(base_ptr) + i); } inline const uint32_t& as_udword(size_t i) const { return *(reinterpret_cast(base_ptr) + i); } - + template inline cast_t* as_ptr() { return reinterpret_cast(base_ptr); } diff --git a/src/crypto/pow_hash/cn_slow_hash_soft.cpp b/src/crypto/pow_hash/cn_slow_hash_soft.cpp index acead47a..bb87d207 100644 --- a/src/crypto/pow_hash/cn_slow_hash_soft.cpp +++ b/src/crypto/pow_hash/cn_slow_hash_soft.cpp @@ -410,6 +410,27 @@ void cn_slow_hash::explode_scratchpad_soft() } } +#if defined(__arm__) +inline void generate_512(uint64_t idx, const uint64_t* in, uint8_t* out) +{ + constexpr size_t hash_size = 200; // 25x8 bytes + alignas(8) uint64_t hash[25]; + + memcpy(hash, in, hash_size); + hash[0] ^= idx; + + keccakf(hash); + memcpy(out, hash, 160); + out += 160; + + keccakf(hash); + memcpy(out, hash, 176); + out += 176; + + keccakf(hash); + memcpy(out, hash, 176); +} +#else inline void generate_512(uint64_t idx, const uint64_t* in, uint8_t* out) { constexpr size_t hash_size = 200; // 25x8 bytes @@ -429,6 +450,7 @@ inline void generate_512(uint64_t idx, const uint64_t* in, uint8_t* out) keccakf(hash); memcpy(out, hash, 176); } +#endif template void cn_slow_hash::explode_scratchpad_3() diff --git a/src/crypto/random.cpp b/src/crypto/random.cpp index 00229f95..a1c9d3b3 100644 --- a/src/crypto/random.cpp +++ b/src/crypto/random.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // // All rights reserved. // @@ -60,13 +60,13 @@ prng::~prng() # if defined(_WIN32) if(!CryptReleaseContext(hnd->prov, 0)) { - std::cerr << "CryptReleaseContext" << std::endl; + GULPS_ERROR("CryptReleaseContext"); std::abort(); } # else if(close(hnd->fd) < 0) { - std::cerr << "Exit Failure :: close /dev/urandom " << std::endl; + GULPS_ERROR("Exit Failure :: close /dev/urandom "); std::abort(); } # endif @@ -78,18 +78,18 @@ void prng::start() { hnd = new prng_handle; #if defined(CRYPTO_TEST_ONLY_FIXED_PRNG) - std::cerr << "WARNING!!! Fixed PRNG is active! This should be done in tests only!" << std::endl; + GULPS_ERROR("WARNING!!! Fixed PRNG is active! This should be done in tests only!"); return; #elif defined(_WIN32) if(!CryptAcquireContext(&hnd->prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { - std::cerr << "CryptAcquireContext Failed " << std::endl; + GULPS_ERROR("CryptAcquireContext Failed "); std::abort(); } #else if((hnd->fd = open("/dev/urandom", O_RDONLY | O_NOCTTY | O_CLOEXEC)) < 0) { - std::cerr << "Exit Failure :: open /dev/urandom" << std::endl; + GULPS_ERROR("Exit Failure :: open /dev/urandom"); std::abort(); } #endif @@ -98,7 +98,7 @@ void prng::start() if(test[0] == 0 && test[1] == 0) { - std::cerr << "PRNG self-check failed!" << std::endl; + GULPS_ERROR("PRNG self-check failed!"); std::abort(); } } @@ -125,7 +125,7 @@ void prng::generate_random(uint8_t* output, size_t size_bytes) output += 200; size_bytes -= 200; } - + if(size_bytes > 0) { uint8_t last[200]; @@ -149,7 +149,7 @@ void prng::generate_system_random_bytes(uint8_t* result, size_t n) #elif defined(_WIN32) if(!CryptGenRandom(hnd->prov, (DWORD)n, result)) { - std::cerr << "CryptGenRandom Failed " << std::endl; + GULPS_ERROR("CryptGenRandom Failed "); std::abort(); } #else @@ -164,13 +164,13 @@ void prng::generate_system_random_bytes(uint8_t* result, size_t n) { if(errno != EINTR) { - std::cerr << "EXIT_FAILURE :: read /dev/urandom" << std::endl; + GULPS_ERROR("EXIT_FAILURE :: read /dev/urandom"); std::abort(); } } else if(res == 0) { - std::cerr << "EXIT_FAILURE :: read /dev/urandom: end of file " << std::endl; + GULPS_ERROR("EXIT_FAILURE :: read /dev/urandom: end of file "); std::abort(); } else @@ -178,6 +178,6 @@ void prng::generate_system_random_bytes(uint8_t* result, size_t n) result += res; n -= (size_t)res; } - } + } #endif } diff --git a/src/crypto/random.hpp b/src/crypto/random.hpp index 5debcb5b..7737e9c3 100644 --- a/src/crypto/random.hpp +++ b/src/crypto/random.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // // All rights reserved. // @@ -16,12 +16,14 @@ #pragma once +#include "common/gulps.hpp" #include struct prng_handle; class prng { + GULPS_CAT_MAJOR("random"); public: prng() {} ~prng(); @@ -38,7 +40,7 @@ class prng /** * @brief Get singleton instance. One instance exists per thread. - * + * * @return Singleton reference */ diff --git a/src/crypto/tree-hash.c b/src/crypto/tree-hash.c index 2e86c444..480021b1 100644 --- a/src/crypto/tree-hash.c +++ b/src/crypto/tree-hash.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index 9ecc1cfa..279e51c7 100644 --- a/src/cryptonote_basic/CMakeLists.txt +++ b/src/cryptonote_basic/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -92,5 +92,6 @@ target_link_libraries(cryptonote_basic ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index b3ccc1f9..5a679766 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,8 +30,10 @@ extern "C" { #include "cryptonote_basic_impl.h" #include "cryptonote_format_utils.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "account" +#include "common/gulps.hpp" + + +GULPS_CAT_MAJOR("crybas_account"); using namespace std; @@ -49,19 +51,9 @@ hw::device &account_keys::get_device() const void account_keys::set_device(hw::device &hwdev) { m_device = &hwdev; - MCDEBUG("device", "account_keys::set_device device type: " << typeid(hwdev).name()); + GULPS_CAT_LOG_L1("device", "account_keys::set_device device type: ", typeid(hwdev).name()); } -//----------------------------------------------------------------- -account_base::account_base() -{ - set_null(); -} -//----------------------------------------------------------------- -void account_base::set_null() -{ - m_keys = account_keys(); -} //----------------------------------------------------------------- void account_base::forget_spend_key() { @@ -144,7 +136,7 @@ void account_base::create_from_device(const std::string &device_name) hw::device &hwdev = hw::get_device(device_name); m_keys.set_device(hwdev); hwdev.set_name(device_name); - MCDEBUG("ledger", "device type: " << typeid(hwdev).name()); + GULPS_CAT_LOG_L1("ledger", "device type: ", typeid(hwdev).name()); hwdev.init(); hwdev.connect(); hwdev.get_public_address(m_keys.m_account_address); @@ -191,7 +183,7 @@ std::string account_base::get_public_address_str(network_type nettype) const case STAGENET: return get_public_address_as_str(false, m_keys.m_account_address); default: - CHECK_AND_ASSERT_THROW_MES(false, "Unknown nettype"); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "Unknown nettype"); } } //----------------------------------------------------------------- @@ -206,7 +198,7 @@ std::string account_base::get_public_integrated_address_str(const crypto::hash8 case STAGENET: return get_account_integrated_address_as_str(m_keys.m_account_address, payment_id); default: - CHECK_AND_ASSERT_THROW_MES(false, "Unknown nettype"); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "Unknown nettype"); } } //----------------------------------------------------------------- diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index fb5469c6..5b908271 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -39,7 +39,7 @@ struct account_keys crypto::secret_key_16 m_short_seed; hw::device *m_device = &hw::get_device("default"); - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(account_keys) KV_SERIALIZE(m_account_address) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key) @@ -59,7 +59,6 @@ struct account_keys class account_base { public: - account_base(); inline crypto::secret_key_16 generate_new(uint8_t acc_opt) { @@ -115,7 +114,7 @@ class account_base static constexpr uint64_t EARLIEST_TIMESTAMP = 1483228800; // 01-01-2017 00:00 - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(account_base) KV_SERIALIZE(m_keys) KV_SERIALIZE(m_creation_timestamp) KV_SERIALIZE(m_acc_opt) @@ -123,9 +122,8 @@ class account_base private: crypto::secret_key_16 generate(); - void set_null(); - account_keys m_keys; + account_keys m_keys = account_keys(); uint64_t m_creation_timestamp; uint8_t m_acc_opt; }; diff --git a/src/cryptonote_basic/account_boost_serialization.h b/src/cryptonote_basic/account_boost_serialization.h index e5a38f53..710064e3 100644 --- a/src/cryptonote_basic/account_boost_serialization.h +++ b/src/cryptonote_basic/account_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/blobdatatype.h b/src/cryptonote_basic/blobdatatype.h index 4a34b478..bea0814e 100644 --- a/src/cryptonote_basic/blobdatatype.h +++ b/src/cryptonote_basic/blobdatatype.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h index 3dfb976a..cd4af904 100644 --- a/src/cryptonote_basic/connection_context.h +++ b/src/cryptonote_basic/connection_context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 25e1ae75..c17f3db4 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -428,6 +428,9 @@ struct block : public block_header /************************************************************************/ struct account_public_address { + account_public_address(const crypto::public_key m_spend_public_key, const crypto::public_key m_view_public_key) : m_spend_public_key(m_spend_public_key), + m_view_public_key(m_view_public_key) {} + crypto::public_key m_spend_public_key; crypto::public_key m_view_public_key; @@ -436,7 +439,7 @@ struct account_public_address FIELD(m_view_public_key) END_SERIALIZE() - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(account_public_address) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key) END_KV_SERIALIZE_MAP() diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 7a686f81..f0c26d5e 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -19,7 +19,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "include_base_utils.h" -using namespace epee; +#include "common/gulps.hpp" #include "common/base58.h" #include "common/dns_utils.h" @@ -33,14 +33,17 @@ using namespace epee; #include "serialization/container.h" #include "string_tools.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("basic_util"); namespace cryptonote { struct integrated_address { + integrated_address(account_public_address adr, crypto::hash8 payment_id) : adr(adr), payment_id(payment_id) {} + account_public_address adr; crypto::hash8 payment_id; @@ -49,7 +52,7 @@ struct integrated_address FIELD(payment_id) END_SERIALIZE() - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(integrated_address) KV_SERIALIZE(adr) KV_SERIALIZE(payment_id) END_KV_SERIALIZE_MAP() @@ -57,13 +60,15 @@ struct integrated_address struct kurz_address { + kurz_address(crypto::public_key m_public_key) : m_public_key(m_public_key) {} + crypto::public_key m_public_key; BEGIN_SERIALIZE_OBJECT() FIELD(m_public_key) END_SERIALIZE() - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(kurz_address) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_public_key) END_KV_SERIALIZE_MAP() }; @@ -106,42 +111,24 @@ template bool get_dev_fund_amount(uint64_t height, uint64_t& amount); template bool get_dev_fund_amount(uint64_t height, uint64_t& amount); //----------------------------------------------------------------------------------------------- -bool get_block_reward(network_type nettype, size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint64_t height) +uint64_t get_base_reward_tabular(uint64_t height, uint64_t already_generated_coins) { - uint64_t base_reward; - uint64_t round_factor = 10000000; // 1 * pow(10, 7) - if(height > 0) - { - if(height < (PEAK_COIN_EMISSION_HEIGHT + COIN_EMISSION_HEIGHT_INTERVAL)) - { - uint64_t interval_num = height / COIN_EMISSION_HEIGHT_INTERVAL; - double money_supply_pct = 0.1888 + interval_num * (0.023 + interval_num * 0.0032); - base_reward = ((uint64_t)(MONEY_SUPPLY * money_supply_pct)) >> EMISSION_SPEED_FACTOR; - } - else - { - base_reward = (MONEY_SUPPLY - already_generated_coins) >> EMISSION_SPEED_FACTOR; - } - } - else - { + uint64_t interval_num = std::min(uint64_t(height / COIN_EMISSION_HEIGHT_INTERVAL), uint64_t(COIN_EMISSION_STEPS.size() - 1llu)); + + uint64_t base_reward = 0; + if(height == 0) base_reward = GENESIS_BLOCK_REWARD; - } + else if(already_generated_coins < MONEY_SUPPLY) + base_reward = COIN_EMISSION_STEPS[interval_num]; + else + base_reward = FINAL_SUBSIDY; - if(base_reward < FINAL_SUBSIDY) - { - if(MONEY_SUPPLY > already_generated_coins) - { - base_reward = FINAL_SUBSIDY; - } - else - { - base_reward = FINAL_SUBSIDY / 2; - } - } + return base_reward; +} - // rounding (floor) base reward - base_reward = base_reward / round_factor * round_factor; +bool get_block_reward(network_type nettype, size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint64_t height) +{ + uint64_t base_reward = get_base_reward_tabular(height, already_generated_coins); //make it soft if(median_size < common_config::CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) @@ -151,7 +138,7 @@ bool get_block_reward(network_type nettype, size_t median_size, size_t current_b if(current_block_size > 2 * median_size) { - MERROR("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); + GULPSF_ERROR("Block cumulative size is too big: {}, expected less than {}", current_block_size, 2 * median_size); return false; } @@ -213,7 +200,7 @@ std::string get_public_address_as_str(bool subaddress, account_public_address co else address_prefix = config::RYO_KURZ_ADDRESS_BASE58_PREFIX; - kurz_address kadr = {adr.m_spend_public_key}; + kurz_address kadr(adr.m_spend_public_key); return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(kadr)); } else @@ -237,7 +224,7 @@ std::string get_account_integrated_address_as_str(account_public_address const & { uint64_t integrated_address_prefix = config::RYO_LONG_INTEGRATED_ADDRESS_BASE58_PREFIX; - integrated_address iadr = {adr, payment_id}; + integrated_address iadr(adr, payment_id); return tools::base58::encode_addr(integrated_address_prefix, t_serializable_object_to_blob(iadr)); } @@ -258,14 +245,13 @@ bool is_coinbase(const transaction &tx) } //----------------------------------------------------------------------- template -bool get_account_address_from_str(address_parse_info &info, std::string const &str, const bool silent) +bool get_account_address_from_str(address_parse_info &info, std::string const &str) { blobdata data; uint64_t prefix; if(!tools::base58::decode_addr(str, prefix, data)) { - if(!silent) - LOG_PRINT_L2("Invalid address format"); + GULPS_ERROR("Invalid address format"); return false; } @@ -295,8 +281,7 @@ bool get_account_address_from_str(address_parse_info &info, std::string const &s break; */ default: - if(!silent) - LOG_PRINT_L1("Wrong address prefix: " << prefix); + GULPS_ERROR("Wrong address prefix: "_s + std::to_string(prefix)); return false; } @@ -305,8 +290,7 @@ bool get_account_address_from_str(address_parse_info &info, std::string const &s integrated_address iadr; if(!::serialization::parse_binary(data, iadr)) { - if(!silent) - LOG_PRINT_L1("Account public address keys can't be parsed"); + GULPS_ERROR("Account public address keys can't be parsed"); return false; } info.address = iadr.adr; @@ -317,8 +301,7 @@ bool get_account_address_from_str(address_parse_info &info, std::string const &s kurz_address kadr; if(!::serialization::parse_binary(data, kadr)) { - if(!silent) - LOG_PRINT_L1("Account public address keys can't be parsed"); + GULPS_ERROR("Account public address keys can't be parsed"); return false; } @@ -329,25 +312,23 @@ bool get_account_address_from_str(address_parse_info &info, std::string const &s { if(!::serialization::parse_binary(data, info.address)) { - if(!silent) - LOG_PRINT_L1("Account public address keys can't be parsed"); + GULPS_ERROR("Account public address keys can't be parsed"); return false; } } if(!crypto::check_key(info.address.m_spend_public_key) || !crypto::check_key(info.address.m_view_public_key)) { - if(!silent) - LOG_PRINT_L1("Failed to validate address keys"); + GULPS_ERROR("Failed to validate address keys"); return false; } return true; } -template bool get_account_address_from_str(address_parse_info &, std::string const &, const bool); -template bool get_account_address_from_str(address_parse_info &, std::string const &, const bool); -template bool get_account_address_from_str(address_parse_info &, std::string const &, const bool); +template bool get_account_address_from_str(address_parse_info &, std::string const &); +template bool get_account_address_from_str(address_parse_info &, std::string const &); +template bool get_account_address_from_str(address_parse_info &, std::string const &); //-------------------------------------------------------------------------------- bool operator==(const cryptonote::transaction &a, const cryptonote::transaction &b) @@ -368,7 +349,7 @@ bool parse_hash256(const std::string str_hash, crypto::hash &hash) bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); if(!res || buf.size() != sizeof(crypto::hash)) { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; + GULPSF_ERROR("invalid hash format: <{}>", str_hash); return false; } else diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index 68b5d9e6..107155ce 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -152,18 +152,18 @@ inline std::string get_account_integrated_address_as_str(network_type nettype, c } template -bool get_account_address_from_str(address_parse_info &info, const std::string &str, const bool silent = false); +bool get_account_address_from_str(address_parse_info &info, const std::string &str); -inline bool get_account_address_from_str(network_type nettype, address_parse_info &info, const std::string &str, const bool silent = false) +inline bool get_account_address_from_str(network_type nettype, address_parse_info &info, const std::string &str) { switch(nettype) { case MAINNET: - return get_account_address_from_str(info, str, silent); + return get_account_address_from_str(info, str); case TESTNET: - return get_account_address_from_str(info, str, silent); + return get_account_address_from_str(info, str); case STAGENET: - return get_account_address_from_str(info, str, silent); + return get_account_address_from_str(info, str); default: return false; } diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 49d9da2f..6edf6abc 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 10995c74..9bae4873 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -19,8 +19,6 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "include_base_utils.h" -using namespace epee; - #include "crypto/pow_hash/cn_slow_hash.hpp" #include "crypto/crypto.h" #include "crypto/hash.h" @@ -33,13 +31,14 @@ using namespace epee; #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn" +#include "common/gulps.hpp" + #define ENCRYPTED_PAYMENT_ID_TAIL 0x8d // #define ENABLE_HASH_CASH_INTEGRITY_CHECK +using namespace epee; using namespace crypto; static const uint64_t valid_decomposed_outputs[] = { @@ -57,7 +56,7 @@ static const uint64_t valid_decomposed_outputs[] = { (uint64_t)100000000000, (uint64_t)200000000000, (uint64_t)300000000000, (uint64_t)400000000000, (uint64_t)500000000000, (uint64_t)600000000000, (uint64_t)700000000000, (uint64_t)800000000000, (uint64_t)900000000000, (uint64_t)1000000000000, (uint64_t)2000000000000, (uint64_t)3000000000000, (uint64_t)4000000000000, (uint64_t)5000000000000, (uint64_t)6000000000000, (uint64_t)7000000000000, (uint64_t)8000000000000, (uint64_t)9000000000000, // 1 kiloRyo (uint64_t)10000000000000, (uint64_t)20000000000000, (uint64_t)30000000000000, (uint64_t)40000000000000, (uint64_t)50000000000000, (uint64_t)60000000000000, (uint64_t)70000000000000, (uint64_t)80000000000000, (uint64_t)90000000000000, - (uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000, + (uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000, (uint64_t)1000000000000000, (uint64_t)2000000000000000, (uint64_t)3000000000000000, (uint64_t)4000000000000000, (uint64_t)5000000000000000, (uint64_t)6000000000000000, (uint64_t)7000000000000000, (uint64_t)8000000000000000, (uint64_t)9000000000000000, // 1 megaRyo (uint64_t)10000000000000000, (uint64_t)20000000000000000, (uint64_t)30000000000000000, (uint64_t)40000000000000000, (uint64_t)50000000000000000, (uint64_t)60000000000000000, (uint64_t)70000000000000000, (uint64_t)80000000000000000, (uint64_t)90000000000000000, (uint64_t)100000000000000000, (uint64_t)200000000000000000, (uint64_t)300000000000000000, (uint64_t)400000000000000000, (uint64_t)500000000000000000, (uint64_t)600000000000000000, (uint64_t)700000000000000000, (uint64_t)800000000000000000, (uint64_t)900000000000000000, @@ -71,17 +70,20 @@ static std::atomic tx_hashes_cached_count(0); static std::atomic block_hashes_calculated_count(0); static std::atomic block_hashes_cached_count(0); -#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) \ +#define CHECK_AND_ASSERT_THROW_MES_L1(expr, ...) \ { \ if(!(expr)) \ { \ - MWARNING(message); \ - throw std::runtime_error(message); \ + std::stringstream ss ; \ + ss << stream_writer::write(__VA_ARGS__); \ + GULPS_WARN(__VA_ARGS__); \ + throw std::runtime_error(ss.str()); \ } \ } namespace cryptonote { +GULPS_CAT_MAJOR("formt_utils"); static inline unsigned char *operator&(ec_point &point) { return &reinterpret_cast(point); @@ -136,7 +138,7 @@ bool expand_transaction_1(transaction &tx, bool base_only) rct::rctSig &rv = tx.rct_signatures; if(rv.outPk.size() != tx.vout.size()) { - LOG_PRINT_L1("Failed to parse transaction from blob, bad outPk size in tx " << get_transaction_hash(tx)); + GULPS_LOG_L1("Failed to parse transaction from blob, bad outPk size in tx ", get_transaction_hash(tx)); return false; } @@ -147,25 +149,25 @@ bool expand_transaction_1(transaction &tx, bool base_only) { if (rv.p.bulletproofs.size() != 1) { - LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx)); + GULPS_LOG_L1("Failed to parse transaction from blob, bad bulletproofs size in tx ", get_transaction_hash(tx)); return false; } if (rv.p.bulletproofs[0].L.size() < 6) { - LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs L size in tx " << get_transaction_hash(tx)); + GULPS_LOG_L1("Failed to parse transaction from blob, bad bulletproofs L size in tx ", get_transaction_hash(tx)); return false; } const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6); if (max_outputs < tx.vout.size()) { - LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx)); + GULPS_LOG_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx ", get_transaction_hash(tx)); return false; } const size_t n_amounts = tx.vout.size(); - CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V"); + GULPS_CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V"); rv.p.bulletproofs[0].V.resize(n_amounts); for (size_t i = 0; i < n_amounts; ++i) @@ -180,8 +182,8 @@ bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx) ss << tx_blob; binary_archive ba(ss); bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + GULPS_CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); tx.invalidate_hashes(); return true; } @@ -192,8 +194,8 @@ bool parse_and_validate_tx_base_from_blob(const blobdata &tx_blob, transaction & ss << tx_blob; binary_archive ba(ss); bool r = tx.serialize_base(ba); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + GULPS_CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data"); return true; } //--------------------------------------------------------------- @@ -203,8 +205,8 @@ bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx, c ss << tx_blob; binary_archive ba(ss); bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + GULPS_CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data"); tx.invalidate_hashes(); //TODO: validate tx @@ -217,19 +219,19 @@ bool generate_key_image_helper(const account_keys &ack, const std::unordered_map { crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" , tx_public_key , ", " , ack.m_view_secret_key , ")"); std::vector additional_recv_derivations; for(size_t i = 0; i < additional_tx_public_keys.size(); ++i) { crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation); r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" , additional_tx_public_keys[i] , ", " , ack.m_view_secret_key , ")"); additional_recv_derivations.push_back(additional_recv_derivation); } boost::optional subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index, hwdev); - CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address"); + GULPS_CHECK_AND_ASSERT_MES(subaddr_recv_info, false, "key image helper: given output pubkey doesn't seem to belong to this address"); return generate_key_image_helper_precomp(ack, out_key, subaddr_recv_info->derivation, real_output_index, subaddr_recv_info->index, in_ephemeral, ki, hwdev); } @@ -266,22 +268,22 @@ bool generate_key_image_helper_precomp(const account_keys &ack, const crypto::pu if(ack.m_multisig_keys.empty()) { // when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); + GULPS_CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key"); } else { // when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation - CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); + GULPS_CHECK_AND_ASSERT_MES(hwdev.derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key"); // and don't forget to add the contribution from the subaddress part if(!received_index.is_zero()) { crypto::public_key subaddr_pk; - CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); + GULPS_CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key"); add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk); } } - CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, + GULPS_CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, false, "key image helper precomp: given output pubkey doesn't match the derived one"); } @@ -365,7 +367,7 @@ bool parse_tx_extra(const std::vector &tx_extra, std::vector &tx_extra, const s //--------------------------------------------------------------- bool add_extra_nonce_to_tx_extra(std::vector &tx_extra, const blobdata &extra_nonce) { - CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max"); + GULPS_CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max"); size_t start_pos = tx_extra.size(); tx_extra.resize(tx_extra.size() + 2 + extra_nonce.size()); //write tag @@ -484,7 +486,7 @@ bool remove_field_from_tx_extra(std::vector &tx_extra, const std::type_ { tx_extra_field field; bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); + GULPS_CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " , string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); if(field.type() != type) ::do_serialize(newar, field); @@ -492,7 +494,7 @@ bool remove_field_from_tx_extra(std::vector &tx_extra, const std::type_ eof = (EOF == iss.peek()); iss.clear(state); } - CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); + GULPS_CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " , string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast(tx_extra.data()), tx_extra.size()))); tx_extra.clear(); std::string s = oss.str(); tx_extra.reserve(s.size()); @@ -500,22 +502,15 @@ bool remove_field_from_tx_extra(std::vector &tx_extra, const std::type_ return true; } //--------------------------------------------------------------- -bool add_payment_id_to_tx_extra(std::vector &tx_extra, const tx_extra_uniform_payment_id* pid) +bool add_payment_id_to_tx_extra(std::vector &tx_extra, const tx_extra_uniform_payment_id &pid) { size_t pos = tx_extra.size(); tx_extra.resize(pos + 1 + sizeof(crypto::uniform_payment_id)); tx_extra[pos] = TX_EXTRA_UNIFORM_PAYMENT_ID; - if(pid != nullptr) - { - if(pid->pid.zero == 0) //failsafe, don't add unencrypted data - return false; - memcpy(&tx_extra[pos+1], &pid->pid, sizeof(crypto::uniform_payment_id)); - } - else - { - rand(sizeof(crypto::uniform_payment_id), &tx_extra[pos+1]); - } + if(pid.pid.zero == 0) //failsafe, don't add unencrypted data + return false; + memcpy(&tx_extra[pos+1], &pid.pid, sizeof(crypto::uniform_payment_id)); return true; } @@ -581,7 +576,7 @@ bool get_inputs_money_amount(const transaction &tx, uint64_t &money) //--------------------------------------------------------------- uint64_t get_block_height(const block &b) { - CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1"); + GULPS_CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " , get_block_hash(b) , ", b.miner_tx.vin.size() != 1"); CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], const txin_gen, coinbase_in, 0); return coinbase_in.height; } @@ -590,9 +585,9 @@ bool check_inputs_types_supported(const transaction &tx) { for(const auto &in : tx.vin) { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), false, "wrong variant type: " - << in.type().name() << ", expected " << typeid(txin_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); + GULPS_CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), false, "wrong variant type: " + , in.type().name() , ", expected " , typeid(txin_to_key).name() + , ", in transaction id=" , get_transaction_hash(tx)); } return true; } @@ -601,9 +596,9 @@ bool check_outs_valid(const transaction &tx) { for(const tx_out &out : tx.vout) { - CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: " - << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); + GULPS_CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: " + , out.target.type().name() , ", expected " , typeid(txout_to_key).name() + , ", in transaction id=" , get_transaction_hash(tx)); if(!check_key(boost::get(out.target).key)) return false; @@ -652,7 +647,7 @@ uint64_t get_outs_money_amount(const transaction &tx) std::string short_hash_str(const crypto::hash &h) { std::string res = string_tools::pod_to_hex(h); - CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion"); + GULPS_CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion"); auto erased_pos = res.erase(8, 48); res.insert(8, "...."); return res; @@ -662,24 +657,25 @@ bool is_out_to_acc(const account_keys &acc, const txout_to_key &out_key, const c { crypto::key_derivation derivation; bool r = acc.get_device().generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); crypto::public_key pk; r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); if(pk == out_key.key) return true; // try additional tx pubkeys if available if(!additional_tx_pub_keys.empty()) { - CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys"); + GULPS_CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys"); r = acc.get_device().generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation"); r = acc.get_device().derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); - CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key"); return pk == out_key.key; } return false; } + //--------------------------------------------------------------- boost::optional is_out_to_acc_precomp(const std::unordered_map &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector &additional_derivations, size_t output_index, hw::device &hwdev) { @@ -692,7 +688,7 @@ boost::optional is_out_to_acc_precomp(const std::unorde // try additional tx pubkeys if available if(!additional_derivations.empty()) { - CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); + GULPS_CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); found = subaddresses.find(subaddress_spendkey); if(found != subaddresses.end()) @@ -700,6 +696,29 @@ boost::optional is_out_to_acc_precomp(const std::unorde } return boost::none; } + +#ifdef HAVE_EC_64 +boost::optional is_out_to_acc_precomp_64(const std::unordered_map &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector &additional_derivations, size_t output_index, hw::device &hwdev) +{ + // try the shared tx pubkey + crypto::public_key subaddress_spendkey; + hwdev.derive_subaddress_public_key_64(out_key, derivation, output_index, subaddress_spendkey); + auto found = subaddresses.find(subaddress_spendkey); + if(found != subaddresses.end()) + return subaddress_receive_info{found->second, derivation}; + // try additional tx pubkeys if available + if(!additional_derivations.empty()) + { + GULPS_CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); + hwdev.derive_subaddress_public_key_64(out_key, additional_derivations[output_index], output_index, subaddress_spendkey); + found = subaddresses.find(subaddress_spendkey); + if(found != subaddresses.end()) + return subaddress_receive_info{found->second, additional_derivations[output_index]}; + } + return boost::none; +} +#endif + //--------------------------------------------------------------- bool lookup_acc_outs(const account_keys &acc, const transaction &tx, std::vector &outs, uint64_t &money_transfered) { @@ -712,12 +731,12 @@ bool lookup_acc_outs(const account_keys &acc, const transaction &tx, std::vector //--------------------------------------------------------------- bool lookup_acc_outs(const account_keys &acc, const transaction &tx, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, std::vector &outs, uint64_t &money_transfered) { - CHECK_AND_ASSERT_MES(additional_tx_pub_keys.empty() || additional_tx_pub_keys.size() == tx.vout.size(), false, "wrong number of additional pubkeys"); + GULPS_CHECK_AND_ASSERT_MES(additional_tx_pub_keys.empty() || additional_tx_pub_keys.size() == tx.vout.size(), false, "wrong number of additional pubkeys"); money_transfered = 0; size_t i = 0; for(const tx_out &o : tx.vout) { - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong type id in transaction out"); + GULPS_CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong type id in transaction out"); if(is_out_to_acc(acc, boost::get(o.target), tx_pub_key, additional_tx_pub_keys, i)) { outs.push_back(i); @@ -744,7 +763,7 @@ void set_default_decimal_point(unsigned int decimal_point) default_decimal_point = decimal_point; break; default: - ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point); + GULPS_ASSERT_MES_AND_THROW("Invalid decimal point specification: ", decimal_point); } } //--------------------------------------------------------------- @@ -768,7 +787,7 @@ std::string get_unit(unsigned int decimal_point) case 0: return "nanoryo"; default: - ASSERT_MES_AND_THROW("Invalid decimal point specification: " << default_decimal_point); + GULPS_ASSERT_MES_AND_THROW("Invalid decimal point specification: ", std::to_string(default_decimal_point)); } } //--------------------------------------------------------------- @@ -829,7 +848,7 @@ bool calculate_transaction_hash(const transaction &t, crypto::hash &res, size_t const size_t inputs = t.vin.size(); const size_t outputs = t.vout.size(); bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base"); cryptonote::get_blob_hash(ss.str(), hashes[1]); } @@ -846,7 +865,7 @@ bool calculate_transaction_hash(const transaction &t, crypto::hash &res, size_t const size_t outputs = t.vout.size(); const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get(t.vin[0]).key_offsets.size() - 1 : 0; bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable"); cryptonote::get_blob_hash(ss.str(), hashes[2]); } @@ -865,7 +884,7 @@ bool get_transaction_hash(const transaction &t, crypto::hash &res, size_t *blob_ if(t.is_hash_valid()) { #ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK - CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure"); #endif res = t.hash; if(blob_size) @@ -920,7 +939,7 @@ bool get_block_hash(const block &b, crypto::hash &res) if(b.is_hash_valid()) { #ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK - CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure"); #endif res = b.hash; ++block_hashes_cached_count; @@ -946,7 +965,7 @@ bool get_block_longhash(network_type nettype, const block &b, cn_pow_hash_v2 &ct { block b_local = b; //workaround to avoid const errors with do_serialize blobdata bd = get_block_hashing_blob(b); - + uint8_t cn_heavy_v = get_fork_v(nettype, FORK_POW_CN_HEAVY); uint8_t cn_gpu_v = get_fork_v(nettype, FORK_POW_CN_GPU); @@ -993,7 +1012,7 @@ bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b) ss << b_blob; binary_archive ba(ss); bool r = ::serialization::serialize(ba, b); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); b.invalidate_hashes(); b.miner_tx.invalidate_hashes(); return true; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 3199b74d..60406b52 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -64,7 +64,7 @@ bool add_tx_pub_key_to_extra(std::vector &tx_extra, const crypto::publi std::vector get_additional_tx_pub_keys_from_extra(const std::vector &tx_extra); std::vector get_additional_tx_pub_keys_from_extra(const transaction_prefix &tx); bool add_additional_tx_pub_keys_to_extra(std::vector &tx_extra, const std::vector &additional_pub_keys); -bool add_payment_id_to_tx_extra(std::vector &tx_extra, const tx_extra_uniform_payment_id* pid = nullptr); +bool add_payment_id_to_tx_extra(std::vector &tx_extra, const tx_extra_uniform_payment_id &pid); bool get_payment_id_from_tx_extra(const std::vector &tx_extra, tx_extra_uniform_payment_id& pid); bool get_payment_id_from_tx_extra(const std::vector &tx_extra_fields, tx_extra_uniform_payment_id& pid); bool add_extra_nonce_to_tx_extra(std::vector &tx_extra, const blobdata &extra_nonce); @@ -80,6 +80,9 @@ struct subaddress_receive_info crypto::key_derivation derivation; }; boost::optional is_out_to_acc_precomp(const std::unordered_map &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector &additional_derivations, size_t output_index, hw::device &hwdev); +#ifdef HAVE_EC_64 +boost::optional is_out_to_acc_precomp_64(const std::unordered_map &subaddresses, const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::vector &additional_derivations, size_t output_index, hw::device &hwdev); +#endif bool lookup_acc_outs(const account_keys &acc, const transaction &tx, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_public_keys, std::vector &outs, uint64_t &money_transfered); bool lookup_acc_outs(const account_keys &acc, const transaction &tx, std::vector &outs, uint64_t &money_transfered); bool get_tx_fee(const transaction &tx, uint64_t &fee); @@ -165,7 +168,8 @@ std::string obj_to_json_str(T &obj) std::stringstream ss; json_archive ar(ss, true); bool r = ::serialization::serialize(ar, obj); - CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); + GULPS_CAT_MAJOR("formt_utils"); + GULPS_CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); return ss.str(); } //--------------------------------------------------------------- @@ -179,7 +183,31 @@ crypto::hash get_tx_tree_hash(const block &b); bool is_valid_decomposed_amount(uint64_t amount); void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t &block_hashes_cached); +//------------------------------------------------------------------------------------------------------------------------------ +inline blobdata get_pruned_tx_blob(transaction &tx) +{ + GULPS_CAT_MAJOR("formt_utils"); + std::stringstream ss; + binary_archive ba(ss); + bool r = tx.serialize_base(ba); + GULPS_CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); + return ss.str(); +} +//------------------------------------------------------------------------------------------------------------------------------ +inline blobdata get_pruned_tx_blob(const blobdata &blobdata) +{ + GULPS_CAT_MAJOR("formt_utils"); + cryptonote::transaction tx; + + if(!cryptonote::parse_and_validate_tx_base_from_blob(blobdata, tx)) + { + GULPS_ERROR("Failed to parse and validate tx from blob"); + return cryptonote::blobdata(); + } + return get_pruned_tx_blob(tx); +} + #define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ - CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ + GULPS_CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " , variant_var.type().name() , ", expected " , typeid(specific_type).name()); \ specific_type &variable_name = boost::get(variant_var); } diff --git a/src/cryptonote_basic/cryptonote_stat_info.h b/src/cryptonote_basic/cryptonote_stat_info.h index f610d210..0469ad28 100644 --- a/src/cryptonote_basic/cryptonote_stat_info.h +++ b/src/cryptonote_basic/cryptonote_stat_info.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -31,7 +31,7 @@ struct core_stat_info uint64_t alternative_blocks; std::string top_block_id_str; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(core_stat_info) KV_SERIALIZE(tx_pool_size) KV_SERIALIZE(blockchain_height) KV_SERIALIZE(mining_speed) diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index 1f8f05c9..01106965 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -18,6 +18,8 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#include "common/gulps.hpp" + #include #include #include @@ -31,6 +33,8 @@ #include "include_base_utils.h" #include "misc_language.h" +GULPS_CAT_MAJOR("crybas_diff"); + namespace cryptonote { @@ -214,13 +218,14 @@ difficulty_type next_difficulty_v2(std::vector timestamps, std::v } time_spans.push_back(time_span); - LOG_PRINT_L3("Timespan " << i << ": " << (time_span / 60) / 60 << ":" << (time_span > 3600 ? (time_span % 3600) / 60 : time_span / 60) << ":" << time_span % 60 << " (" << time_span << ")"); + GULPSF_LOG_L3("Timespan {}: {}:{}:{} ({})", i, (time_span / 60) / 60, (time_span > 3600 ? (time_span % 3600) / 60 : time_span / 60), time_span % 60, time_span ); + } timespan_median = epee::misc_utils::median(time_spans); } uint64_t timespan_length = length - cut_begin * 2 - 1; - LOG_PRINT_L2("Timespan Median: " << timespan_median << ", Timespan Average: " << total_timespan / timespan_length); + GULPSF_LOG_L2("Timespan Median: {}, Timespan Average: {}", timespan_median, total_timespan / timespan_length); uint64_t total_timespan_median = timespan_median > 0 ? timespan_median * timespan_length : total_timespan * 7 / 10; uint64_t adjusted_total_timespan = (total_timespan * 8 + total_timespan_median * 3) / 10; // 0.8A + 0.3M (the median of a poisson distribution is 70% of the mean, so 0.25A = 0.25/0.7 = 0.285M) @@ -246,8 +251,7 @@ difficulty_type next_difficulty_v2(std::vector timestamps, std::v uint64_t next_diff = (low + adjusted_total_timespan - 1) / adjusted_total_timespan; if(next_diff < 1) next_diff = 1; - LOG_PRINT_L2("Total timespan: " << total_timespan << ", Adjusted total timespan: " << adjusted_total_timespan << ", Total work: " << total_work << ", Next diff: " << next_diff << ", Hashrate (H/s): " << next_diff / target_seconds); - + GULPSF_LOG_L2("Total timespan: {}, Adjusted total timespan: {}, Total work: {}, Next diff: {}, Hashrate (H/s): {}", total_timespan, adjusted_total_timespan, total_work, next_diff, next_diff / target_seconds); return next_diff; } @@ -290,8 +294,7 @@ difficulty_type next_difficulty_v3(const std::vector ×tamps, // 99/100 adds a small bias towards decreasing diff, unlike zawy we do it in a separate step to avoid an overflow at 6GH/s next_D = (next_D * 99ull) / 100ull; - LOG_PRINT_L2("diff sum: " << (cumulative_difficulties[N] - cumulative_difficulties[0]) << " L " << L << " sizes " << timestamps.size() << " " << cumulative_difficulties.size() << " next_D " << next_D); - + GULPSF_LOG_L2("diff sum: {} L {} sizes {} {} next_D {}",(cumulative_difficulties[N] - cumulative_difficulties[0]), L, timestamps.size(), cumulative_difficulties.size(), next_D); return next_D; } @@ -313,7 +316,7 @@ void interpolate_timestamps(std::vector& timestamps) uint64_t maxValid = timestamps[N]; for(size_t i = 1; i < N; i++) { - /* + /* * Mask timestamp if it is smaller or equal to last valid timestamp * or if it is larger or equal to largest timestamp */ @@ -341,7 +344,7 @@ void interpolate_timestamps(std::vector& timestamps) if(timestamps[i] <= N) { // denominator -- NOT THE SAME AS [i+1] - uint64_t den = timestamps[i] + 1; + uint64_t den = timestamps[i] + 1; // numerator uint64_t num = timestamps[i]; uint64_t delta = timestamps[i+1] - timestamps[i-num]; diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index bf481f71..880d0a00 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_basic/hardfork.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 #include @@ -23,8 +24,10 @@ #include "cryptonote_basic/cryptonote_basic.h" #include "hardfork.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "hardfork" + +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("crybas_hfork"); using namespace cryptonote; @@ -186,10 +189,10 @@ void HardFork::init() } if(populate) { - MINFO("The DB has no hard fork info, reparsing from start"); + GULPS_INFO("The DB has no hard fork info, reparsing from start"); height = 1; } - MDEBUG("reorganizing from " << height); + GULPSF_LOG_L1("reorganizing from {}", height); if(populate) { reorganize_from_chain_height(height); @@ -200,7 +203,7 @@ void HardFork::init() { rescan_from_chain_height(height); } - MDEBUG("reorganization done"); + GULPS_LOG_L1("reorganization done"); } uint8_t HardFork::get_block_version(uint64_t height) const diff --git a/src/cryptonote_basic/hardfork.h b/src/cryptonote_basic/hardfork.h index 3a19962d..df39c818 100644 --- a/src/cryptonote_basic/hardfork.h +++ b/src/cryptonote_basic/hardfork.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index 01529cac..cfbf2d70 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,6 +18,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + #include "boost/logic/tribool.hpp" #include "common/command_line.h" #include "cryptonote_basic_impl.h" @@ -60,9 +61,6 @@ #include #endif -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "miner" - using namespace epee; #include "miner.h" @@ -144,7 +142,7 @@ bool miner::request_block_template() if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce)) { - LOG_ERROR("Failed to get_block_template(), stopping mining"); + GULPS_ERROR("Failed to get_block_template(), stopping mining"); return false; } set_block_template(bl, di, height); @@ -186,7 +184,7 @@ void miner::merge_hr() uint64_t total_hr = std::accumulate(m_last_hash_rates.begin(), m_last_hash_rates.end(), 0); float hr = static_cast(total_hr) / static_cast(m_last_hash_rates.size()); const auto precision = std::cout.precision(); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << precision << ENDL; + GULPSF_PRINT("hashrate: {:.{}f}", hr, precision); } } m_last_hr_merge_time = misc_utils::get_tick_count(); @@ -212,7 +210,7 @@ bool miner::init(const boost::program_options::variables_map &vm, network_type n { std::string buff; bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages)); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " , command_line::get_arg(vm, arg_extra_messages)); std::vector extra_vec; boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on); m_extra_messages.resize(extra_vec.size()); @@ -228,7 +226,7 @@ bool miner::init(const boost::program_options::variables_map &vm, network_type n m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string(); m_config = AUTO_VAL_INIT(m_config); epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); - MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index); + GULPSF_INFO("Loaded {} extra messages, current index {}", m_extra_messages.size(), m_config.current_extra_message_index); } if(command_line::has_arg(vm, arg_start_mining)) @@ -236,14 +234,14 @@ bool miner::init(const boost::program_options::variables_map &vm, network_type n address_parse_info info; if(!cryptonote::get_account_address_from_str(nettype, info, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress) { - LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled"); + GULPSF_LOG_ERROR("Target account address {} has wrong format, starting daemon canceled", command_line::get_arg(vm, arg_start_mining) ); return false; } - if(command_line::get_arg(vm, arg_start_mining) == common_config::DEV_FUND_ADDRESS) - { - LOG_ERROR("Dev fund address is not mineable. If you would like to support the dev team please mine to " << common_config::RYO_DONATION_ADDR); - return false; + if(command_line::get_arg(vm, arg_start_mining) == common_config::DEV_FUND_ADDRESS) + { + GULPSF_LOG_ERROR("Dev fund address is not mineable. If you would like to support the dev team please mine to {}", common_config::RYO_DONATION_ADDR); + return false; } m_mine_address = info.address; @@ -294,13 +292,13 @@ bool miner::start(const account_public_address &adr, size_t threads_count, const CRITICAL_REGION_LOCAL(m_threads_lock); if(is_mining()) { - LOG_ERROR("Starting miner but it's already started"); + GULPS_LOG_ERROR("Starting miner but it's already started"); return false; } if(!m_threads.empty()) { - LOG_ERROR("Unable to start miner because there are active mining threads"); + GULPS_LOG_ERROR("Unable to start miner because there are active mining threads"); return false; } @@ -316,12 +314,12 @@ bool miner::start(const account_public_address &adr, size_t threads_count, const m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this))); } - LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!"); + GULPSF_PRINT("Mining has started with {} threads, good luck!", threads_count ); if(get_is_background_mining_enabled()) { m_background_mining_thread = boost::thread(attrs, boost::bind(&miner::background_worker_thread, this)); - LOG_PRINT_L0("Background mining controller thread started"); + GULPS_LOG_L0("Background mining controller thread started"); } return true; @@ -346,11 +344,11 @@ void miner::send_stop_signal() //----------------------------------------------------------------------------------------------------- bool miner::stop() { - MTRACE("Miner has received stop signal"); + GULPS_LOG_L2("Miner has received stop signal"); if(!is_mining()) { - MDEBUG("Not mining - nothing to stop"); + GULPS_LOG_L1("Not mining - nothing to stop"); return true; } @@ -369,7 +367,7 @@ bool miner::stop() m_background_mining_thread.interrupt(); m_background_mining_thread.join(); - MINFO("Mining has been stopped, " << m_threads.size() << " finished"); + GULPSF_INFO("Mining has been stopped, {} finished", m_threads.size()); m_threads.clear(); return true; } @@ -406,31 +404,31 @@ void miner::on_synchronized() void miner::pause() { CRITICAL_REGION_LOCAL(m_miners_count_lock); - MDEBUG("miner::pause: " << m_pausers_count << " -> " << (m_pausers_count + 1)); + GULPSF_LOG_L1("miner::pause: {} -> {}", m_pausers_count , (m_pausers_count + 1)); ++m_pausers_count; if(m_pausers_count == 1 && is_mining()) - MDEBUG("MINING PAUSED"); + GULPS_LOG_L1("MINING PAUSED"); } //----------------------------------------------------------------------------------------------------- void miner::resume() { CRITICAL_REGION_LOCAL(m_miners_count_lock); - MDEBUG("miner::resume: " << m_pausers_count << " -> " << (m_pausers_count - 1)); + GULPSF_LOG_L1("miner::resume: {} -> {}", m_pausers_count , (m_pausers_count - 1)); --m_pausers_count; if(m_pausers_count < 0) { m_pausers_count = 0; - MERROR("Unexpected miner::resume() called"); + GULPS_ERROR("Unexpected miner::resume() called"); } if(!m_pausers_count && is_mining()) - MDEBUG("MINING RESUMED"); + GULPS_LOG_L1("MINING RESUMED"); } //----------------------------------------------------------------------------------------------------- bool miner::worker_thread() { uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); - MGINFO("Miner thread was started [" << th_local_index << "]"); + GULPS_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); + GULPSF_PRINT("Miner thread was started [{}]", th_local_index); uint32_t nonce = m_starter_nonce + th_local_index; difficulty_type local_diff = 0; uint32_t local_template_ver = 0; @@ -449,7 +447,7 @@ bool miner::worker_thread() misc_utils::sleep_no_w(m_miner_extra_sleep); while(!m_is_background_mining_started) { - MGINFO("background mining is enabled, but not started, waiting until start triggers"); + GULPS_PRINT("background mining is enabled, but not started, waiting until start triggers"); boost::unique_lock started_lock(m_is_background_mining_started_mutex); m_is_background_mining_started_cond.wait(started_lock); if(m_stop) @@ -472,7 +470,7 @@ bool miner::worker_thread() if(!local_template_ver) //no any set_block_template call { - LOG_PRINT_L2("Block template not set yet"); + GULPS_LOG_L2("Block template not set yet"); epee::misc_utils::sleep_no_w(1000); continue; } @@ -485,7 +483,7 @@ bool miner::worker_thread() { //we lucky! ++m_config.current_extra_message_index; - MGINFO_GREEN("Found block for difficulty: " << local_diff); + GULPSF_PRINT_CLR(gulps::COLOR_GREEN, "Found block for difficulty: {}", local_diff); if(!m_phandler->handle_block_found(b)) { --m_config.current_extra_message_index; @@ -500,7 +498,7 @@ bool miner::worker_thread() nonce += m_threads_total; ++m_hashes; } - MGINFO("Miner thread stopped [" << th_local_index << "]"); + GULPSF_PRINT("Miner thread stopped [{}]", th_local_index); return true; } //----------------------------------------------------------------------------------------------------- @@ -586,7 +584,7 @@ bool miner::background_worker_thread() if(!get_system_times(prev_total_time, prev_idle_time)) { - LOG_ERROR("get_system_times call failed, background mining will NOT work!"); + GULPS_LOG_ERROR("get_system_times call failed, background mining will NOT work!"); return false; } @@ -612,7 +610,7 @@ bool miner::background_worker_thread() /* while( !m_is_background_mining_enabled ) { - MGINFO("background mining is disabled, waiting until enabled!"); + GULPS_PRINT("background mining is disabled, waiting until enabled!"); boost::unique_lock enabled_lock( m_is_background_mining_enabled_mutex ); m_is_background_mining_enabled_cond.wait( enabled_lock ); } @@ -627,7 +625,7 @@ bool miner::background_worker_thread() } catch(const boost::thread_interrupted &) { - MDEBUG("background miner thread interrupted "); + GULPS_LOG_L1("background miner thread interrupted "); continue; // if interrupted because stop called, loop should end .. } @@ -650,13 +648,13 @@ bool miner::background_worker_thread() if(!get_system_times(current_total_time, current_idle_time)) { - MERROR("get_system_times call failed"); + GULPS_ERROR("get_system_times call failed"); continue; } if(!get_process_time(current_process_time)) { - MERROR("get_process_time call failed!"); + GULPS_ERROR("get_process_time call failed!"); continue; } @@ -666,10 +664,10 @@ bool miner::background_worker_thread() uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff); uint8_t process_percentage = get_percent_of_total(process_diff, total_diff); - MGINFO("idle percentage is " << unsigned(idle_percentage) << "\%, miner percentage is " << unsigned(process_percentage) << "\%, ac power : " << on_ac_power); + GULPSF_PRINT("idle percentage is {}%, miner percentage is {}%, ac power : {}", unsigned(idle_percentage), unsigned(process_percentage), on_ac_power); if(idle_percentage + process_percentage < get_idle_threshold() || !on_ac_power) { - MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining stopping, thanks for your contribution!"); + GULPSF_PRINT("cpu is {}% idle, idle threshold is {}%, ac power : {}, background mining stopping, thanks for your contribution!", unsigned(idle_percentage), unsigned(get_idle_threshold()), on_ac_power); m_is_background_mining_started = false; // reset process times @@ -687,7 +685,7 @@ bool miner::background_worker_thread() // fall below zero because all the time functions aggregate across all processors. // I'm just hard limiting to 5 millis min sleep here, other options? m_miner_extra_sleep = std::max(new_miner_extra_sleep, (int64_t)5); - MDEBUG("m_miner_extra_sleep " << m_miner_extra_sleep); + GULPSF_LOG_L1("m_miner_extra_sleep {}", m_miner_extra_sleep); } prev_total_time = current_total_time; @@ -699,7 +697,7 @@ bool miner::background_worker_thread() if(!get_system_times(current_total_time, current_idle_time)) { - MERROR("get_system_times call failed"); + GULPS_ERROR("get_system_times call failed"); continue; } @@ -707,10 +705,10 @@ bool miner::background_worker_thread() uint64_t idle_diff = (current_idle_time - prev_idle_time); uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff); - MGINFO("idle percentage is " << unsigned(idle_percentage)); + GULPSF_PRINT("idle percentage is {}", unsigned(idle_percentage)); if(idle_percentage >= get_idle_threshold() && on_ac_power) { - MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining started, good luck!"); + GULPSF_PRINT("cpu is {}% idle, idle threshold is {}\%, ac power : {}, background mining started, good luck!", unsigned(idle_percentage), unsigned(get_idle_threshold()), on_ac_power); m_is_background_mining_started = true; m_is_background_mining_started_cond.notify_all(); @@ -721,7 +719,7 @@ bool miner::background_worker_thread() if(!get_process_time(previous_process_time)) { m_is_background_mining_started = false; - MERROR("get_process_time call failed!"); + GULPS_ERROR("get_process_time call failed!"); } } @@ -756,14 +754,14 @@ bool miner::get_system_times(uint64_t &total_time, uint64_t &idle_time) if(!epee::file_io_utils::is_file_exist(STAT_FILE_PATH)) { - LOG_ERROR("'" << STAT_FILE_PATH << "' file does not exist"); + GULPSF_LOG_ERROR("'{}' file does not exist", STAT_FILE_PATH ); return false; } std::ifstream stat_file_stream(STAT_FILE_PATH); if(stat_file_stream.fail()) { - LOG_ERROR("failed to open '" << STAT_FILE_PATH << "'"); + GULPSF_ERROR("failed to open '{}'", STAT_FILE_PATH ); return false; } @@ -774,7 +772,7 @@ bool miner::get_system_times(uint64_t &total_time, uint64_t &idle_time) uint64_t utime, ntime, stime, itime; if(!(stat_file_iss >> utime && stat_file_iss >> ntime && stat_file_iss >> stime && stat_file_iss >> itime)) { - LOG_ERROR("failed to read '" << STAT_FILE_PATH << "'"); + GULPSF_LOG_ERROR("failed to read '{}'", STAT_FILE_PATH ); return false; } @@ -806,14 +804,12 @@ bool miner::get_system_times(uint64_t &total_time, uint64_t &idle_time) size_t n = sizeof(s.cp_time); if(sysctlbyname("kern.cp_time", s.cp_time, &n, NULL, 0) == -1) { - LOG_ERROR("sysctlbyname(\"kern.cp_time\"): " << strerror(errno)); + GULPSF_LOG_ERROR("sysctlbyname(\"kern.cp_time\"): {}", strerror(errno)); return false; } if(n != sizeof(s.cp_time)) { - LOG_ERROR("sysctlbyname(\"kern.cp_time\") output is unexpectedly " - << n << " bytes instead of the expected " << sizeof(s.cp_time) - << " bytes."); + GULPSF_LOG_ERROR("sysctlbyname(\"kern.cp_time\") output is unexpectedly {} bytes instead of the expected {} bytes.", n, sizeof(s.cp_time)); return false; } @@ -906,7 +902,7 @@ boost::logic::tribool miner::on_battery_power() std::ifstream power_supply_type_stream(power_supply_type_path.string()); if(power_supply_type_stream.fail()) { - LOG_PRINT_L0("Unable to read from " << power_supply_type_path << " to check power supply type"); + GULPS_PRINT("Unable to read from ", power_supply_type_path, " to check power supply type" ); continue; } @@ -922,7 +918,7 @@ boost::logic::tribool miner::on_battery_power() std::ifstream power_supply_online_stream(power_supply_online_path.string()); if(power_supply_online_stream.fail()) { - LOG_PRINT_L0("Unable to read from " << power_supply_online_path << " to check ac power supply status"); + GULPS_PRINT("Unable to read from ", power_supply_online_path, " to check ac power supply status"); continue; } @@ -940,7 +936,7 @@ boost::logic::tribool miner::on_battery_power() std::ifstream power_supply_status_stream(power_supply_status_path.string()); if(power_supply_status_stream.fail()) { - LOG_PRINT_L0("Unable to read from " << power_supply_status_path << " to check battery power supply status"); + GULPS_PRINT("Unable to read from ", power_supply_status_path, " to check battery power supply status"); continue; } @@ -966,7 +962,7 @@ boost::logic::tribool miner::on_battery_power() if(boost::logic::indeterminate(on_battery)) { - LOG_ERROR("couldn't query power status from " << power_supply_class_path); + GULPSF_LOG_ERROR("couldn't query power status from {}", power_supply_class_path); } return on_battery; @@ -977,8 +973,7 @@ boost::logic::tribool miner::on_battery_power() { if(errno != ENOENT) { - LOG_ERROR("Cannot query battery status: " - << "sysctlbyname(\"hw.acpi.acline\"): " << strerror(errno)); + GULPS_LGOG_ERROR("Cannot query battery status: ", "sysctlbyname(\"hw.acpi.acline\"): ", strerror(errno)); return boost::logic::tribool(boost::logic::indeterminate); } @@ -988,8 +983,7 @@ boost::logic::tribool miner::on_battery_power() const int fd = open(dev_apm, O_RDONLY); if(fd == -1) { - LOG_ERROR("Cannot query battery status: " - << "open(): " << dev_apm << ": " << strerror(errno)); + GULPSF_LOG_ERROR("Cannot query battery status: open(): {}: {}", dev_apm, strerror(errno)); return boost::logic::tribool(boost::logic::indeterminate); } @@ -997,8 +991,7 @@ boost::logic::tribool miner::on_battery_power() if(ioctl(fd, APMIO_GETINFO, &info) == -1) { close(fd); - LOG_ERROR("Cannot query battery status: " - << "ioctl(" << dev_apm << ", APMIO_GETINFO): " << strerror(errno)); + GULPSF_LOG_FERROR("Cannot query battery status: ioctl({}, APMIO_GETINFO): {}", dev_apm, strerror(errno)); return boost::logic::tribool(boost::logic::indeterminate); } @@ -1023,22 +1016,19 @@ boost::logic::tribool miner::on_battery_power() return boost::logic::tribool(false); } - LOG_ERROR("Cannot query battery status: " - << "sysctl hw.acpi.acline is not available and /dev/apm returns " - << "unexpected ac-line status (" << info.ai_acline << ") and " - << "battery status (" << info.ai_batt_stat << ")."); + GULPSF_LOG_ERROR("Cannot query battery status: sysctl hw.acpi.acline is not available and /dev/apm returns unexpected ac-line status ({}) and battery status ({}).", + info.ai_acline, info.ai_batt_stat); return boost::logic::tribool(boost::logic::indeterminate); } if(n != sizeof(ac)) { - LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly " - << n << " bytes instead of the expected " << sizeof(ac) << " bytes."); + GULPSF_LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly {} bytes instead of the expected {} bytes.", n, sizeof(ac)); return boost::logic::tribool(boost::logic::indeterminate); } return boost::logic::tribool(ac == 0); #endif - LOG_ERROR("couldn't query power status"); + GULPS_LOG_ERROR("couldn't query power status"); return boost::logic::tribool(boost::logic::indeterminate); } } diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index 7215d222..cdb87141 100644 --- a/src/cryptonote_basic/miner.h +++ b/src/cryptonote_basic/miner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -23,7 +23,7 @@ #include "cryptonote_basic.h" #include "difficulty.h" #include "math_helper.h" -#include "cryptonote_basic/blobdatatype.h" +#include "cryptonote_basic/blobdatatype.h" #include #include #include @@ -36,6 +36,8 @@ #include #endif +#include "common/gulps.hpp" + namespace cryptonote { @@ -53,6 +55,7 @@ struct i_miner_handler /************************************************************************/ class miner { + GULPS_CAT_MAJOR("crybas_miner"); public: miner(i_miner_handler *phandler); ~miner(); @@ -105,7 +108,7 @@ class miner { uint64_t current_extra_message_index; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(miner_config) KV_SERIALIZE(current_extra_message_index) END_KV_SERIALIZE_MAP() }; diff --git a/src/cryptonote_basic/subaddress_index.h b/src/cryptonote_basic/subaddress_index.h index 4e7de4d8..864635e8 100644 --- a/src/cryptonote_basic/subaddress_index.h +++ b/src/cryptonote_basic/subaddress_index.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -27,6 +27,8 @@ namespace cryptonote { struct subaddress_index { + subaddress_index(uint32_t maj, uint32_t min) { major = maj; minor = min; } + uint32_t major; uint32_t minor; bool operator==(const subaddress_index &rhs) const { return !memcmp(this, &rhs, sizeof(subaddress_index)); } @@ -38,7 +40,7 @@ struct subaddress_index FIELD(minor) END_SERIALIZE() - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(subaddress_index) KV_SERIALIZE(major) KV_SERIALIZE(minor) END_KV_SERIALIZE_MAP() diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h index e134a7ca..4491f313 100644 --- a/src/cryptonote_basic/tx_extra.h +++ b/src/cryptonote_basic/tx_extra.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h index e69f9fec..3929e740 100644 --- a/src/cryptonote_basic/verification_context.h +++ b/src/cryptonote_basic/verification_context.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_config.cpp b/src/cryptonote_config.cpp index 8ae3c317..2b5148bc 100644 --- a/src/cryptonote_config.cpp +++ b/src/cryptonote_config.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details // All rights reserved. diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 0c2f5885..72dc0ac9 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -23,6 +23,7 @@ #include #include #include +#include #define CRYPTONOTE_DNS_TIMEOUT_MS 20000 @@ -101,8 +102,19 @@ // coin emission change interval/speed configs #define COIN_EMISSION_MONTH_INTERVAL 6 // months to change emission speed #define COIN_EMISSION_HEIGHT_INTERVAL ((uint64_t)(COIN_EMISSION_MONTH_INTERVAL * (30.4375 * 24 * 3600) / common_config::DIFFICULTY_TARGET)) // calculated to # of heights to change emission speed -#define PEAK_COIN_EMISSION_YEAR 4 -#define PEAK_COIN_EMISSION_HEIGHT ((uint64_t)(((12 * 30.4375 * 24 * 3600) / common_config::DIFFICULTY_TARGET) * PEAK_COIN_EMISSION_YEAR)) // = (# of heights emmitted per year) * PEAK_COIN_EMISSION_YEAR + +static constexpr std::array COIN_EMISSION_STEPS = {{ + 32000000000, 36450000000, 41970000000, 48590000000, 56280000000, + 65070000000, 65070000000, 60820000000, 56840000000, 53130000000, + 49660000000, 46420000000, 43390000000, 40550000000, 37910000000, + 35430000000, 33120000000, 30950000000, 28930000000, 27040000000, + 25280000000, 23630000000, 22080000000, 20640000000, 19290000000, + 18030000000, 16850000000, 15750000000, 14720000000, 13760000000, + 12860000000, 12020000000, 11240000000, 10500000000, 9820000000, + 9180000000, 8580000000, 8020000000, 7490000000, 7000000000, + 6540000000, 6120000000, 5720000000, 5340000000, 4990000000, + 4670000000, 4360000000, 4080000000 +}}; #define TX_FORK_ID_STR "ryo-currency" @@ -258,8 +270,8 @@ struct config static constexpr uint16_t RPC_DEFAULT_PORT = 12211; static constexpr uint16_t ZMQ_RPC_DEFAULT_PORT = 12212; - //Random UUID generated from radioactive cs-137 ( http://www.fourmilab.ch/hotbits/how3.html ) it gives me a nice warm feeling =) - static constexpr boost::uuids::uuid NETWORK_ID = { { 0xcd, 0xac, 0x50, 0x2e, 0xb3, 0x74, 0x8f, 0xf2, 0x0f, 0xb7, 0x72, 0x18, 0x0f, 0x73, 0x24, 0x13 } }; + //Random UUID generated from radioactive cs-137 ( http://www.fourmilab.ch/hotbits/how3.html ) it gives me a nice warm feeling =) + static constexpr boost::uuids::uuid NETWORK_ID = { { 0xcd, 0xac, 0x50, 0x2e, 0xb3, 0x74, 0x8f, 0xf2, 0x0f, 0xb7, 0x72, 0x18, 0x0f, 0x73, 0x24, 0x13 } }; static constexpr const char *GENESIS_TX = "023c01ff0001808098d0daf1d00f028be379aa57a70fa19c0ee5765fdc3d2aae0b1034158f4963e157d9042c24fbec21013402fc7071230f1f86f33099119105a7b1f64a898526060ab871e685059c223100"; @@ -286,16 +298,16 @@ struct config static constexpr uint64_t RYO_LONG_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x29e192; // RYoE static constexpr uint64_t RYO_LONG_SUBADDRESS_BASE58_PREFIX = 0x30e192; // RYoU - static constexpr uint16_t P2P_DEFAULT_PORT = 13310; - static constexpr uint16_t RPC_DEFAULT_PORT = 13311; - static constexpr uint16_t ZMQ_RPC_DEFAULT_PORT = 13312; - - static constexpr boost::uuids::uuid NETWORK_ID = { { 0x6f, 0x81, 0x7d, 0x7e, 0xa2, 0x0b, 0x71, 0x77, 0x22, 0xc8, 0xd2, 0xff, 0x02, 0x5d, 0xe9, 0x92 } }; + static constexpr uint16_t P2P_DEFAULT_PORT = 13310; + static constexpr uint16_t RPC_DEFAULT_PORT = 13311; + static constexpr uint16_t ZMQ_RPC_DEFAULT_PORT = 13312; + + static constexpr boost::uuids::uuid NETWORK_ID = { { 0x6f, 0x81, 0x7d, 0x7e, 0xa2, 0x0b, 0x71, 0x77, 0x22, 0xc8, 0xd2, 0xff, 0x02, 0x5d, 0xe9, 0x92 } }; static constexpr const char *GENESIS_TX = "023c01ff0001808098d0daf1d00f028be379aa57a70fa19c0ee5765fdc3d2aae0b1034158f4963e157d9042c24fbec21013402fc7071230f1f86f33099119105a7b1f64a898526060ab871e685059c223100"; static constexpr uint32_t GENESIS_NONCE = 10001; - + ////////////////////// Dev fund constants // How ofen do we add the dev reward static constexpr uint64_t DEV_FUND_PERIOD = 15 * 24; // 1 day @@ -317,16 +329,16 @@ struct config static constexpr uint64_t RYO_LONG_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x1fbbe192; // RYosE static constexpr uint64_t RYO_LONG_SUBADDRESS_BASE58_PREFIX = 0xe3c2192; // RYosU - static constexpr uint16_t P2P_DEFAULT_PORT = 14410; - static constexpr uint16_t RPC_DEFAULT_PORT = 14411; - static constexpr uint16_t ZMQ_RPC_DEFAULT_PORT = 14412; - - static constexpr boost::uuids::uuid NETWORK_ID = { { 0x15, 0x77, 0x3a, 0x26, 0x42, 0xa0, 0x3f, 0xf3, 0xe5, 0x79, 0x72, 0x8d, 0x4e, 0x5a, 0xf2, 0x98 } }; + static constexpr uint16_t P2P_DEFAULT_PORT = 14410; + static constexpr uint16_t RPC_DEFAULT_PORT = 14411; + static constexpr uint16_t ZMQ_RPC_DEFAULT_PORT = 14412; + + static constexpr boost::uuids::uuid NETWORK_ID = { { 0x15, 0x77, 0x3a, 0x26, 0x42, 0xa0, 0x3f, 0xf3, 0xe5, 0x79, 0x72, 0x8d, 0x4e, 0x5a, 0xf2, 0x98 } }; static constexpr const char *GENESIS_TX = "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b"; static constexpr uint32_t GENESIS_NONCE = 10002; - + ////////////////////// Dev fund constants // How ofen do we add the dev reward static constexpr uint64_t DEV_FUND_PERIOD = 15 * 24; // 1 day diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 6d26fbb0..9045438a 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -84,6 +84,7 @@ target_link_libraries(cryptonote_core ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_THREAD_LIBRARY} + fmt::fmt-header-only PRIVATE ${Blocks} ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index d4060c6a..b6b6ac18 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,6 +18,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + #include #include #include @@ -49,8 +50,9 @@ #include "blocks/blocks.h" #endif -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "blockchain" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blockchain"); #define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100 * 1024 * 1024) // 100 MB @@ -69,8 +71,6 @@ using epee::string_tools::pod_to_hex; DISABLE_VS_WARNINGS(4267) -#define MERROR_VER(x) MCERROR("verify", x) - // used to overestimate the block reward when estimating a per kB to use #define BLOCK_REWARD_OVERESTIMATE ((uint64_t)(16000000000)) @@ -130,12 +130,12 @@ static const struct Blockchain::Blockchain(tx_memory_pool &tx_pool) : m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_current_block_cumul_sz_median(0), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_cancel(false) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); } //------------------------------------------------------------------ bool Blockchain::have_tx(const crypto::hash &id) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -145,7 +145,7 @@ bool Blockchain::have_tx(const crypto::hash &id) const //------------------------------------------------------------------ bool Blockchain::have_tx_keyimg_as_spent(const crypto::key_image &key_im) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -159,7 +159,7 @@ bool Blockchain::have_tx_keyimg_as_spent(const crypto::key_image &key_im) const template bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_key &tx_in_to_key, visitor_t &vis, const crypto::hash &tx_prefix_hash, uint64_t *pmax_related_block_height) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // ND: Disable locking and make method private. //CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -194,13 +194,13 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke m_db->get_output_key(0, absolute_offsets, outputs, true); if(absolute_offsets.size() != outputs.size()) { - MERROR_VER("Output does not exist!"); + GULPSF_VERIFY_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } catch(...) { - MERROR_VER("Output does not exist!"); + GULPSF_VERIFY_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } @@ -209,7 +209,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke // check for partial results and add the rest if needed; if(outputs.size() < absolute_offsets.size() && outputs.size() > 0) { - MDEBUG("Additional outputs needed: " << absolute_offsets.size() - outputs.size()); + GULPSF_LOG_L1("Additional outputs needed: {}", absolute_offsets.size() - outputs.size()); std::vector add_offsets; std::vector add_outputs; for(size_t i = outputs.size(); i < absolute_offsets.size(); i++) @@ -219,13 +219,13 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke m_db->get_output_key(0, add_offsets, add_outputs, true); if(add_offsets.size() != add_outputs.size()) { - MERROR_VER("Output does not exist!"); + GULPSF_VERIFY_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } catch(...) { - MERROR_VER("Output does not exist!"); + GULPSF_VERIFY_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end()); @@ -249,13 +249,13 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke // call to the passed boost visitor to grab the public key for the output if(!vis.handle_output(output_index.unlock_time, output_index.pubkey, output_index.commitment)) { - MERROR_VER("Failed to handle_output for output no = " << count << ", with absolute offset " << i); + GULPSF_VERIFY_ERR_TX("Failed to handle_output for output no = {}, with absolute offset {}", count , i); return false; } } catch(...) { - MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i); + GULPSF_VERIFY_ERR_TX("Output does not exist! amount = {}, absolute_offset = {}", tx_in_to_key.amount , i); return false; } @@ -272,12 +272,12 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke } catch(const OUTPUT_DNE &e) { - MERROR_VER("Output does not exist: " << e.what()); + GULPS_VERIFY_ERR_TX("Output does not exist: ", e.what()); return false; } catch(const TX_DNE &e) { - MERROR_VER("Transaction does not exist: " << e.what()); + GULPS_VERIFY_ERR_TX("Transaction does not exist: ", e.what()); return false; } } @@ -287,7 +287,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke //------------------------------------------------------------------ uint64_t Blockchain::get_current_blockchain_height() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -299,16 +299,16 @@ uint64_t Blockchain::get_current_blockchain_height() const // dereferencing a null BlockchainDB pointer bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline, const cryptonote::test_options *test_options) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_tx_pool); CRITICAL_REGION_LOCAL1(m_blockchain_lock); memcpy(m_dev_view_key.data, common_config::DEV_FUND_VIEWKEY, 32); - + address_parse_info dev_addr; if(!get_account_address_from_str(dev_addr, std::string(common_config::DEV_FUND_ADDRESS))) { - LOG_ERROR("Failed to parse dev address"); + GULPS_LOG_ERROR("Failed to parse dev address"); return false; } @@ -316,18 +316,18 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline crypto::public_key vk; if(!secret_key_to_public_key(m_dev_view_key, vk) || vk != dev_addr.address.m_view_public_key) { - LOG_ERROR("Dev private view key failed verification!"); + GULPS_LOG_ERROR("Dev private view key failed verification!"); return false; } if(db == nullptr) { - LOG_ERROR("Attempted to init Blockchain with null DB"); + GULPS_LOG_ERROR("Attempted to init Blockchain with null DB"); return false; } if(!db->is_open()) { - LOG_ERROR("Attempted to init Blockchain with unopened DB"); + GULPS_LOG_ERROR("Attempted to init Blockchain with unopened DB"); delete db; return false; } @@ -375,7 +375,7 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline // taking testnet into account if(!m_db->height()) { - MINFO("Blockchain not loaded, generating genesis block."); + GULPS_INFO("Blockchain not loaded, generating genesis block."); block bl = boost::value_initialized(); block_verification_context bvc = boost::value_initialized(); if(m_nettype == TESTNET) @@ -391,7 +391,7 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline generate_genesis_block(MAINNET, bl, config::GENESIS_TX, config::GENESIS_NONCE); } add_new_block(bl, bvc); - CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "Failed to add genesis block to blockchain"); + GULPS_CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "Failed to add genesis block to blockchain"); } // TODO: if blockchain load successful, verify blockchain against both // hard-coded and runtime-loaded (and enforced) checkpoints. @@ -425,7 +425,7 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline load_compiled_in_block_hashes(); #endif - MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block()); + GULPSF_INFO("Blockchain initialized. last block: {}, {} time ago, current difficulty: {}", m_db->height() - 1 , epee::misc_utils::get_time_interval_string(timestamp_diff) , get_difficulty_for_next_block()); m_db->block_txn_stop(); uint64_t num_popped_blocks = 0; @@ -438,15 +438,15 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline if(ideal_hf_version <= 1 || ideal_hf_version == top_block.major_version) { if(num_popped_blocks > 0) - MGINFO("Initial popping done, top block: " << top_id << ", top height: " << top_height << ", block version: " << (uint64_t)top_block.major_version); + GULPSF_GLOBAL_PRINT("Initial popping done, top block: {}, top height: {}, block version: {}", top_id , top_height, (uint64_t)top_block.major_version); break; } else { if(num_popped_blocks == 0) - MGINFO("Current top block " << top_id << " at height " << top_height << " has version " << (uint64_t)top_block.major_version << " which disagrees with the ideal version " << (uint64_t)ideal_hf_version); + GULPSF_GLOBAL_PRINT("Current top block {} at height {} has version {} which disagrees with the ideal version {}", top_id, top_height, (uint64_t)top_block.major_version, (uint64_t)ideal_hf_version); if(num_popped_blocks % 100 == 0) - MGINFO("Popping blocks... " << top_height); + GULPSF_GLOBAL_PRINT("Popping blocks... {}", top_height); ++num_popped_blocks; block popped_block; std::vector popped_txs; @@ -458,12 +458,12 @@ bool Blockchain::init(BlockchainDB *db, const network_type nettype, bool offline // so we re-throw catch(const std::exception &e) { - MERROR("Error popping block from blockchain: " << e.what()); + GULPSF_ERROR("Error popping block from blockchain: {}", e.what()); throw; } catch(...) { - MERROR("Error popping block from blockchain, throwing!"); + GULPS_ERROR("Error popping block from blockchain, throwing!"); throw; } } @@ -491,7 +491,7 @@ bool Blockchain::init(BlockchainDB *db, HardFork *&hf, const network_type nettyp //------------------------------------------------------------------ bool Blockchain::store_blockchain() { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // lock because the rpc_thread command handler also calls this CRITICAL_REGION_LOCAL(m_db->m_synchronization_lock); @@ -504,26 +504,26 @@ bool Blockchain::store_blockchain() } catch(const std::exception &e) { - MERROR(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!"); + GULPSF_ERROR("Error syncing blockchain db: {}-- shutting down now to prevent issues!", e.what()); throw; } catch(...) { - MERROR("There was an issue storing the blockchain, shutting down now to prevent issues!"); + GULPS_ERROR("There was an issue storing the blockchain, shutting down now to prevent issues!"); throw; } TIME_MEASURE_FINISH(save); if(m_show_time_stats) - MINFO("Blockchain stored OK, took: " << save << " ms"); + GULPSF_INFO("Blockchain stored OK, took: {} ms", save ); return true; } //------------------------------------------------------------------ bool Blockchain::deinit() { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); - MTRACE("Stopping blockchain read/write activity"); + GULPS_LOG_L2("Stopping blockchain read/write activity"); // stop async service m_async_work_idle.reset(); @@ -541,15 +541,15 @@ bool Blockchain::deinit() try { m_db->close(); - MTRACE("Local blockchain read/write activity stopped successfully"); + GULPS_LOG_L2("Local blockchain read/write activity stopped successfully"); } catch(const std::exception &e) { - LOG_ERROR(std::string("Error closing blockchain db: ") + e.what()); + GULPSF_LOG_ERROR("Error closing blockchain db: {}", e.what()); } catch(...) { - LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!"); + GULPS_LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!"); } delete m_hardfork; @@ -564,7 +564,7 @@ bool Blockchain::deinit() // from it to the tx_pool block Blockchain::pop_block_from_blockchain() { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); m_timestamps_and_difficulties_height = 0; @@ -580,12 +580,12 @@ block Blockchain::pop_block_from_blockchain() // so we re-throw catch(const std::exception &e) { - LOG_ERROR("Error popping block from blockchain: " << e.what()); + GULPSF_LOG_ERROR("Error popping block from blockchain: {}", e.what()); throw; } catch(...) { - LOG_ERROR("Error popping block from blockchain, throwing!"); + GULPS_LOG_ERROR("Error popping block from blockchain, throwing!"); throw; } @@ -604,7 +604,7 @@ block Blockchain::pop_block_from_blockchain() bool r = m_tx_pool.add_tx(tx, tvc, true, true, false); if(!r) { - LOG_ERROR("Error returning transaction to tx_pool"); + GULPS_LOG_ERROR("Error returning transaction to tx_pool"); } } } @@ -622,7 +622,7 @@ block Blockchain::pop_block_from_blockchain() //------------------------------------------------------------------ bool Blockchain::reset_and_set_genesis_block(const block &b) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); m_timestamps_and_difficulties_height = 0; m_alternative_chains.clear(); @@ -637,7 +637,7 @@ bool Blockchain::reset_and_set_genesis_block(const block &b) //------------------------------------------------------------------ crypto::hash Blockchain::get_tail_id(uint64_t &height) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); height = m_db->height() - 1; return get_tail_id(); @@ -645,7 +645,7 @@ crypto::hash Blockchain::get_tail_id(uint64_t &height) const //------------------------------------------------------------------ crypto::hash Blockchain::get_tail_id() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -667,7 +667,7 @@ crypto::hash Blockchain::get_tail_id() const */ bool Blockchain::get_short_chain_history(std::list &ids) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); uint64_t i = 0; uint64_t current_multiplier = 1; @@ -710,7 +710,7 @@ bool Blockchain::get_short_chain_history(std::list &ids) const //------------------------------------------------------------------ crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -724,12 +724,12 @@ crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const } catch(const std::exception &e) { - MERROR(std::string("Something went wrong fetching block hash by height: ") + e.what()); + GULPSF_ERROR("Something went wrong fetching block hash by height: {}", e.what()); throw; } catch(...) { - MERROR(std::string("Something went wrong fetching block hash by height")); + GULPS_ERROR("Something went wrong fetching block hash by height"); throw; } return null_hash; @@ -737,7 +737,7 @@ crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const //------------------------------------------------------------------ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // try to find block in main chain @@ -762,12 +762,12 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph } catch(const std::exception &e) { - MERROR(std::string("Something went wrong fetching block by hash: ") + e.what()); + GULPS_ERROR("Something went wrong fetching block by hash: {}", e.what()); throw; } catch(...) { - MERROR(std::string("Something went wrong fetching block hash by hash")); + GULPS_ERROR("Something went wrong fetching block hash by hash"); throw; } @@ -780,7 +780,7 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph // less blocks than desired if there aren't enough. difficulty_type Blockchain::get_difficulty_for_next_block() { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); std::vector timestamps; std::vector difficulties; @@ -857,7 +857,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block() // that had been removed. bool Blockchain::rollback_blockchain_switching(std::list &original_chain, uint64_t rollback_height) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // fail if rollback_height passed is too high @@ -882,15 +882,15 @@ bool Blockchain::rollback_blockchain_switching(std::list &original_chain, { block_verification_context bvc = boost::value_initialized(); bool r = handle_block_to_main_chain(bl, bvc); - CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC! failed to add (again) block while chain switching during the rollback!"); + GULPS_CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC! failed to add (again) block while chain switching during the rollback!"); } m_hardfork->reorganize_from_chain_height(rollback_height); - LOG_PRINT_L1("Rollback to height " << rollback_height << " was successful."); + GULPSF_LOG_L1("Rollback to height {} was successful.", rollback_height ); if(original_chain.size()) { - LOG_PRINT_L1("Restoration to previous blockchain successful as well."); + GULPS_LOG_L1("Restoration to previous blockchain successful as well."); } return true; } @@ -916,18 +916,18 @@ double calc_poisson_ln(double lam, uint64_t k) // boolean based on success therein. bool Blockchain::switch_to_alternative_blockchain(std::list &alt_chain, bool discard_disconnected_chain) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); m_timestamps_and_difficulties_height = 0; // if empty alt chain passed (not sure how that could happen), return false - CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed"); + GULPS_CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed"); // verify that main chain has front of alt chain's parent block if(!m_db->block_exists(alt_chain.front()->second.bl.prev_id)) { - LOG_ERROR("Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!"); + GULPS_LOG_ERROR("Attempting to move to an alternate chain, but it doesn't appear to connect to the main chain!"); return false; } @@ -953,12 +953,11 @@ bool Blockchain::switch_to_alternative_blockchain(std::list get_adjusted_time() + common_config::BLOCK_FUTURE_TIME_LIMIT_V3) { - LOG_ERROR("Attempting to move to an alternate chain, but it failed FTL check! timestamp: " << high_timestamp << - " limit: " << get_adjusted_time() + common_config::BLOCK_FUTURE_TIME_LIMIT_V3); + GULPSF_LOG_ERROR("Attempting to move to an alternate chain, but it failed FTL check! timestamp: {} limit: {}", high_timestamp , get_adjusted_time() + common_config::BLOCK_FUTURE_TIME_LIMIT_V3); return false; } - LOG_PRINT_L1("Poisson check triggered by reorg size of " << alt_chain_size); + GULPSF_LOG_L1("Poisson check triggered by reorg size of {}", alt_chain_size); uint64_t failed_checks = 0, i = 1; constexpr crypto::hash zero_hash = {{0}}; @@ -974,7 +973,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list= high_timestamp) { - LOG_PRINT_L1("Skipping check at depth " << i << " due to tampered timestamp on main chain."); + GULPSF_LOG_L1("Skipping check at depth {} due to tampered timestamp on main chain.", i ); failed_checks++; continue; } @@ -982,17 +981,17 @@ bool Blockchain::switch_to_alternative_blockchain(std::list i / 2) { - LOG_ERROR("Attempting to move to an alternate chain, but it failed Poisson check! " << failed_checks << " fails out of " << i << " alt_chain_size: " << alt_chain_size); + GULPSF_LOG_ERROR("Attempting to move to an alternate chain, but it failed Poisson check! {} fails out of {} alt_chain_size: {}", failed_checks , i, alt_chain_size); return false; } } @@ -1021,7 +1020,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::listsecond, get_block_hash(ch_ent->second.bl)); - LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl)); + GULPSF_LOG_L1("The block was inserted as invalid while connecting new alternative chain, block_id: {}", get_block_hash(ch_ent->second.bl)); m_alternative_chains.erase(*alt_ch_iter++); for(auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end();) @@ -1054,7 +1053,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::listreorganize_from_chain_height(split_height); - MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height()); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_GREEN, "REORGANIZE SUCCESS! on height: {}, new blockchain size: {}", split_height , m_db->height()); return true; } //------------------------------------------------------------------ @@ -1077,7 +1076,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list &alt_chain, block_extended_info &bei) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); std::vector timestamps; std::vector cumulative_difficulties; @@ -1117,8 +1116,8 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: } // make sure we haven't accidentally grabbed too many blocks...maybe don't need this check? - CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= block_count, false, "Internal error, alt_chain.size()[" << alt_chain.size() - << "] + vtimestampsec.size()[" << timestamps.size() << "] NOT <= DIFFICULTY_WINDOW[]" << block_count); + GULPS_CHECK_AND_ASSERT_MES((alt_chain.size() + timestamps.size()) <= block_count, false, "Internal error, alt_chain.size()[" , alt_chain.size() + , "] + vtimestampsec.size()[", timestamps.size(), "] NOT <= DIFFICULTY_WINDOW[]", block_count); for(auto it : alt_chain) { @@ -1162,18 +1161,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: // a non-overflowing tx amount (dubious necessity on this check) bool Blockchain::prevalidate_miner_transaction(const block &b, uint64_t height) { - LOG_PRINT_L3("Blockchain::" << __func__); - CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs"); - CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type"); - CHECK_AND_ASSERT_MES(b.miner_tx.rct_signatures.type == rct::RCTTypeNull, false, "V1 miner transactions are not allowed."); + GULPS_LOG_L3("Blockchain::", __func__); + GULPS_CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs"); + GULPS_CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type"); + GULPS_CHECK_AND_ASSERT_MES(b.miner_tx.rct_signatures.type == rct::RCTTypeNull, false, "V1 miner transactions are not allowed."); if(boost::get(b.miner_tx.vin[0]).height != height) { - MWARNING("The miner transaction in block has invalid height: " << boost::get(b.miner_tx.vin[0]).height << ", expected: " << height); + GULPSF_WARN("The miner transaction in block has invalid height: {}, expected: ", boost::get(b.miner_tx.vin[0]).height, height); return false; } - MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx)); - CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW); + GULPS_LOG_L1("Miner tx hash: ", get_transaction_hash(b.miner_tx)); + GULPS_CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" , b.miner_tx.unlock_time , ", expected " , height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW); //check outs overflow //NOTE: not entirely sure this is necessary, given that this function is @@ -1181,7 +1180,7 @@ bool Blockchain::prevalidate_miner_transaction(const block &b, uint64_t height) // does not overflow a uint64_t, and this transaction *is* a uint64_t... if(!check_outs_overflow(b.miner_tx)) { - MERROR("miner transaction has money overflow in block " << get_block_hash(b)); + GULPSF_ERROR("miner transaction has money overflow in block {}", get_block_hash(b)); return false; } @@ -1191,13 +1190,13 @@ bool Blockchain::prevalidate_miner_transaction(const block &b, uint64_t height) // This function validates the miner transaction reward bool Blockchain::validate_miner_transaction_v2(const block &b, uint64_t height, size_t cumulative_block_size, uint64_t fee, uint64_t &base_reward, uint64_t already_generated_coins, bool &partial_block_reward) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); crypto::public_key tx_pub = get_tx_pub_key_from_extra(b.miner_tx); crypto::key_derivation deriv; if(tx_pub == null_pkey || !generate_key_derivation(tx_pub, m_dev_view_key, deriv)) { - MERROR_VER("Transaction public key is absent or invalid!"); + GULPS_VERIFY_ERR_TX("Transaction public key is absent or invalid!"); return false; } @@ -1209,9 +1208,9 @@ bool Blockchain::validate_miner_transaction_v2(const block &b, uint64_t height, const tx_out& o = b.miner_tx.vout[i]; crypto::public_key pk; - CHECK_AND_ASSERT_MES(derive_public_key(deriv, i, m_dev_spend_key, pk), false, "Dev public key is invalid!"); - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "Out needs to be txout_to_key!"); - CHECK_AND_ASSERT_MES(o.amount != 0, false, "Non-plaintext output in a miner tx"); + GULPS_CHECK_AND_ASSERT_MES(derive_public_key(deriv, i, m_dev_spend_key, pk), false, "Dev public key is invalid!"); + GULPS_CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "Out needs to be txout_to_key!"); + GULPS_CHECK_AND_ASSERT_MES(o.amount != 0, false, "Non-plaintext output in a miner tx"); if(boost::get(b.miner_tx.vout[i].target).key == pk) dev_money += o.amount; @@ -1226,13 +1225,13 @@ bool Blockchain::validate_miner_transaction_v2(const block &b, uint64_t height, if(!get_block_reward(m_nettype, epee::misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward, m_db->height())) { - MERROR_VER("block size " << cumulative_block_size << " is bigger than allowed for this blockchain"); + GULPSF_VERIFY_ERR_TX("block size {} is bigger than allowed for this blockchain", cumulative_block_size ); return false; } if(base_reward + fee < miner_money) { - MERROR_VER("coinbase transaction spend too much money (" << print_money(miner_money) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")"); + GULPSF_VERIFY_ERR_TX("coinbase transaction spend too much money ({}). Block reward is {}({}+{})", print_money(miner_money), print_money(base_reward + fee), print_money(base_reward), print_money(fee)); return false; } @@ -1241,14 +1240,14 @@ bool Blockchain::validate_miner_transaction_v2(const block &b, uint64_t height, if(dev_money_needed != dev_money) { - MERROR_VER("Coinbase transaction generates wrong dev fund amount. Generated " << print_money(dev_money) << " nedded " << print_money(dev_money_needed)); + GULPSF_VERIFY_ERR_TX("Coinbase transaction generates wrong dev fund amount. Generated {} nedded {}", print_money(dev_money), print_money(dev_money_needed)); return false; } // from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward // to show the amount of coins that were actually generated, the remainder will be pushed back for later // emission. This modifies the emission curve very slightly. - CHECK_AND_ASSERT_MES(miner_money - fee <= base_reward, false, "base reward calculation bug"); + GULPS_CHECK_AND_ASSERT_MES(miner_money - fee <= base_reward, false, "base reward calculation bug"); if(base_reward + fee != miner_money) partial_block_reward = true; base_reward = miner_money - fee; @@ -1258,7 +1257,7 @@ bool Blockchain::validate_miner_transaction_v2(const block &b, uint64_t height, bool Blockchain::validate_miner_transaction_v1(const block &b, size_t cumulative_block_size, uint64_t fee, uint64_t &base_reward, uint64_t already_generated_coins, bool &partial_block_reward) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); //validate reward uint64_t money_in_use = 0; for(auto &o : b.miner_tx.vout) @@ -1270,19 +1269,19 @@ bool Blockchain::validate_miner_transaction_v1(const block &b, size_t cumulative if(!get_block_reward(m_nettype, epee::misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward, m_db->height())) { - MERROR_VER("block size " << cumulative_block_size << " is bigger than allowed for this blockchain"); + GULPSF_VERIFY_ERR_TX("block size {} is bigger than allowed for this blockchain", cumulative_block_size ); return false; } if(base_reward + fee < money_in_use) { - MERROR_VER("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")"); + GULPSF_VERIFY_ERR_TX("coinbase transaction spend too much money ({}). Block reward is {}({}+{})", print_money(money_in_use), print_money(base_reward + fee), print_money(base_reward), print_money(fee)); return false; } // from hard fork 2, since a miner can claim less than the full block reward, we update the base_reward // to show the amount of coins that were actually generated, the remainder will be pushed back for later // emission. This modifies the emission curve very slightly. - CHECK_AND_ASSERT_MES(money_in_use - fee <= base_reward, false, "base reward calculation bug"); + GULPS_CHECK_AND_ASSERT_MES(money_in_use - fee <= base_reward, false, "base reward calculation bug"); if(base_reward + fee != money_in_use) partial_block_reward = true; base_reward = money_in_use - fee; @@ -1293,7 +1292,7 @@ bool Blockchain::validate_miner_transaction_v1(const block &b, size_t cumulative // get the block sizes of the last blocks, and return by reference . void Blockchain::get_last_n_blocks_sizes(std::vector &sz, size_t count) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); auto h = m_db->height(); @@ -1313,13 +1312,13 @@ void Blockchain::get_last_n_blocks_sizes(std::vector &sz, size_t count) //------------------------------------------------------------------ uint64_t Blockchain::get_current_cumulative_blocksize_limit() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); return m_current_block_cumul_sz_limit; } //------------------------------------------------------------------ uint64_t Blockchain::get_current_cumulative_blocksize_median() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); return m_current_block_cumul_sz_median; } //------------------------------------------------------------------ @@ -1336,7 +1335,7 @@ uint64_t Blockchain::get_current_cumulative_blocksize_median() const // necessary at all. bool Blockchain::create_block_template(block &b, const account_public_address &miner_address, difficulty_type &diffic, uint64_t &height, uint64_t &expected_reward, const blobdata &ex_nonce) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); size_t median_size; uint64_t already_generated_coins; @@ -1355,7 +1354,7 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m } diffic = get_difficulty_for_next_block(); - CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead."); + GULPS_CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead."); median_size = m_current_block_cumul_sz_limit / 2; already_generated_coins = m_db->get_block_already_generated_coins(height - 1); @@ -1377,7 +1376,7 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m auto cur_res = m_tx_pool.m_transactions.find(cur_hash); if(cur_res == m_tx_pool.m_transactions.end()) { - LOG_ERROR("Creating block template: error: transaction not found"); + GULPS_LOG_ERROR("Creating block template: error: transaction not found"); continue; } tx_memory_pool::tx_details &cur_tx = cur_res->second; @@ -1385,24 +1384,24 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m real_fee += cur_tx.fee; if(cur_tx.blob_size != get_object_blobsize(cur_tx.tx)) { - LOG_ERROR("Creating block template: error: invalid transaction size"); + GULPS_LOG_ERROR("Creating block template: error: invalid transaction size"); } if(cur_tx.fee != cur_tx.tx.rct_signatures.txnFee) { - LOG_ERROR("Creating block template: error: invalid fee"); + GULPS_LOG_ERROR("Creating block template: error: invalid fee"); } } if(txs_size != real_txs_size) { - LOG_ERROR("Creating block template: error: wrongly calculated transaction size"); + GULPS_LOG_ERROR("Creating block template: error: wrongly calculated transaction size"); } if(fee != real_fee) { - LOG_ERROR("Creating block template: error: wrongly calculated fee"); + GULPS_LOG_ERROR("Creating block template: error: wrongly calculated fee"); } CRITICAL_REGION_END(); - MDEBUG("Creating block template: height " << height << ", median size " << median_size << ", already generated coins " << already_generated_coins << ", transaction size " << txs_size << ", fee " << fee); + GULPSF_LOG_L1("Creating block template: height {}, median size {}, already generated coins {}, transaction size {}, fee {}", height, median_size, already_generated_coins, txs_size, fee); #endif /* @@ -1411,22 +1410,22 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m */ //make blocks coin-base tx looks close to real coinbase tx to get truthful blob size bool r = construct_miner_tx(m_nettype, height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce); - CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance"); size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx); #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - MDEBUG("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) << ", cumulative size " << cumulative_size); + GULPSF_LOG_L1("Creating block template: miner tx size {}, cumulative size {}", get_object_blobsize(b.miner_tx) , cumulative_size); #endif for(size_t try_count = 0; try_count != 10; ++try_count) { r = construct_miner_tx(m_nettype, height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce); - CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance"); size_t coinbase_blob_size = get_object_blobsize(b.miner_tx); if(coinbase_blob_size > cumulative_size - txs_size) { cumulative_size = txs_size + coinbase_blob_size; #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - MDEBUG("Creating block template: miner tx size " << coinbase_blob_size << ", cumulative size " << cumulative_size << " is greater than before"); + GULPSF_LOG_L1("Creating block template: miner tx size {}, cumulative size {} is greater than before", coinbase_blob_size , cumulative_size ); #endif continue; } @@ -1435,31 +1434,31 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m { size_t delta = cumulative_size - txs_size - coinbase_blob_size; #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - MDEBUG("Creating block template: miner tx size " << coinbase_blob_size << ", cumulative size " << txs_size + coinbase_blob_size << " is less than before, adding " << delta << " zero bytes"); + GULPSF_LOG_L1("Creating block template: miner tx size {}, cumulative size {} is less than before, adding {} zero bytes", coinbase_blob_size, txs_size + coinbase_blob_siz, delta); #endif b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0); //here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len. if(cumulative_size != txs_size + get_object_blobsize(b.miner_tx)) { - CHECK_AND_ASSERT_MES(cumulative_size + 1 == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " + 1 is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx)); + GULPS_CHECK_AND_ASSERT_MES(cumulative_size + 1 == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" , cumulative_size , " + 1 is not equal txs_cumulative_size=" , txs_size , " + get_object_blobsize(b.miner_tx)=" , get_object_blobsize(b.miner_tx)); b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1); if(cumulative_size != txs_size + get_object_blobsize(b.miner_tx)) { //fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size - MDEBUG("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1); + GULPSF_LOG_L1("Miner tx creation has no luck with delta_extra size = {} and {}", delta , delta - 1); cumulative_size += delta - 1; continue; } - MDEBUG("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count); + GULPSF_LOG_L1("Setting extra for block: {}, try_count={}", b.miner_tx.extra.size() , try_count); } } - CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx)); + GULPS_CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" , cumulative_size , " is not equal txs_cumulative_size=" , txs_size , " + get_object_blobsize(b.miner_tx)=" , get_object_blobsize(b.miner_tx)); #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - MDEBUG("Creating block template: miner tx size " << coinbase_blob_size << ", cumulative size " << cumulative_size << " is now good"); + GULPSF_LOG_L1("Creating block template: miner tx size {}, cumulative size {} is now good", coinbase_blob_size , cumulative_size ); #endif return true; } - LOG_ERROR("Failed to create_block_template with " << 10 << " tries"); + GULPSF_LOG_ERROR("Failed to create_block_template with {}, tries", 10); return false; } //------------------------------------------------------------------ @@ -1467,7 +1466,7 @@ bool Blockchain::create_block_template(block &b, const account_public_address &m // the needed number of timestamps for the BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW. bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector ×tamps) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); uint64_t window_size = check_hard_fork_feature(FORK_V3_DIFFICULTY) ? common_config::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V3 : common_config::BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2; @@ -1476,8 +1475,8 @@ bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vect CRITICAL_REGION_LOCAL(m_blockchain_lock); size_t need_elements = window_size - timestamps.size(); - CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " - << " m_db->height() -- " << start_top_height << " >= " << m_db->height()); + GULPS_CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " + ," m_db->height() -- ", start_top_height, " >= ", m_db->height()); size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0; while(start_top_height != stop_offset) { @@ -1495,13 +1494,13 @@ bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vect // a long forked chain eventually. bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id, block_verification_context &bvc) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); m_timestamps_and_difficulties_height = 0; uint64_t block_height = get_block_height(b); if(0 == block_height) { - MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0."); + GULPSF_VERIFY_ERR_BLK("Block with id: {} (as alternative), but miner tx says height is 0.", epee::string_tools::pod_to_hex(id) ); bvc.m_verifivation_failed = true; return false; } @@ -1511,9 +1510,8 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id // the block to be added, then this is fine. if(!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height)) { - MERROR_VER("Block with id: " << id << std::endl - << " can't be accepted for alternative chain, block height: " << block_height << std::endl - << " blockchain height: " << get_current_blockchain_height()); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\n can't be accepted for alternative chain, block height: {}\n blockchain height: {}", id, + block_height, get_current_blockchain_height()); bvc.m_verifivation_failed = true; return false; } @@ -1521,8 +1519,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id // this is a cheap test if(!m_hardfork->check_for_height(b, block_height)) { - LOG_PRINT_L1("Block with id: " << id << std::endl - << "has old version for height " << block_height); + GULPSF_LOG_L1("Block with id: {}\nhas old version for height {}", id , block_height); bvc.m_verifivation_failed = true; return false; } @@ -1551,19 +1548,19 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id if(alt_chain.size()) { // make sure alt chain doesn't somehow start past the end of the main chain - CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height"); + GULPS_CHECK_AND_ASSERT_MES(m_db->height() > alt_chain.front()->second.height, false, "main blockchain wrong height"); // make sure that the blockchain contains the block that should connect // this alternate chain with it. if(!m_db->block_exists(alt_chain.front()->second.bl.prev_id)) { - MERROR("alternate chain does not appear to connect to main chain..."); + GULPS_ERROR("alternate chain does not appear to connect to main chain..."); return false; } // make sure block connects correctly to the main chain auto h = m_db->get_block_hash_from_height(alt_chain.front()->second.height - 1); - CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id, false, "alternative chain has wrong connection to main chain"); + GULPS_CHECK_AND_ASSERT_MES(h == alt_chain.front()->second.bl.prev_id, false, "alternative chain has wrong connection to main chain"); complete_timestamps_vector(m_db->get_block_height(alt_chain.front()->second.bl.prev_id), timestamps); } // if block not associated with known alternate chain @@ -1571,7 +1568,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id { // if block parent is not part of main chain or an alternate chain, // we ignore it - CHECK_AND_ASSERT_MES(parent_in_main, false, "internal error: broken imperative condition: parent_in_main"); + GULPS_CHECK_AND_ASSERT_MES(parent_in_main, false, "internal error: broken imperative condition: parent_in_main"); complete_timestamps_vector(m_db->get_block_height(b.prev_id), timestamps); } @@ -1580,8 +1577,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id // (not earlier than the median of the last X blocks) if(!check_block_timestamp(timestamps, b)) { - MERROR_VER("Block with id: " << id << std::endl - << " for alternative chain, has invalid timestamp: " << b.timestamp); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\n for alternative chain, has invalid timestamp: {}", id, b.timestamp); bvc.m_verifivation_failed = true; return false; } @@ -1589,33 +1585,39 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id // FIXME: consider moving away from block_extended_info at some point block_extended_info bei = boost::value_initialized(); bei.bl = b; - bei.height = alt_chain.size() ? it_prev->second.height + 1 : m_db->get_block_height(b.prev_id) + 1; + + const uint64_t prev_height = alt_chain.size() ? it_prev->second.height : m_db->get_block_height(b.prev_id); + bei.height = prev_height + 1; + + const uint64_t block_reward = get_outs_money_amount(b.miner_tx); + const uint64_t prev_generated_coins = alt_chain.size() ? + it_prev->second.already_generated_coins : m_db->get_block_already_generated_coins(prev_height); + bei.already_generated_coins = (block_reward < (MONEY_SUPPLY - prev_generated_coins)) ? + prev_generated_coins + block_reward : MONEY_SUPPLY; bool is_a_checkpoint; if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint)) { - LOG_ERROR("CHECKPOINT VALIDATION FAILED"); + GULPS_LOG_ERROR("CHECKPOINT VALIDATION FAILED"); bvc.m_verifivation_failed = true; return false; } // Check the block's hash against the difficulty target for its alt chain difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei); - CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); + GULPS_CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); crypto::hash proof_of_work = null_hash; get_block_longhash(m_nettype, bei.bl, m_pow_ctx, proof_of_work); if(!check_hash(proof_of_work, current_diff)) { - MERROR_VER("Block with id: " << id << std::endl - << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl - << " expected difficulty: " << current_diff); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\nfor alternative chain, does not have enough proof of work: {}\nexpected difficulty: {}", id, proof_of_work, current_diff); bvc.m_verifivation_failed = true; return false; } if(!prevalidate_miner_transaction(b, bei.height)) { - MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction."); + GULPSF_VERIFY_ERR_BLK("Block with id: {} (as alternative) has incorrect miner transaction.", epee::string_tools::pod_to_hex(id) ); bvc.m_verifivation_failed = true; return false; } @@ -1638,14 +1640,14 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id // add block to alternate blocks storage, // as well as the current "alt chain" container auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei)); - CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist"); + GULPS_CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist"); alt_chain.push_back(i_res.first); // FIXME: is it even possible for a checkpoint to show up not on the main chain? if(is_a_checkpoint) { //do reorganize! - MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_GREEN, "###### REORGANIZE on height: {} of {}, checkpoint is found in alternative chain on height {}", alt_chain.front()->second.height , m_db->height() - 1 , bei.height); bool r = switch_to_alternative_blockchain(alt_chain, true); @@ -1659,8 +1661,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain { //do reorganize! - MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl - << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_GREEN, "###### REORGANIZE on height: {} of {} with cum_difficulty {} \nalternative blockchain size: {} with cum_difficulty {}", alt_chain.front()->second.height , m_db->height() - 1 , m_db->get_block_cumulative_difficulty(m_db->height() - 1) , alt_chain.size() ,bei.cumulative_difficulty); bool r = switch_to_alternative_blockchain(alt_chain, false); if(r) @@ -1671,10 +1672,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id } else { - MGINFO_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl - << "id:\t" << id << std::endl - << "PoW:\t" << proof_of_work << std::endl - << "difficulty:\t" << current_diff); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_BLUE, "----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT {}\nid:\t{}\nPoW:\t{}\ndifficulty:\t{}", bei.height , id , proof_of_work , current_diff); return true; } } @@ -1682,9 +1680,10 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id { //block orphaned bvc.m_marked_as_orphaned = true; - MERROR_VER("Block recognized as orphaned and rejected, id = " << id << ", height " << block_height - << ", parent in alt " << (it_prev != m_alternative_chains.end()) << ", parent in main " << parent_in_main - << " (parent " << b.prev_id << ", current top " << get_tail_id() << ", chain height " << get_current_blockchain_height() << ")"); + GULPSF_VERIFY_ERR_BLK("Block recognized as orphaned and rejected, id = {}, height {}, parent in alt {}, parent in main {} (parent {}, current top {}, chain height {})", + id, block_height, + (it_prev != m_alternative_chains.end()), parent_in_main, + b.prev_id, get_tail_id(), get_current_blockchain_height()); } return true; @@ -1692,7 +1691,7 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id //------------------------------------------------------------------ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list> &blocks, std::list &txs) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); if(start_offset >= m_db->height()) return false; @@ -1706,7 +1705,7 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list missed_ids; get_transactions_blobs(blk.second.tx_hashes, txs, missed_ids); - CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain"); + GULPS_CHECK_AND_ASSERT_MES(!missed_ids.size(), false, "has missed transactions in own block in main blockchain"); } return true; @@ -1714,7 +1713,7 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::list> &blocks) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); if(start_offset >= m_db->height()) return false; @@ -1724,7 +1723,7 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::listget_block_blob_from_height(i), block())); if(!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) { - LOG_ERROR("Invalid block"); + GULPS_LOG_ERROR("Invalid block"); return false; } } @@ -1740,7 +1739,7 @@ bool Blockchain::get_blocks(uint64_t start_offset, size_t count, std::listblock_txn_start(true); rsp.current_blockchain_height = get_current_blockchain_height(); @@ -1758,9 +1757,7 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request &arg, NO if(missed_tx_ids.size() != 0) { - LOG_ERROR("Error retrieving blocks, missed " << missed_tx_ids.size() - << " transactions for block with hash: " << get_block_hash(bl.second) - << std::endl); + GULPSF_LOG_ERROR("Error retrieving blocks, missed {} transactions for block with hash: {}", missed_tx_ids.size() , get_block_hash(bl.second)); // append missed transaction hashes to response missed_ids field, // as done below if any standalone transactions were requested @@ -1791,7 +1788,7 @@ bool Blockchain::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request &arg, NO //------------------------------------------------------------------ bool Blockchain::get_alternative_blocks(std::list &blocks) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); for(const auto &alt_bl : m_alternative_chains) @@ -1803,7 +1800,7 @@ bool Blockchain::get_alternative_blocks(std::list &blocks) const //------------------------------------------------------------------ size_t Blockchain::get_alternative_blocks_count() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); return m_alternative_chains.size(); } @@ -1812,7 +1809,7 @@ size_t Blockchain::get_alternative_blocks_count() const // unlocked and other such checks should be done by here. void Blockchain::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount &result_outs, uint64_t amount, size_t i) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry &oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry()); @@ -1919,7 +1916,7 @@ crypto::public_key Blockchain::get_output_key(uint64_t amount, uint64_t global_i // in some cases bool Blockchain::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request &req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response &res) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // for each amount that we need to get mixins for, get random outputs @@ -1947,7 +1944,7 @@ bool Blockchain::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUT // unlocked and other such checks should be done by here. void Blockchain::add_out_to_get_rct_random_outs(std::list &outs, uint64_t amount, size_t i) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry &oen = *outs.insert(outs.end(), COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry()); @@ -1964,7 +1961,7 @@ void Blockchain::add_out_to_get_rct_random_outs(std::list random outputs @@ -2047,7 +2044,7 @@ bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::r // which will have a zero mask if (res.outs.size() < req.outs_count) { - LOG_PRINT_L0("Out of RCT inputs (" << res.outs.size() << "/" << req.outs_count << "), using regular ones"); + GULPSF_PRINT("Out of RCT inputs ({}/{}), using regular ones", res.outs.size(), req.outs_count); // TODO: arbitrary selection, needs better COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req2 = AUTO_VAL_INIT(req2); @@ -2078,7 +2075,7 @@ bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::r //------------------------------------------------------------------ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request &req, COMMAND_RPC_GET_OUTPUTS_BIN::response &res) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); res.outs.clear(); @@ -2121,14 +2118,14 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, // This is used to see what to send another node that needs to sync. bool Blockchain::find_blockchain_supplement(const std::list &qblock_ids, uint64_t &starter_offset) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // make sure the request includes at least the genesis block, otherwise // how can we expect to sync from the client that the block list came from? if(!qblock_ids.size() /*|| !req.m_total_height*/) { - MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection"); + GULPSF_CAT_ERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}, dropping connection", qblock_ids.size()/*", m_height=" << req.m_total_height <<*/); return false; } @@ -2138,10 +2135,8 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc auto gen_hash = m_db->get_block_hash_from_height(0); if(qblock_ids.back() != gen_hash) { - MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl - << "id: " << qblock_ids.back() << ", " << std::endl - << "expected: " << gen_hash << "," << std::endl - << " dropping connection"); + GULPSF_CAT_ERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: \nid: {}, \nexpected: {}, \n dropping connection", + qblock_ids.back(), gen_hash); m_db->block_txn_abort(); return false; } @@ -2159,7 +2154,7 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc } catch(const std::exception &e) { - MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it); + GULPSF_WARN("Non-critical error trying to find block by hash in BlockchainDB, hash: {}", *bl_it); m_db->block_txn_abort(); return false; } @@ -2170,7 +2165,7 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc // but just in case... if(bl_it == qblock_ids.end()) { - MERROR("Internal error handling connection, can't find split point"); + GULPS_ERROR("Internal error handling connection, can't find split point"); return false; } @@ -2181,7 +2176,7 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc //------------------------------------------------------------------ uint64_t Blockchain::block_difficulty(uint64_t i) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -2192,7 +2187,7 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const } catch(const BLOCK_DNE &e) { - MERROR("Attempted to get block difficulty for height above blockchain height"); + GULPS_ERROR("Attempted to get block difficulty for height above blockchain height"); } return 0; } @@ -2202,7 +2197,7 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const template bool Blockchain::get_blocks(const t_ids_container &block_ids, t_blocks_container &blocks, t_missed_container &missed_bs) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); for(const auto &block_hash : block_ids) @@ -2212,7 +2207,7 @@ bool Blockchain::get_blocks(const t_ids_container &block_ids, t_blocks_container blocks.push_back(std::make_pair(m_db->get_block_blob(block_hash), block())); if(!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) { - LOG_ERROR("Invalid block"); + GULPS_LOG_ERROR("Invalid block"); return false; } } @@ -2233,7 +2228,7 @@ bool Blockchain::get_blocks(const t_ids_container &block_ids, t_blocks_container template bool Blockchain::get_transactions_blobs(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); for(const auto &tx_hash : txs_ids) @@ -2257,7 +2252,7 @@ bool Blockchain::get_transactions_blobs(const t_ids_container &txs_ids, t_tx_con template bool Blockchain::get_transactions(const t_ids_container &txs_ids, t_tx_container &txs, t_missed_container &missed_txs) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); for(const auto &tx_hash : txs_ids) @@ -2270,7 +2265,7 @@ bool Blockchain::get_transactions(const t_ids_container &txs_ids, t_tx_container txs.push_back(transaction()); if(!parse_and_validate_tx_from_blob(tx, txs.back())) { - LOG_ERROR("Invalid transaction"); + GULPS_LOG_ERROR("Invalid transaction"); return false; } } @@ -2290,7 +2285,7 @@ bool Blockchain::get_transactions(const t_ids_container &txs_ids, t_tx_container // BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes. bool Blockchain::find_blockchain_supplement(const std::list &qblock_ids, std::list &hashes, uint64_t &start_height, uint64_t ¤t_height) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // if we can't find the split point, return false @@ -2313,7 +2308,7 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc bool Blockchain::find_blockchain_supplement(const std::list &qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request &resp) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); bool result = find_blockchain_supplement(qblock_ids, resp.m_block_ids, resp.start_height, resp.total_height); @@ -2329,7 +2324,7 @@ bool Blockchain::find_blockchain_supplement(const std::list &qbloc // blocks by reference. bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list &qblock_ids, std::list>> &blocks, uint64_t &total_height, uint64_t &start_height, size_t max_count) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); // if a specific start height has been requested @@ -2358,10 +2353,10 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons blocks.resize(blocks.size() + 1); blocks.back().first = m_db->get_block_blob_from_height(i); block b; - CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first, b), false, "internal error, invalid block"); + GULPS_CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first, b), false, "internal error, invalid block"); std::list mis; get_transactions_blobs(b.tx_hashes, blocks.back().second, mis); - CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found"); + GULPS_CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found"); size += blocks.back().first.size(); for(const auto &t : blocks.back().second) size += t.size(); @@ -2369,10 +2364,145 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons m_db->block_txn_stop(); return true; } + +bool Blockchain::find_blockchain_supplement_indexed(const uint64_t req_start_block, const std::list &qblock_ids, std::vector& blocks, + std::vector& out_idx, uint64_t &total_height, uint64_t &start_height, size_t max_count) const +{ + GULPS_LOG_L3("Blockchain::", __func__); + CRITICAL_REGION_LOCAL(m_blockchain_lock); + + // if a specific start height has been requested + if(req_start_block > 0) + { + // if requested height is higher than our chain, return false -- we can't help + if(req_start_block >= m_db->height()) + { + return false; + } + start_height = req_start_block; + } + else + { + if(!find_blockchain_supplement(qblock_ids, start_height)) + { + return false; + } + } + + m_db->block_txn_start(true); + total_height = get_current_blockchain_height(); + size_t end_height = std::min(total_height, start_height + max_count); + size_t count = 0, size = 0; + blocks.reserve(end_height - start_height); + out_idx.reserve(end_height - start_height); + + std::vector ent; + std::vector idx; + std::vector> b; + + struct tx_blob + { + cryptonote::blobdata blob; + size_t bi; + size_t txi; + }; + + std::vector tx; + size_t max_conc = tools::get_max_concurrency(); + ent.resize(max_conc); + idx.resize(max_conc); + b.resize(max_conc); + tx.resize(max_conc * 32); + + tools::threadpool &tpool = tools::threadpool::getInstance(); + tools::threadpool::waiter waiter; + + for(size_t i = start_height; i < end_height; count++) + { + if(size >= FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE && count >= 3) + break; + + size_t batch_size = std::min(max_conc, end_height - i); + + for(size_t bi = 0; bi < batch_size; bi++) + { + blocks.emplace_back(); + out_idx.emplace_back(); + ent[bi] = &blocks.back(); + idx[bi] = &out_idx.back(); + ent[bi]->block = m_db->get_block_blob_from_height(i+bi); + } + + for(size_t bi = 0; bi < batch_size; bi++) + tpool.submit(&waiter, [&, bi] { b[bi].second = parse_and_validate_block_from_blob(ent[bi]->block, b[bi].first); }); + waiter.wait(); + + size_t total_tx_cnt = 0; + size_t ttxi = 0; + for(size_t bi = 0; bi < batch_size; bi++) + { + GULPS_CHECK_AND_ASSERT_MES(b[bi].second, false, "internal error, invalid block"); + const block& bl = b[bi].first; + size_t tx_cnt = bl.tx_hashes.size(); + idx[bi]->indices.resize(tx_cnt+1); + + get_tx_outputs_gindexs(get_transaction_hash(bl.miner_tx), idx[bi]->indices[0].indices); + + total_tx_cnt += tx_cnt; + if(tx.size() < total_tx_cnt) + tx.resize(total_tx_cnt*2); + + ent[bi]->txs.resize(tx_cnt); + for(size_t txi=0; txi < tx_cnt; txi++, ttxi++) + { + GULPS_CHECK_AND_ASSERT_MES(m_db->get_tx_blob_indexed(bl.tx_hashes[txi], tx[ttxi].blob, idx[bi]->indices[txi+1].indices), + false, "internal error, transaction from block not found"); + tx[ttxi].bi = bi; + tx[ttxi].txi = txi; + } + } + + size_t txpt = total_tx_cnt / max_conc; + if(txpt > 0) + { + for(size_t thdi=0; thdi < max_conc; thdi++) + { + tpool.submit(&waiter, [&, thdi] { + for(size_t ttxi = thdi*txpt; ttxi < (thdi+1)*txpt; ttxi++) + { + size_t bi = tx[ttxi].bi; + size_t txi = tx[ttxi].txi; + ent[bi]->txs[txi] = cryptonote::get_pruned_tx_blob(tx[ttxi].blob); + } + }); + } + waiter.wait(); + } + + for(size_t ttxi = txpt*max_conc; ttxi < total_tx_cnt; ttxi++) + { + size_t bi = tx[ttxi].bi; + size_t txi = tx[ttxi].txi; + ent[bi]->txs[txi] = cryptonote::get_pruned_tx_blob(tx[ttxi].blob); + } + + for(size_t bi = 0; bi < batch_size; bi++) + { + size += ent[bi]->block.size(); + for(const auto &t : ent[bi]->txs) + size += t.size(); + } + + i += batch_size; + } + + m_db->block_txn_stop(); + return true; +} //------------------------------------------------------------------ bool Blockchain::add_block_as_invalid(const block &bl, const crypto::hash &h) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); block_extended_info bei = AUTO_VAL_INIT(bei); bei.bl = bl; return add_block_as_invalid(bei, h); @@ -2380,35 +2510,34 @@ bool Blockchain::add_block_as_invalid(const block &bl, const crypto::hash &h) //------------------------------------------------------------------ bool Blockchain::add_block_as_invalid(const block_extended_info &bei, const crypto::hash &h) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); auto i_res = m_invalid_blocks.insert(std::map::value_type(h, bei)); - CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed"); - MINFO("BLOCK ADDED AS INVALID: " << h << std::endl - << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size()); + GULPS_CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed"); + GULPSF_INFO("BLOCK ADDED AS INVALID: {}\n, prev_id={}, m_invalid_blocks count={}", h , bei.bl.prev_id , m_invalid_blocks.size()); return true; } //------------------------------------------------------------------ bool Blockchain::have_block(const crypto::hash &id) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); if(m_db->block_exists(id)) { - LOG_PRINT_L3("block exists in main chain"); + GULPS_LOG_L3("block exists in main chain"); return true; } if(m_alternative_chains.count(id)) { - LOG_PRINT_L3("block found in m_alternative_chains"); + GULPS_LOG_L3("block found in m_alternative_chains"); return true; } if(m_invalid_blocks.count(id)) { - LOG_PRINT_L3("block found in m_invalid_blocks"); + GULPS_LOG_L3("block found in m_invalid_blocks"); return true; } @@ -2417,14 +2546,14 @@ bool Blockchain::have_block(const crypto::hash &id) const //------------------------------------------------------------------ bool Blockchain::handle_block_to_main_chain(const block &bl, block_verification_context &bvc) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); crypto::hash id = get_block_hash(bl); return handle_block_to_main_chain(bl, id, bvc); } //------------------------------------------------------------------ size_t Blockchain::get_total_transactions() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // WARNING: this function does not take m_blockchain_lock, and thus should only call read only // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must @@ -2440,7 +2569,7 @@ size_t Blockchain::get_total_transactions() const // remove them later if the block fails validation. bool Blockchain::check_for_double_spend(const transaction &tx, key_images_container &keys_this_block) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); struct add_transaction_input_visitor : public boost::static_visitor { @@ -2489,7 +2618,7 @@ bool Blockchain::check_for_double_spend(const transaction &tx, key_images_contai { if(!boost::apply_visitor(add_transaction_input_visitor(keys_this_block, m_db), in)) { - LOG_ERROR("Double spend detected!"); + GULPS_LOG_ERROR("Double spend detected!"); return false; } } @@ -2499,12 +2628,12 @@ bool Blockchain::check_for_double_spend(const transaction &tx, key_images_contai //------------------------------------------------------------------ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vector &indexs) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); uint64_t tx_index; if(!m_db->tx_exists(tx_id, tx_index)) { - MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id); + GULPSF_VERIFY_ERR_TX("get_tx_outputs_gindexs failed to find transaction with id = {}", tx_id); return false; } @@ -2518,7 +2647,7 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vectoris_vout_bad(tx.vout[0])) indexs.insert(indexs.begin(), uint64_t(-1)); //This vout is unspendable so give it an invalid index else - CHECK_AND_ASSERT_MES(tx.vout.empty(), false, "internal error: global indexes for transaction " << tx_id << " is empty, and tx vout is not"); + GULPS_CHECK_AND_ASSERT_MES(tx.vout.empty(), false, "internal error: global indexes for transaction " , tx_id , " is empty, and tx vout is not"); } return true; @@ -2536,9 +2665,7 @@ void Blockchain::on_new_tx_from_block(const cryptonote::transaction &tx) if(m_show_time_stats) { size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get(tx.vin[0]).key_offsets.size() : 0; - MINFO("HASH: " - << "-" - << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a); + GULPSF_INFO("HASH: - I/M/O: {}/{}/{} H: {} chcktx: {}", tx.vin.size() , ring_size , tx.vout.size() , 0 ,a); } } #endif @@ -2554,7 +2681,7 @@ void Blockchain::on_new_tx_from_block(const cryptonote::transaction &tx) // as a return-by-reference. bool Blockchain::check_tx_inputs(transaction &tx, uint64_t &max_used_block_height, crypto::hash &max_used_block_id, tx_verification_context &tvc, bool kept_by_block) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); #if defined(PER_BLOCK_CHECKPOINT) @@ -2573,19 +2700,19 @@ bool Blockchain::check_tx_inputs(transaction &tx, uint64_t &max_used_block_heigh if(m_show_time_stats) { size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get(tx.vin[0]).key_offsets.size() : 0; - MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx)); + GULPSF_INFO("HASH: {} I/M/O: {}/{}/{} H: {} ms: {} B: {}", get_transaction_hash(tx), tx.vin.size(), ring_size, tx.vout.size(), max_used_block_height, a + m_fake_scan_time, get_object_blobsize(tx)); } if(!res) return false; - CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" << max_used_block_height << " is not less then blockchain size = " << m_db->height()); + GULPS_CHECK_AND_ASSERT_MES(max_used_block_height < m_db->height(), false, "internal error: max used block index=" , max_used_block_height , " is not less then blockchain size = " , m_db->height()); max_used_block_id = m_db->get_block_hash_from_height(max_used_block_height); return true; } //------------------------------------------------------------------ bool Blockchain::check_tx_outputs(const transaction &tx, tx_verification_context &tvc) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); for(auto &o : tx.vout) @@ -2613,21 +2740,21 @@ bool Blockchain::check_tx_outputs(const transaction &tx, tx_verification_context bool has_bulletproofs = tx.rct_signatures.type == rct::RCTTypeBulletproof; if((has_bulletproofs && tx.rct_signatures.p.bulletproofs.empty()) || (!has_bulletproofs && !tx.rct_signatures.p.bulletproofs.empty())) { - MERROR("Invalid signature semantics"); + GULPS_ERROR("Invalid signature semantics"); tvc.m_invalid_output = true; return false; } if(has_bulletproofs && !check_hard_fork_feature(FORK_BULLETPROOFS)) { - MERROR("Bulletproofs are not allowed yet"); + GULPS_ERROR("Bulletproofs are not allowed yet"); tvc.m_invalid_output = true; return false; } if(!has_bulletproofs && check_hard_fork_feature(FORK_BULLETPROOFS_REQ)) { - MERROR("Bulletproofs are required"); + GULPS_ERROR("Bulletproofs are required"); tvc.m_invalid_output = true; return false; } @@ -2637,7 +2764,7 @@ bool Blockchain::check_tx_outputs(const transaction &tx, tx_verification_context //------------------------------------------------------------------ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); for(const txin_v &in : tx.vin) { CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, in_to_key, true); @@ -2649,7 +2776,7 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector> &pubkeys) { PERF_TIMER(expand_transaction_2); - CHECK_AND_ASSERT_MES(tx.version == 2 || tx.version == 3, false, "Transaction version is not 2 or 3"); + GULPS_CHECK_AND_ASSERT_MES(tx.version == 2 || tx.version == 3, false, "Transaction version is not 2 or 3"); rct::rctSig &rv = tx.rct_signatures; @@ -2659,13 +2786,13 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr // mixRing - full and simple store it in opposite ways if(rv.type == rct::RCTTypeFull) { - CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); + GULPS_CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); rv.mixRing.resize(pubkeys[0].size()); for(size_t m = 0; m < pubkeys[0].size(); ++m) rv.mixRing[m].clear(); for(size_t n = 0; n < pubkeys.size(); ++n) { - CHECK_AND_ASSERT_MES(pubkeys[n].size() <= pubkeys[0].size(), false, "More inputs that first ring"); + GULPS_CHECK_AND_ASSERT_MES(pubkeys[n].size() <= pubkeys[0].size(), false, "More inputs that first ring"); for(size_t m = 0; m < pubkeys[n].size(); ++m) { rv.mixRing[m].push_back(pubkeys[n][m]); @@ -2674,7 +2801,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } else if(rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof) { - CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); + GULPS_CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys"); rv.mixRing.resize(pubkeys.size()); for(size_t n = 0; n < pubkeys.size(); ++n) { @@ -2687,7 +2814,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } else { - CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast(rv.type)); + GULPS_CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast(rv.type)); } // II @@ -2700,7 +2827,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } else if(rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof) { - CHECK_AND_ASSERT_MES(rv.p.MGs.size() == tx.vin.size(), false, "Bad MGs size"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.MGs.size() == tx.vin.size(), false, "Bad MGs size"); for(size_t n = 0; n < tx.vin.size(); ++n) { rv.p.MGs[n].II.resize(1); @@ -2709,7 +2836,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr } else { - CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast(rv.type)); + GULPS_CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast(rv.type)); } // outPk was already done by handle_incoming_tx @@ -2725,7 +2852,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, uint64_t *pmax_used_block_height) { PERF_TIMER(check_tx_inputs); - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); size_t sig_index = 0; if(pmax_used_block_height) *pmax_used_block_height = 0; @@ -2750,7 +2877,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, if(vin_mixin > cryptonote::common_config::MAX_MIXIN) { - MERROR_VER("Tx " << get_transaction_hash(tx) << " has too high ring size (" << vin_mixin << "), max = " << cryptonote::common_config::MAX_MIXIN + 1); + GULPS_VERIFY_ERR_TX("Tx ", get_transaction_hash(tx), " has too high ring size (", vin_mixin, "), max = ", cryptonote::common_config::MAX_MIXIN + 1); tvc.m_verifivation_failed = true; return false; } @@ -2759,7 +2886,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, size_t min_mixin = check_hard_fork_feature(FORK_RINGSIZE_INC_REQ) ? cryptonote::common_config::MIN_MIXIN_V2 : cryptonote::common_config::MIN_MIXIN_V1; if(lowest_mixin < min_mixin) { - MERROR_VER("Tx " << get_transaction_hash(tx) << " has too low ring size (" << (lowest_mixin + 1) << ")"); + GULPSF_VERIFY_ERR_TX("Tx {} has too low ring size ({})", get_transaction_hash(tx) , (lowest_mixin + 1) ); tvc.m_low_mixin = true; return false; } @@ -2767,7 +2894,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, bool strict_tx_semantics = check_hard_fork_feature(FORK_STRICT_TX_SEMANTICS); if(strict_tx_semantics && highest_mixin != lowest_mixin) { - MERROR_VER("Tx " << get_transaction_hash(tx) << " has different input ring sizes min = " << lowest_mixin << ", max = " << highest_mixin); + GULPSF_VERIFY_ERR_TX("Tx {} has different input ring sizes min = {}, max = {}", get_transaction_hash(tx) , lowest_mixin , highest_mixin); tvc.m_verifivation_failed = true; return false; } @@ -2788,7 +2915,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(has_pubkey) { - MERROR_VER("Tx has a duplicate pub key."); + GULPS_VERIFY_ERR_TX("Tx has a duplicate pub key."); tvc.m_verifivation_failed = true; return false; } @@ -2798,16 +2925,16 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(has_extrapubkeys) { - MERROR_VER("Tx has a duplicate exta pub keys field."); + GULPS_VERIFY_ERR_TX("Tx has a duplicate exta pub keys field."); tvc.m_verifivation_failed = true; return false; } has_extrapubkeys = true; - + tx_extra_additional_pub_keys extrapubkeys = boost::get(f); if(extrapubkeys.data.size() != tx.vout.size()) { - MERROR_VER("Extra pubkeys size mismatch! Extra pubkey count must equal output count."); + GULPS_VERIFY_ERR_TX("Extra pubkeys size mismatch! Extra pubkey count must equal output count."); tvc.m_verifivation_failed = true; return false; } @@ -2816,7 +2943,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(has_uniform_pid) { - MERROR_VER("Tx has a duplicate uniform pid field."); + GULPS_VERIFY_ERR_TX("Tx has a duplicate uniform pid field."); tvc.m_verifivation_failed = true; return false; } @@ -2826,14 +2953,14 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, if(uids_required && !has_uniform_pid) { - MERROR_VER("Transaction has no uniform pid field."); + GULPS_VERIFY_ERR_TX("Transaction has no uniform pid field."); tvc.m_verifivation_failed = true; return false; } if(!has_pubkey) { - MERROR_VER("Transaction has no pub key."); + GULPS_VERIFY_ERR_TX("Transaction has no pub key."); tvc.m_verifivation_failed = true; return false; } @@ -2847,7 +2974,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, const txin_to_key& in_to_key = boost::get(txin); if(last_key_image != nullptr && memcmp(&in_to_key.k_image, last_key_image, sizeof(*last_key_image)) >= 0) { - MERROR_VER("transaction has unsorted inputs"); + GULPS_VERIFY_ERR_TX("transaction has unsorted inputs"); tvc.m_verifivation_failed = true; return false; } @@ -2860,7 +2987,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, const size_t max_tx_version = MAX_TRANSACTION_VERSION; if(tx.version > max_tx_version) { - MERROR_VER("transaction version " << (unsigned)tx.version << " is higher than max accepted version " << max_tx_version); + GULPSF_VERIFY_ERR_TX("transaction version {} is higher than max accepted version {}", (unsigned)tx.version , max_tx_version); tvc.m_verifivation_failed = true; return false; } @@ -2868,7 +2995,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, const size_t min_tx_version = check_hard_fork_feature(FORK_NEED_V3_TXES) ? 3 : MIN_TRANSACTION_VERSION; if(tx.version < min_tx_version) { - MERROR_VER("transaction version " << (unsigned)tx.version << " is lower than min accepted version " << min_tx_version); + GULPSF_VERIFY_ERR_TX("transaction version {} is lower than min accepted version {}", (unsigned)tx.version , min_tx_version); tvc.m_verifivation_failed = true; return false; } @@ -2889,15 +3016,15 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { // make sure output being spent is of type txin_to_key, rather than // e.g. txin_gen, which is only used for miner transactions - CHECK_AND_ASSERT_MES(txin.type() == typeid(txin_to_key), false, "wrong type id in tx input at Blockchain::check_tx_inputs"); + GULPS_CHECK_AND_ASSERT_MES(txin.type() == typeid(txin_to_key), false, "wrong type id in tx input at Blockchain::check_tx_inputs"); const txin_to_key &in_to_key = boost::get(txin); // make sure tx output has key offset(s) (is signed to be used) - CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "empty in_to_key.key_offsets in transaction with id " << get_transaction_hash(tx)); + GULPS_CHECK_AND_ASSERT_MES(in_to_key.key_offsets.size(), false, "empty in_to_key.key_offsets in transaction with id " , get_transaction_hash(tx)); if(have_tx_keyimg_as_spent(in_to_key.k_image)) { - MERROR_VER("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image)); + GULPS_VERIFY_ERR_TX("Key image already spent in blockchain: ", epee::string_tools::pod_to_hex(in_to_key.k_image)); tvc.m_double_spend = true; return false; } @@ -2907,10 +3034,10 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, if(!check_tx_input(tx.version, in_to_key, tx_prefix_hash, std::vector(), tx.rct_signatures, pubkeys[sig_index], pmax_used_block_height)) { it->second[in_to_key.k_image] = false; - MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index); + GULPS_VERIFY_ERR_TX("Failed to check ring signature for tx ", get_transaction_hash(tx), " vin key with k_image: ", in_to_key.k_image, " sig_index: ", sig_index); if(pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain() { - MERROR_VER(" *pmax_used_block_height: " << *pmax_used_block_height); + GULPSF_VERIFY_ERR_TX(" *pmax_used_block_height: {}", *pmax_used_block_height); } return false; @@ -2920,7 +3047,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, } if(!expand_transaction_2(tx, tx_prefix_hash, pubkeys)) { - MERROR_VER("Failed to expand rct signatures!"); + GULPS_VERIFY_ERR_TX("Failed to expand rct signatures!"); return false; } @@ -2933,7 +3060,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, case rct::RCTTypeNull: { // we only accept no signatures for coinbase txes - MERROR_VER("Null rct signature on non-coinbase tx"); + GULPS_VERIFY_ERR_TX("Null rct signature on non-coinbase tx"); return false; } case rct::RCTTypeSimple: @@ -2943,14 +3070,14 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(pubkeys.size() != rv.mixRing.size()) { - MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); return false; } for(size_t i = 0; i < pubkeys.size(); ++i) { if(pubkeys[i].size() != rv.mixRing[i].size()) { - MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); return false; } } @@ -2961,12 +3088,12 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[n][m].dest)) { - MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m); + GULPSF_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched pubkey at vin {}, index {}", n , m); return false; } if(pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[n][m].mask)) { - MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m); + GULPSF_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched commitment at vin {}, index {}", n , m); return false; } } @@ -2975,21 +3102,21 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, if(rv.p.MGs.size() != tx.vin.size()) { - MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched MGs/vin sizes"); return false; } for(size_t n = 0; n < tx.vin.size(); ++n) { if(rv.p.MGs[n].II.empty() || memcmp(&boost::get(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32)) { - MERROR_VER("Failed to check ringct signatures: mismatched key image"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched key image"); return false; } } if(!rct::verRctNonSemanticsSimple(rv)) { - MERROR_VER("Failed to check ringct signatures!"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures!"); return false; } break; @@ -3005,7 +3132,7 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, size_matches &= pubkeys.size() == rv.mixRing[i].size(); if(!size_matches) { - MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched pubkeys/mixRing size"); return false; } @@ -3015,12 +3142,12 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, { if(pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[m][n].dest)) { - MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m); + GULPSF_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched pubkey at vin {}, index {}", n , m); return false; } if(pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[m][n].mask)) { - MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m); + GULPSF_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched commitment at vin {}, index {}", n , m); return false; } } @@ -3029,32 +3156,32 @@ bool Blockchain::check_tx_inputs(transaction &tx, tx_verification_context &tvc, if(rv.p.MGs.size() != 1) { - MERROR_VER("Failed to check ringct signatures: Bad MGs size"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: Bad MGs size"); return false; } if(rv.p.MGs.empty() || rv.p.MGs[0].II.size() != tx.vin.size()) { - MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched II/vin sizes"); return false; } for(size_t n = 0; n < tx.vin.size(); ++n) { if(memcmp(&boost::get(tx.vin[n]).k_image, &rv.p.MGs[0].II[n], 32)) { - MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures: mismatched II/vin sizes"); return false; } } if(!rct::verRct(rv, false)) { - MERROR_VER("Failed to check ringct signatures!"); + GULPS_VERIFY_ERR_TX("Failed to check ringct signatures!"); return false; } break; } default: - MERROR_VER("Unsupported rct type: " << rv.type); + GULPSF_VERIFY_ERR_TX("Unsupported rct type: {}", rv.type); return false; } @@ -3128,7 +3255,7 @@ bool Blockchain::check_fee(const transaction &tx, size_t blob_size, uint64_t fee return false; fee_per_kb = get_dynamic_per_kb_fee(base_reward, median); - LOG_PRINT_L2("Using " << print_money(fee) << "/kB fee"); + GULPSF_LOG_L2("Using {}/kB fee", print_money(fee_per_kb) ); //WHO THOUGHT THAT FLOATS IN CONSENSUS CODE ARE A GOOD IDEA????? float kB = (blob_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE) * 1.0f / 1024; @@ -3136,14 +3263,14 @@ bool Blockchain::check_fee(const transaction &tx, size_t blob_size, uint64_t fee if(fee < needed_fee) { - MERROR_VER("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee)); + GULPSF_VERIFY_ERR_TX("transaction fee is not enough: {}, minimum fee: {}", print_money(fee), print_money(needed_fee)); return false; } } if(fee < needed_fee) { - MERROR_VER("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee)); + GULPSF_VERIFY_ERR_TX("transaction fee is not enough: {}, minimum fee: {}", print_money(fee), print_money(needed_fee)); return false; } return true; @@ -3154,7 +3281,7 @@ bool Blockchain::check_fee(const transaction &tx, size_t blob_size, uint64_t fee // a block index or a unix time. bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // ND: Instead of calling get_current_blockchain_height(), call m_db->height() // directly as get_current_blockchain_height() locks the recursive mutex. return m_db->height() - 1 + CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS >= unlock_time; @@ -3165,7 +3292,7 @@ bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const // signature for each input. bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key &txin, const crypto::hash &tx_prefix_hash, const std::vector &sig, const rct::rctSig &rct_signatures, std::vector &output_keys, uint64_t *pmax_related_block_height) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); // ND: // 1. Disable locking and make method private. @@ -3183,7 +3310,7 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key &txin, cons //check tx unlock time if(!m_bch.is_tx_spendtime_unlocked(unlock_time)) { - MERROR_VER("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time); + GULPSF_VERIFY_ERR_TX("One of outputs for one of inputs has wrong tx.unlock_time = {}", unlock_time); return false; } @@ -3203,18 +3330,18 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key &txin, cons outputs_visitor vi(output_keys, *this); if(!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height)) { - MERROR_VER("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size()); + GULPSF_VERIFY_ERR_TX("Failed to get output keys for tx with amount = {} and count indexes {}", print_money(txin.amount), txin.key_offsets.size()); return false; } if(txin.key_offsets.size() != output_keys.size()) { - MERROR_VER("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size()); + GULPSF_VERIFY_ERR_TX("Output keys for tx with amount = {} and count indexes {} returned wrong keys count {}", print_money(txin.amount), txin.key_offsets.size() , output_keys.size()); return false; } if(tx_version == 1) { - CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(), false, "internal error: tx signatures count=" << sig.size() << " mismatch with outputs keys count for inputs=" << output_keys.size()); + GULPS_CHECK_AND_ASSERT_MES(sig.size() == output_keys.size(), false, "internal error: tx signatures count=" , sig.size() , " mismatch with outputs keys count for inputs=" , output_keys.size()); } // rct_signatures will be expanded after this return true; @@ -3223,7 +3350,7 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key &txin, cons //TODO: Is this intended to do something else? Need to look into the todo there. uint64_t Blockchain::get_adjusted_time() const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); //TODO: add collecting median time return time(NULL); } @@ -3231,12 +3358,12 @@ uint64_t Blockchain::get_adjusted_time() const //TODO: revisit, has changed a bit on upstream bool Blockchain::check_block_timestamp(std::vector ×tamps, const block &b, uint64_t &median_ts) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); median_ts = epee::misc_utils::median(timestamps); if(b.timestamp < median_ts) { - MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << timestamps.size() << " blocks, " << median_ts); + GULPSF_VERIFY_ERR_BLK("Timestamp of block with id: {}, {}, less than median of last {} blocks, {}", get_block_hash(b) , b.timestamp , timestamps.size(), median_ts); return false; } @@ -3252,7 +3379,7 @@ bool Blockchain::check_block_timestamp(std::vector ×tamps, const // false otherwise bool Blockchain::check_block_timestamp(const block &b, uint64_t &median_ts) const { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); uint64_t block_future_time_limit = check_hard_fork_feature(FORK_V3_DIFFICULTY) ? common_config::BLOCK_FUTURE_TIME_LIMIT_V3 : common_config::BLOCK_FUTURE_TIME_LIMIT_V2; @@ -3266,7 +3393,7 @@ bool Blockchain::check_block_timestamp(const block &b, uint64_t &median_ts) cons if(b.timestamp > get_adjusted_time() + block_future_time_limit) { - MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours"); + GULPSF_VERIFY_ERR_BLK("Timestamp of block with id: {}, {}, bigger than adjusted time + 2 hours", get_block_hash(b) , b.timestamp ); median_ts = get_adjusted_time() + block_future_time_limit; return false; } @@ -3302,7 +3429,7 @@ void Blockchain::return_tx_to_pool(std::vector &txs) // all the transactions in a popped block when a reorg happens. if(!m_tx_pool.add_tx(tx, tvc, true, true, false)) { - MERROR("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool"); + GULPSF_ERROR("Failed to return taken transaction with hash: {} to tx_pool", get_transaction_hash(tx) ); } } } @@ -3318,10 +3445,10 @@ bool Blockchain::flush_txes_from_pool(const std::list &txids) size_t blob_size; uint64_t fee; bool relayed, do_not_relay, double_spend_seen; - MINFO("Removing txid " << txid << " from the pool"); + GULPSF_INFO("Removing txid {} from the pool", txid ); if(m_tx_pool.have_tx(txid) && !m_tx_pool.take_tx(txid, tx, blob_size, fee, relayed, do_not_relay, double_spend_seen)) { - MERROR("Failed to remove txid " << txid << " from the pool"); + GULPSF_ERROR("Failed to remove txid {} from the pool", txid ); res = false; } } @@ -3333,7 +3460,7 @@ bool Blockchain::flush_txes_from_pool(const std::list &txids) // m_db->add_block() bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash &id, block_verification_context &bvc) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); TIME_MEASURE_START(block_processing_time); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -3344,9 +3471,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash m_db->block_txn_start(true); if(bl.prev_id != get_tail_id()) { - MERROR_VER("Block with id: " << id << std::endl - << "has wrong prev_id: " << bl.prev_id << std::endl - << "expected: " << get_tail_id()); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\nhas wrong prev_id: {}\nexpected: {}", id, bl.prev_id, get_tail_id()); leave: m_db->block_txn_stop(); return false; @@ -3356,20 +3481,17 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash if(!seen_future_version && bl.major_version > m_hardfork->get_ideal_version()) { seen_future_version = true; - const el::Level level = el::Level::Warning; - MCLOG_RED(level, "global", "**********************************************************************"); - MCLOG_RED(level, "global", "A block was seen on the network with a version higher than the last"); - MCLOG_RED(level, "global", "known one. This may be an old version of the daemon, and a software"); - MCLOG_RED(level, "global", "update may be required to sync further. Try running: update check"); - MCLOG_RED(level, "global", "**********************************************************************"); + GULPS_CAT_LOG_WARN("global", "**********************************************************************"); + GULPS_CAT_LOG_WARN("global", "A block was seen on the network with a version higher than the last"); + GULPS_CAT_LOG_WARN("global", "known one. This may be an old version of the daemon, and a software"); + GULPS_CAT_LOG_WARN("global", "update may be required to sync further. Try running: update check"); + GULPS_CAT_LOG_WARN("global", "**********************************************************************"); } // this is a cheap test if(!m_hardfork->check(bl)) { - MERROR_VER("Block with id: " << id << std::endl - << "has old version: " << (unsigned)bl.major_version << std::endl - << "current: " << (unsigned)m_hardfork->get_current_version_num()); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\nhas old version: {}\ncurrent: {}", id, (unsigned)bl.major_version, (unsigned)m_hardfork->get_current_version_num()); bvc.m_verifivation_failed = true; goto leave; } @@ -3381,8 +3503,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // of a set number of the most recent blocks. if(!check_block_timestamp(bl)) { - MERROR_VER("Block with id: " << id << std::endl - << "has invalid timestamp: " << bl.timestamp); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\nhas invalid timestamp: {}", id, bl.timestamp); bvc.m_verifivation_failed = true; goto leave; } @@ -3397,7 +3518,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // FIXME: get_difficulty_for_next_block can also assert, look into // changing this to throwing exceptions instead so we can clean up. difficulty_type current_diffic = get_difficulty_for_next_block(); - CHECK_AND_ASSERT_MES(current_diffic, false, "!!!!!!!!! difficulty overhead !!!!!!!!!"); + GULPS_CHECK_AND_ASSERT_MES(current_diffic, false, "!!!!!!!!! difficulty overhead !!!!!!!!!"); TIME_MEASURE_FINISH(target_calculating_time); @@ -3425,7 +3546,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash { if(memcmp(&hash, &expected_hash, sizeof(hash)) != 0) { - MERROR_VER("Block with id is INVALID: " << id); + GULPSF_VERIFY_ERR_BLK("Block with id is INVALID: {}", id); bvc.m_verifivation_failed = true; goto leave; } @@ -3433,7 +3554,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash } else { - MCINFO("verify", "No pre-validated hash at height " << m_db->height() << ", verifying fully"); + GULPSF_CAT_PRINT("verify", "No pre-validated hash at height {}, verifying fully", m_db->height()); } } else @@ -3453,9 +3574,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // validate proof_of_work versus difficulty target if(!check_hash(proof_of_work, current_diffic)) { - MERROR_VER("Block with id: " << id << std::endl - << "does not have enough proof of work: " << proof_of_work << std::endl - << "unexpected difficulty: " << current_diffic); + GULPSF_VERIFY_ERR_BLK("Block with id: {}\ndoes not have enough proof of work: {}\nunexpected difficulty: {}", id, proof_of_work, current_diffic); bvc.m_verifivation_failed = true; goto leave; } @@ -3467,7 +3586,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash { if(!m_checkpoints.check_block(get_current_blockchain_height(), id)) { - LOG_ERROR("CHECKPOINT VALIDATION FAILED"); + GULPS_LOG_ERROR("CHECKPOINT VALIDATION FAILED"); bvc.m_verifivation_failed = true; goto leave; } @@ -3482,7 +3601,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // sanity check basic miner tx properties; if(!prevalidate_miner_transaction(bl, m_db->height())) { - MERROR_VER("Block with id: " << id << " failed to pass prevalidation"); + GULPSF_VERIFY_ERR_BLK("Block with id: {} failed to pass prevalidation", id ); bvc.m_verifivation_failed = true; goto leave; } @@ -3517,7 +3636,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // XXX old code does not check whether tx exists if(m_db->tx_exists(tx_id)) { - MERROR("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id); + GULPSF_ERROR("Block with id: {} attempting to add transaction already in blockchain with id: {}", id , tx_id); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3530,7 +3649,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // get transaction with hash from tx_pool if(!m_tx_pool.take_tx(tx_id, tx, blob_size, fee, relayed, do_not_relay, double_spend_seen)) { - MERROR_VER("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id); + GULPSF_VERIFY_ERR_BLK("Block with id: {} has at least one unknown transaction with id: {}", id , tx_id); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3552,7 +3671,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // ND: this is not needed, db->add_block() checks for duplicate k_images and fails accordingly. // if (!check_for_double_spend(tx, keys)) // { - // LOG_PRINT_L0("Double spend detected in transaction (id: " << tx_id); + // GULPSF_VERIFY_ERR_BLK("Double spend detected in transaction (id: " , tx_id); // bvc.m_verifivation_failed = true; // break; // } @@ -3569,11 +3688,11 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash tx_verification_context tvc; if(!check_tx_inputs(tx, tvc)) { - MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); + GULPSF_VERIFY_ERR_BLK("Block with id: {} has at least one transaction (id: {}) with wrong inputs.", id , tx_id ); //TODO: why is this done? make sure that keeping invalid blocks makes sense. add_block_as_invalid(bl, id); - MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions"); + GULPSF_VERIFY_ERR_BLK("Block with id {} added as invalid because of wrong inputs in transactions", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3586,10 +3705,10 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // the transaction inputs, but do some sanity checks anyway. if(tx_index >= m_blocks_txs_check.size() || memcmp(&m_blocks_txs_check[tx_index++], &tx_id, sizeof(tx_id)) != 0) { - MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs."); + GULPSF_VERIFY_ERR_BLK("Block with id: {} has at least one transaction (id: {}) with wrong inputs.", id , tx_id ); //TODO: why is this done? make sure that keeping invalid blocks makes sense. add_block_as_invalid(bl, id); - MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions"); + GULPSF_VERIFY_ERR_BLK("Block with id {} added as invalid because of wrong inputs in transactions", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3611,7 +3730,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash { if(!validate_miner_transaction_v2(bl, m_db->height(), cumulative_block_size, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward)) { - MERROR_VER("Block with id: " << id << " has incorrect miner transaction"); + GULPSF_VERIFY_ERR_BLK("Block with id: {} has incorrect miner transaction", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3621,7 +3740,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash { if(!validate_miner_transaction_v1(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward)) { - MERROR_VER("Block with id: " << id << " has incorrect miner transaction"); + GULPSF_VERIFY_ERR_BLK("Block with id: {} has incorrect miner transaction", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3658,7 +3777,7 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash } catch(const KEY_IMAGE_EXISTS &e) { - LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what()); + GULPSF_LOG_ERROR("Error adding block with hash: {} to blockchain, what = {}", id , e.what()); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); return false; @@ -3666,14 +3785,14 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash catch(const std::exception &e) { //TODO: figure out the best way to deal with this failure - LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what()); + GULPSF_LOG_ERROR("Error adding block with hash: {} to blockchain, what = {}", id , e.what()); return_tx_to_pool(txs); return false; } } else { - LOG_ERROR("Blocks that failed verification should not reach here"); + GULPS_LOG_ERROR("Blocks that failed verification should not reach here"); } TIME_MEASURE_FINISH(addblock); @@ -3681,18 +3800,17 @@ bool Blockchain::handle_block_to_main_chain(const block &bl, const crypto::hash // do this after updating the hard fork state since the size limit may change due to fork update_next_cumulative_size_limit(); - MINFO("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl - << "id:\t" << id << std::endl - << "PoW:\t" << proof_of_work << std::endl - << "HEIGHT " << new_height - 1 << ", difficulty:\t" << current_diffic << std::endl - << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms"); + GULPSF_INFO("+++++ BLOCK SUCCESSFULLY ADDED\nid:\t{}\nPoW:\t{}\nHEIGHT {}, difficulty:\t{}\nblock reward: {}({}+{}), coinbase_blob_size: {} , cumulative size: {}, {}({}/{})ms", + id, proof_of_work, new_height - 1, current_diffic, + print_money(fee_summary + base_reward), print_money(base_reward), print_money(fee_summary), + coinbase_blob_size, cumulative_block_size, block_processing_time, target_calculating_time, longhash_calculating_time); if(m_show_time_stats) { - MINFO("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: " - << cumulative_block_size << " p/t: " << block_processing_time << " (" - << target_calculating_time << "/" << longhash_calculating_time << "/" - << t1 << "/" << t2 << "/" << t3 << "/" << t_exists << "/" << t_pool - << "/" << t_checktx << "/" << t_dblspnd << "/" << vmt << "/" << addblock << ")ms"); + GULPSF_INFO("Height: {} blob: {} cumm: {} p/t: {} ({}/{}/{}/{}/{}/{}/{}/{}/{}/{}/{})ms", + new_height, coinbase_blob_size, cumulative_block_size, block_processing_time, + target_calculating_time , longhash_calculating_time, + t1, t2, t3, t_exists, t_pool, + t_checktx, t_dblspnd, vmt, addblock); } bvc.m_added_to_main_chain = true; @@ -3708,7 +3826,7 @@ bool Blockchain::update_next_cumulative_size_limit() { uint64_t full_reward_zone = get_min_block_size(); - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); std::vector sz; get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW); @@ -3723,7 +3841,7 @@ bool Blockchain::update_next_cumulative_size_limit() //------------------------------------------------------------------ bool Blockchain::add_new_block(const block &bl_, block_verification_context &bvc) { - LOG_PRINT_L3("Blockchain::" << __func__); + GULPS_LOG_L3("Blockchain::", __func__); //copy block here to let modify block.target block bl = bl_; crypto::hash id = get_block_hash(bl); @@ -3732,7 +3850,7 @@ bool Blockchain::add_new_block(const block &bl_, block_verification_context &bvc m_db->block_txn_start(true); if(have_block(id)) { - LOG_PRINT_L3("block with id = " << id << " already exists"); + GULPSF_LOG_L3("block with id = {} already exists", id ); bvc.m_already_exists = true; m_db->block_txn_stop(); m_blocks_txs_check.clear(); @@ -3777,13 +3895,13 @@ void Blockchain::check_against_checkpoints(const checkpoints &points, bool enfor // if asked to enforce checkpoints, roll back to a couple of blocks before the checkpoint if(enforce) { - LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!"); + GULPS_LOG_ERROR("Local blockchain failed to pass a checkpoint, rolling back!"); std::list empty; rollback_blockchain_switching(empty, pt.first - 2); } else { - LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option"); + GULPS_LOG_ERROR("WARNING: local blockchain failed to pass a MoneroPulse checkpoint, and you could be on a fork. You should either sync up from scratch, OR download a fresh blockchain bootstrap, OR enable checkpoint enforcing with the --enforce-dns-checkpointing command-line option"); } } } @@ -3820,7 +3938,7 @@ bool Blockchain::update_checkpoints(const std::string &file_path, bool check_dns } else { - MERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!"); + GULPS_ERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!"); } } @@ -3857,7 +3975,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) { bool success = false; - MTRACE("Blockchain::" << __func__); + GULPS_LOG_L2("Blockchain::", __func__); CRITICAL_REGION_BEGIN(m_blockchain_lock); TIME_MEASURE_START(t1); @@ -3868,7 +3986,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) } catch(const std::exception &e) { - MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what()); + GULPSF_ERROR("Exception in cleanup_handle_incoming_blocks: {}", e.what()); } if(success && m_sync_counter > 0) @@ -3906,7 +4024,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) // when we're well clear of the precomputed hashes, free the memory if(!m_blocks_hash_check.empty() && m_db->height() > m_blocks_hash_check.size() + 4096) { - MINFO("Dumping block hashes, we're now 4k past " << m_blocks_hash_check.size()); + GULPSF_INFO("Dumping block hashes, we're now 4k past {}", m_blocks_hash_check.size()); m_blocks_hash_check.clear(); m_blocks_hash_check.shrink_to_fit(); } @@ -3927,7 +4045,7 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector::max() / 2, 0, "usable is negative"); + GULPSF_LOG_L1("usable: {} / {}", usable , hashes.size()); + GULPS_CHECK_AND_ASSERT_MES(usable < std::numeric_limits::max() / 2, 0, "usable is negative"); return usable; } @@ -4039,7 +4157,7 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::list &blocks_entry) { - MTRACE("Blockchain::" << __func__); + GULPS_LOG_L2("Blockchain::", __func__); TIME_MEASURE_START(prepare); bool stop_batch; uint64_t bytes = 0; @@ -4097,7 +4215,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::listheight(); int batches = blocks_entry.size() / threads; int extra = blocks_entry.size() % threads; - MDEBUG("block_batches: " << batches); + GULPSF_LOG_L1("block_batches: {}", batches); std::vector> maps(threads); std::vector> blocks(threads); auto it = blocks_entry.begin(); @@ -4120,7 +4238,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::listtop_block_hash(); if(block.prev_id != tophash) { - MDEBUG("Skipping prepare blocks. New blocks don't belong to chain."); + GULPS_LOG_L1("Skipping prepare blocks. New blocks don't belong to chain."); return true; } } @@ -4184,7 +4302,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list 1 && threads > 1 && m_show_time_stats) - MDEBUG("Prepare blocks took: " << prepare << " ms"); + GULPSF_LOG_L1("Prepare blocks took: {} ms", prepare ); TIME_MEASURE_START(scantable); @@ -4212,7 +4330,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list 0) { - MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); + GULPSF_INFO("Loading precomputed blocks ({} bytes)", get_blocks_dat_size(testnet, stagenet) ); if(m_nettype == MAINNET) { @@ -4519,20 +4637,20 @@ void Blockchain::load_compiled_in_block_hashes() crypto::hash hash; if(!tools::sha256sum(get_blocks_dat_start(testnet, stagenet), get_blocks_dat_size(testnet, stagenet), hash)) { - MERROR("Failed to hash precomputed blocks data"); + GULPS_ERROR("Failed to hash precomputed blocks data"); return; } - MINFO("precomputed blocks hash: " << hash << ", expected " << expected_block_hashes_hash); + GULPSF_INFO("precomputed blocks hash: {}, expected {}", hash , expected_block_hashes_hash); cryptonote::blobdata expected_hash_data; if(!epee::string_tools::parse_hexstr_to_binbuff(std::string(expected_block_hashes_hash), expected_hash_data) || expected_hash_data.size() != sizeof(crypto::hash)) { - MERROR("Failed to parse expected block hashes hash"); + GULPS_ERROR("Failed to parse expected block hashes hash"); return; } const crypto::hash expected_hash = *reinterpret_cast(expected_hash_data.data()); if(hash != expected_hash) { - MERROR("Block hash data does not match expected hash"); + GULPS_ERROR("Block hash data does not match expected hash"); return; } } @@ -4543,7 +4661,7 @@ void Blockchain::load_compiled_in_block_hashes() const uint32_t nblocks = *p | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) | ((*(p + 3)) << 24); if(nblocks > (std::numeric_limits::max() - 4) / sizeof(hash)) { - MERROR("Block hash data is too large"); + GULPS_ERROR("Block hash data is too large"); return; } const size_t size_needed = 4 + nblocks * sizeof(crypto::hash); @@ -4559,7 +4677,7 @@ void Blockchain::load_compiled_in_block_hashes() m_blocks_hash_of_hashes.push_back(hash); } m_blocks_hash_check.resize(m_blocks_hash_of_hashes.size() * HASH_OF_HASHES_STEP, crypto::null_hash); - MINFO(nblocks << " block hashes loaded"); + GULPSF_INFO("{} block hashes loaded", nblocks); // FIXME: clear tx_pool because the process might have been // terminated and caused it to store txs kept by blocks. diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index e2a16667..35a7fe87 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -411,6 +411,9 @@ class Blockchain */ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list &qblock_ids, std::list>> &blocks, uint64_t &total_height, uint64_t &start_height, size_t max_count) const; + bool find_blockchain_supplement_indexed(const uint64_t req_start_block, const std::list &qblock_ids, std::vector& blocks, + std::vector& out_idx, uint64_t &total_height, uint64_t &start_height, size_t max_count) const; + /** * @brief retrieves a set of blocks and their transactions, and possibly other transactions * diff --git a/src/cryptonote_core/blockchain_storage_boost_serialization.h b/src/cryptonote_core/blockchain_storage_boost_serialization.h index 1a9959f5..74e912af 100644 --- a/src/cryptonote_core/blockchain_storage_boost_serialization.h +++ b/src/cryptonote_core/blockchain_storage_boost_serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index f19189d6..3f0306ec 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -45,12 +45,12 @@ using namespace epee; #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn" +#include "common/gulps.hpp" -DISABLE_VS_WARNINGS(4355) -#define MERROR_VER(x) MCERROR("verify", x) +GULPS_CAT_MAJOR("crtnte_core"); + +DISABLE_VS_WARNINGS(4355) #define BAD_SEMANTICS_TXES_MAX_SIZE 100 @@ -243,7 +243,7 @@ bool core::handle_command_line(const boost::program_options::variables_map &vm) m_offline = get_arg(vm, arg_offline); m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints); if(!command_line::is_arg_defaulted(vm, arg_fluffy_blocks)) - MWARNING(arg_fluffy_blocks.name << " is obsolete, it is now default"); + GULPSF_WARN("{} is obsolete, it is now default", arg_fluffy_blocks.name); if(command_line::get_arg(vm, arg_test_drop_download) == true) test_drop_download(); @@ -336,18 +336,18 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con folder /= "fake"; // make sure the data directory exists, and try to lock it - CHECK_AND_ASSERT_MES(boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false, + GULPS_CHECK_AND_ASSERT_MES(boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false, std::string("Failed to create directory ").append(folder.string()).c_str()); std::unique_ptr db(new_db(db_type)); if(db == NULL) { - LOG_ERROR("Attempted to use non-existent database type"); + GULPS_LOG_ERROR("Attempted to use non-existent database type"); return false; } folder /= db->get_db_name(); - MGINFO("Loading blockchain from folder " << folder.string() << " ..."); + GULPSF_GLOBAL_PRINT("Loading blockchain from folder {} ...", folder.string()); const std::string filename = folder.string(); // default to fast:async:1 @@ -364,7 +364,7 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode); for(const auto &option : options) - MDEBUG("option: " << option); + GULPSF_LOG_L1("option: {}", option); // default to fast:async:1 uint64_t DEFAULT_FLAGS = DBF_FAST; @@ -424,7 +424,7 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con } catch(const DB_ERROR &e) { - LOG_ERROR("Error opening database: " << e.what()); + GULPSF_LOG_ERROR("Error opening database: {}", e.what()); return false; } @@ -434,7 +434,7 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, test_options); r = m_mempool.init(max_txpool_size); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); // now that we have a valid m_blockchain_storage, we can clean out any // transactions in the pool that do not conform to the current fork @@ -442,15 +442,15 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con bool show_time_stats = command_line::get_arg(vm, arg_show_time_stats) != 0; m_blockchain_storage.set_show_time_stats(show_time_stats); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); block_sync_size = command_line::get_arg(vm, arg_block_sync_size); - MGINFO("Loading checkpoints"); + GULPS_GLOBAL_PRINT("Loading checkpoints"); // load json & DNS checkpoints, and verify them // with respect to what blocks we already have - CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); + GULPS_CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); // DNS versions checking if(check_updates_string == "disabled") @@ -463,12 +463,12 @@ bool core::init(const boost::program_options::variables_map &vm, const char *con check_updates_level = UPDATES_UPDATE; else { - MERROR("Invalid argument to --dns-versions-check: " << check_updates_string); + GULPS_ERROR("Invalid argument to --dns-versions-check: {}", check_updates_string); return false; } r = m_miner.init(vm, m_nettype); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); return load_state_data(); } @@ -524,7 +524,7 @@ bool core::handle_incoming_tx_pre(const blobdata &tx_blob, tx_verification_conte if(tx_blob.size() > get_max_tx_size()) { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected"); + GULPSF_LOG_L1("WRONG TRANSACTION BLOB, too big size {}, rejected", tx_blob.size() ); tvc.m_verifivation_failed = true; tvc.m_too_big = true; return false; @@ -535,7 +535,7 @@ bool core::handle_incoming_tx_pre(const blobdata &tx_blob, tx_verification_conte if(!parse_tx_from_blob(tx, tx_hash, tx_prefixt_hash, tx_blob)) { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected"); + GULPS_LOG_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected"); tvc.m_verifivation_failed = true; return false; } @@ -547,7 +547,7 @@ bool core::handle_incoming_tx_pre(const blobdata &tx_blob, tx_verification_conte if(bad_semantics_txes[idx].find(tx_hash) != bad_semantics_txes[idx].end()) { bad_semantics_txes_lock.unlock(); - LOG_PRINT_L1("Transaction already seen with bad semantics, rejected"); + GULPS_LOG_L1("Transaction already seen with bad semantics, rejected"); tvc.m_verifivation_failed = true; return false; } @@ -557,14 +557,14 @@ bool core::handle_incoming_tx_pre(const blobdata &tx_blob, tx_verification_conte if(tx.version < MIN_TRANSACTION_VERSION || tx.version > MAX_TRANSACTION_VERSION) { // v2 is the latest one we know - LOG_PRINT_L1("Transaction version unknown"); + GULPS_LOG_L1("Transaction version unknown"); tvc.m_verifivation_failed = true; return false; } if(tx.unlock_time >= common_config::CRYPTONOTE_MAX_BLOCK_NUMBER) { - LOG_PRINT_L1("Transaction is time-locked and we only accept block number lock."); + GULPS_LOG_L1("Transaction is time-locked and we only accept block number lock."); tvc.m_verifivation_failed = true; return false; } @@ -576,18 +576,18 @@ bool core::handle_incoming_tx_post(const blobdata &tx_blob, tx_verification_cont { if(!check_tx_syntax(tx)) { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected"); + GULPSF_LOG_L1("WRONG TRANSACTION BLOB, Failed to check tx {} syntax, rejected", tx_hash ); tvc.m_verifivation_failed = true; return false; } if(keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area()) { - MTRACE("Skipping semantics check for tx kept by block in embedded hash area"); + GULPS_LOG_L2("Skipping semantics check for tx kept by block in embedded hash area"); } else if(!check_tx_semantic(tx, keeped_by_block)) { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected"); + GULPSF_LOG_L1("WRONG TRANSACTION BLOB, Failed to check tx {} semantic, rejected", tx_hash ); tvc.m_verifivation_failed = true; bad_semantics_txes_lock.lock(); bad_semantics_txes[0].insert(tx_hash); @@ -605,7 +605,7 @@ bool core::handle_incoming_tx_post(const blobdata &tx_blob, tx_verification_cont //----------------------------------------------------------------------------------------------- bool core::handle_incoming_txs(const std::list &tx_blobs, std::vector &tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); struct result { @@ -630,7 +630,7 @@ bool core::handle_incoming_txs(const std::list &tx_blobs, std::vector< } catch(const std::exception &e) { - MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what()); + GULPSF_VERIFY_ERR_TX("Exception in handle_incoming_tx_pre: {}", e.what()); results[i].res = false; } }); @@ -643,11 +643,11 @@ bool core::handle_incoming_txs(const std::list &tx_blobs, std::vector< continue; if(m_mempool.have_tx(results[i].hash)) { - LOG_PRINT_L2("tx " << results[i].hash << "already have transaction in tx_pool"); + GULPSF_LOG_L2("tx {}already have transaction in tx_pool", results[i].hash ); } else if(m_blockchain_storage.have_tx(results[i].hash)) { - LOG_PRINT_L2("tx " << results[i].hash << " already have transaction in blockchain"); + GULPSF_LOG_L2("tx {} already have transaction in blockchain", results[i].hash ); } else { @@ -658,7 +658,7 @@ bool core::handle_incoming_txs(const std::list &tx_blobs, std::vector< } catch(const std::exception &e) { - MERROR_VER("Exception in handle_incoming_tx_post: " << e.what()); + GULPSF_VERIFY_ERR_TX("Exception in handle_incoming_tx_post: {}", e.what()); results[i].res = false; } }); @@ -679,19 +679,19 @@ bool core::handle_incoming_txs(const std::list &tx_blobs, std::vector< ok &= add_new_tx(results[i].tx, results[i].hash, results[i].prefix_hash, it->size(), tvc[i], keeped_by_block, relayed, do_not_relay); if(tvc[i].m_verifivation_failed) { - MERROR_VER("Transaction verification failed: " << results[i].hash); + GULPSF_VERIFY_ERR_TX("Transaction verification failed: {}", results[i].hash); } else if(tvc[i].m_verifivation_impossible) { - MERROR_VER("Transaction verification impossible: " << results[i].hash); + GULPSF_VERIFY_ERR_TX("Transaction verification impossible: {}", results[i].hash); } if(tvc[i].m_added_to_pool) - MDEBUG("tx added: " << results[i].hash); + GULPSF_LOG_L1("tx added: {}", results[i].hash); } return ok; - CATCH_ENTRY_L0("core::handle_incoming_txs()", false); + GULPS_CATCH_ENTRY_L0("core::handle_incoming_txs()", false); } //----------------------------------------------------------------------------------------------- bool core::handle_incoming_tx(const blobdata &tx_blob, tx_verification_context &tvc, bool keeped_by_block, bool relayed, bool do_not_relay) @@ -719,31 +719,31 @@ bool core::check_tx_semantic(const transaction &tx, bool keeped_by_block) const { if(!tx.vin.size()) { - MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx)); + GULPSF_VERIFY_ERR_TX("tx with empty inputs, rejected for tx id= {}", get_transaction_hash(tx)); return false; } if(!check_inputs_types_supported(tx)) { - MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx)); + GULPSF_VERIFY_ERR_TX("unsupported input types for tx id= {}", get_transaction_hash(tx)); return false; } if(!check_outs_valid(tx)) { - MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx)); + GULPSF_VERIFY_ERR_TX("tx with invalid outputs, rejected for tx id= {}", get_transaction_hash(tx)); return false; } if(tx.rct_signatures.outPk.size() != tx.vout.size()) { - MERROR_VER("tx with mismatched vout/outPk count, rejected for tx id= " << get_transaction_hash(tx)); + GULPS_VERIFY_ERR_TX("tx with mismatched vout/outPk count, rejected for tx id= ", get_transaction_hash(tx)); return false; } if(!check_money_overflow(tx)) { - MERROR_VER("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx)); + GULPSF_VERIFY_ERR_TX("tx has money overflow, rejected for tx id= {}", get_transaction_hash(tx)); return false; } @@ -751,26 +751,26 @@ bool core::check_tx_semantic(const transaction &tx, bool keeped_by_block) const if(!keeped_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE) { - MERROR_VER("tx is too large " << get_object_blobsize(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); + GULPSF_VERIFY_ERR_TX("tx is too large {}, expected not bigger than {}", get_object_blobsize(tx) , m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); return false; } //check if tx use different key images if(!check_tx_inputs_keyimages_diff(tx)) { - MERROR_VER("tx uses a single key image more than once"); + GULPS_VERIFY_ERR_TX("tx uses a single key image more than once"); return false; } if(!check_tx_inputs_ring_members_diff(tx)) { - MERROR_VER("tx uses duplicate ring members"); + GULPS_VERIFY_ERR_TX("tx uses duplicate ring members"); return false; } if(!check_tx_inputs_keyimages_domain(tx)) { - MERROR_VER("tx uses key image not in the valid domain"); + GULPS_VERIFY_ERR_TX("tx uses key image not in the valid domain"); return false; } @@ -779,7 +779,7 @@ bool core::check_tx_semantic(const transaction &tx, bool keeped_by_block) const { case rct::RCTTypeNull: // coinbase should not come here, so we reject for all other types - MERROR_VER("Unexpected Null rctSig type"); + GULPS_VERIFY_ERR_TX("Unexpected Null rctSig type"); return false; case rct::RCTTypeSimple: case rct::RCTTypeBulletproof: @@ -787,19 +787,19 @@ bool core::check_tx_semantic(const transaction &tx, bool keeped_by_block) const // and there is very little point in polishing turds if(!rct::verRctSemanticsSimple(rv)) { - MERROR_VER("rct signature semantics check failed"); + GULPS_VERIFY_ERR_TX("rct signature semantics check failed"); return false; } break; case rct::RCTTypeFull: if(!rct::verRct(rv, true)) { - MERROR_VER("rct signature semantics check failed"); + GULPS_VERIFY_ERR_TX("rct signature semantics check failed"); return false; } break; default: - MERROR_VER("Unknown rct type: " << rv.type); + GULPS_VERIFY_ERR_TX("Unknown rct type: ", rv.type); return false; } @@ -930,13 +930,13 @@ bool core::add_new_tx(transaction &tx, const crypto::hash &tx_hash, const crypto if(m_mempool.have_tx(tx_hash)) { - LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool"); + GULPSF_LOG_L2("tx {} already have transaction in tx_pool", tx_hash ); return true; } if(m_blockchain_storage.have_tx(tx_hash)) { - LOG_PRINT_L2("tx " << tx_hash << " already have transaction in blockchain"); + GULPSF_LOG_L2("tx {} already have transaction in blockchain", tx_hash ); return true; } @@ -969,7 +969,7 @@ void core::on_transaction_relayed(const cryptonote::blobdata &tx_blob) crypto::hash tx_hash, tx_prefix_hash; if(!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash)) { - LOG_ERROR("Failed to parse relayed transaction"); + GULPS_LOG_ERROR("Failed to parse relayed transaction"); return; } txs.push_back(std::make_pair(tx_hash, std::move(tx_blob))); @@ -1033,7 +1033,7 @@ block_complete_entry get_block_complete_entry(block &b, tx_memory_pool &pool) for(const auto &tx_hash : b.tx_hashes) { cryptonote::blobdata txblob; - CHECK_AND_ASSERT_THROW_MES(pool.get_transaction(tx_hash, txblob), "Transaction not found in pool"); + GULPS_CHECK_AND_ASSERT_THROW_MES(pool.get_transaction(tx_hash, txblob), "Transaction not found in pool"); bce.txs.push_back(txblob); } return bce; @@ -1060,7 +1060,7 @@ bool core::handle_block_found(block &b) update_miner_block_template(); m_miner.resume(); - CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "mined block failed verification"); + GULPS_CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "mined block failed verification"); if(bvc.m_added_to_main_chain) { cryptonote_connection_context exclude_context = boost::value_initialized(); @@ -1071,11 +1071,11 @@ bool core::handle_block_found(block &b) m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, missed_txs); if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) { - LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block"); + GULPS_LOG_L1("Block found but, seems that reorganize just happened after that, do not relay this block"); return true; } - CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size() - << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size()); + GULPS_CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" , get_block_hash(b) , " txs.size()=" , txs.size() + , ", b.tx_hashes.size()=" , b.tx_hashes.size() , ", missed_txs.size()" , missed_txs.size()); block_to_blob(b, arg.b.block); //pack transactions @@ -1128,16 +1128,16 @@ bool core::cleanup_handle_incoming_blocks(bool force_sync) //----------------------------------------------------------------------------------------------- bool core::handle_incoming_block(const blobdata &block_blob, block_verification_context &bvc, bool update_miner_blocktemplate) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); // load json & DNS checkpoints every 10min/hour respectively, // and verify them with respect to what blocks we already have - CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); + GULPS_CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); bvc = boost::value_initialized(); if(block_blob.size() > common_config::BLOCK_SIZE_LIMIT_ABSOLUTE) { - LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); + GULPSF_LOG_L1("WRONG BLOCK BLOB, too big size {}, rejected", block_blob.size() ); bvc.m_verifivation_failed = true; return false; } @@ -1145,7 +1145,7 @@ bool core::handle_incoming_block(const blobdata &block_blob, block_verification_ block b = AUTO_VAL_INIT(b); if(!parse_and_validate_block_from_blob(block_blob, b)) { - LOG_PRINT_L1("Failed to parse and validate new block"); + GULPS_LOG_L1("Failed to parse and validate new block"); bvc.m_verifivation_failed = true; return false; } @@ -1154,7 +1154,7 @@ bool core::handle_incoming_block(const blobdata &block_blob, block_verification_ update_miner_block_template(); return true; - CATCH_ENTRY_L0("core::handle_incoming_block()", false); + GULPS_CATCH_ENTRY_L0("core::handle_incoming_block()", false); } //----------------------------------------------------------------------------------------------- // Used by the RPC server to check the size of an incoming @@ -1163,7 +1163,7 @@ bool core::check_incoming_block_size(const blobdata &block_blob) const { if(block_blob.size() > common_config::BLOCK_SIZE_LIMIT_ABSOLUTE) { - LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); + GULPSF_LOG_L1("WRONG BLOCK BLOB, too big size {}, rejected", block_blob.size() ); return false; } return true; @@ -1277,15 +1277,13 @@ bool core::on_idle() main_message = "The daemon is running offline and will not attempt to sync to the Ryo network."; else main_message = "The daemon will start synchronizing with the network. This may take a long time to complete."; - MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL - << main_message << ENDL - << ENDL - << "You can set the level of process detailization through \"set_log \" command," << ENDL - << "where is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL - << ENDL - << "Use the \"help\" command to see the list of available commands." << ENDL - << "Use \"help \" to see a command's documentation." << ENDL - << "**********************************************************************" << ENDL); + GULPS_GLOBAL_PRINT_CLR(gulps::COLOR_BOLD_YELLOW, "\n**********************************************************************\n", + main_message, + "\n\nYou can set the level of process detailization through \"set_log \" command,\n", + "where is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING).\n\n", + "Use the \"help\" command to see the list of available commands.\n", + "Use \"help \" to see a command's documentation.\n", + "**********************************************************************\n"); m_starter_message_showed = true; } @@ -1301,19 +1299,18 @@ bool core::on_idle() bool core::check_fork_time() { HardFork::State state = m_blockchain_storage.get_hard_fork_state(); - const el::Level level = el::Level::Warning; switch(state) { case HardFork::LikelyForked: - MCLOG_RED(level, "global", "**********************************************************************"); - MCLOG_RED(level, "global", "Last scheduled hard fork is too far in the past."); - MCLOG_RED(level, "global", "We are most likely forked from the network. Daemon update needed now."); - MCLOG_RED(level, "global", "**********************************************************************"); + GULPS_CAT_WARN("global", "**********************************************************************"); + GULPS_CAT_WARN("global", "Last scheduled hard fork is too far in the past."); + GULPS_CAT_WARN("global", "We are most likely forked from the network. Daemon update needed now."); + GULPS_CAT_WARN("global", "**********************************************************************"); break; case HardFork::UpdateNeeded: - MCLOG_RED(level, "global", "**********************************************************************"); - MCLOG_RED(level, "global", "Last scheduled hard fork time shows a daemon update is needed soon."); - MCLOG_RED(level, "global", "**********************************************************************"); + GULPS_CAT_WARN("global", "**********************************************************************"); + GULPS_CAT_WARN("global", "Last scheduled hard fork time shows a daemon update is needed soon."); + GULPS_CAT_WARN("global", "**********************************************************************"); break; default: break; @@ -1355,7 +1352,7 @@ bool core::check_updates() return true; std::string version, hash; - MCDEBUG("updates", "Checking for a new " << software << " version for " << buildtag); + GULPSF_CAT_LOG_L1("updates", "Checking for a new {} version for {}", software, buildtag); if (!tools::check_updates(software, buildtag, version, hash)) return false; @@ -1363,7 +1360,7 @@ bool core::check_updates() return true; std::string url = tools::get_update_url(software, subdir, buildtag, version, true); - MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash); + GULPSF_GLOBAL_PRINT_CLR(gulps:COLOR_CYAN, "Version {} of {} for {} is available: {}, SHA256 hash {}", version , software, buildtag, url, hash); if (check_updates_level == UPDATES_NOTIFY) return true; @@ -1382,18 +1379,18 @@ bool core::check_updates() if (m_update_download != 0) { - MCDEBUG("updates", "Already downloading update"); + GULPS_CAT_LOG_L1("updates", "Already downloading update"); return true; } crypto::hash file_hash; if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash))) { - MCDEBUG("updates", "We don't have that file already, downloading"); + GULPS_CAT_LOG_L1("updates", "We don't have that file already, downloading"); const std::string tmppath = path.string() + ".tmp"; if (epee::file_io_utils::is_file_exist(tmppath)) { - MCDEBUG("updates", "We have part of the file already, resuming download"); + GULPS_CAT_LOG_L1("updates", "We have part of the file already, resuming download"); } m_last_update_length = 0; m_update_download = tools::download_async(tmppath, url, [this, hash, path](const std::string &tmppath, const std::string &uri, bool success) { @@ -1403,20 +1400,20 @@ bool core::check_updates() crypto::hash file_hash; if (!tools::sha256sum(tmppath, file_hash)) { - MCERROR("updates", "Failed to hash " << tmppath); + GULPSF_CAT_ERROR("updates", "Failed to hash {}", tmppath); remove = true; good = false; } else if (hash != epee::string_tools::pod_to_hex(file_hash)) { - MCERROR("updates", "Download from " << uri << " does not match the expected hash"); + GULPSF_CAT_ERROR("updates", "Download from {} does not match the expected hash", uri ); remove = true; good = false; } } else { - MCERROR("updates", "Failed to download " << uri); + GULPSF_CAT_ERROR("updates", "Failed to download {}", uri); good = false; } boost::unique_lock lock(m_update_mutex); @@ -1426,7 +1423,7 @@ bool core::check_updates() std::error_code e = tools::replace_file(tmppath, path.string()); if (e) { - MCERROR("updates", "Failed to rename downloaded file"); + GULPS_CAT_ERROR("updates", "Failed to rename downloaded file"); good = false; } } @@ -1434,24 +1431,24 @@ bool core::check_updates() { if (!boost::filesystem::remove(tmppath)) { - MCERROR("updates", "Failed to remove invalid downloaded file"); + GULPS_CAT_ERROR("updates", "Failed to remove invalid downloaded file"); good = false; } } if (good) - MCLOG_CYAN(el::Level::Info, "updates", "New version downloaded to " << path.string()); + GULPSF_CAT_PRINT_CLR(gulps::COLOR_CYAN, "updates", "New version downloaded to {}", path.string()); }, [this](const std::string &path, const std::string &uri, size_t length, ssize_t content_length) { if (length >= m_last_update_length + 1024 * 1024 * 10) { m_last_update_length = length; - MCDEBUG("updates", "Downloaded " << length << "/" << (content_length ? std::to_string(content_length) : "unknown")); + GULPSF_CAT_LOG_L1("updates", "Downloaded {}/{}", length, (content_length ? std::to_string(content_length) : "unknown")); } return true; }); } else { - MCDEBUG("updates", "We already have " << path << " with expected hash"); + GULPSF_CAT_LOG_L1("updates", "We already have {} with expected hash", path); } lock.unlock(); @@ -1459,7 +1456,7 @@ bool core::check_updates() if (check_updates_level == UPDATES_DOWNLOAD) return true; - MCERROR("updates", "Download/update not implemented yet"); + GULPS_CAT_ERROR("updates", "Download/update not implemented yet"); #endif return true; } @@ -1469,8 +1466,7 @@ bool core::check_disk_space() uint64_t free_space = get_free_space(); if(free_space < 1ull * 1024 * 1024 * 1024) // 1 GB { - const el::Level level = el::Level::Warning; - MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder); + GULPSF_CAT_WARN("Free space is below 1 GB on {}", m_config_folder); } return true; } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index d590f0ea..0855d172 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -508,6 +508,11 @@ class core : public i_miner_handler */ bool find_blockchain_supplement(const uint64_t req_start_block, const std::list &qblock_ids, std::list>> &blocks, uint64_t &total_height, uint64_t &start_height, size_t max_count) const; + inline bool find_blockchain_supplement_indexed(const uint64_t req_start_block, const std::list &qblock_ids, std::vector& blocks, + std::vector& out_idx, uint64_t &total_height, uint64_t &start_height, size_t max_count) const + { + return m_blockchain_storage.find_blockchain_supplement_indexed(req_start_block, qblock_ids, blocks, out_idx, total_height, start_height, max_count); + } /** * @brief gets some stats about the daemon * diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 9c416c19..cebc4fc5 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -33,8 +33,12 @@ using namespace epee; #include "multisig/multisig.h" #include "ringct/rctSigs.h" +#include "common/gulps.hpp" + using namespace crypto; +GULPS_CAT_MAJOR("crtnte_tx_utils"); + namespace cryptonote { //--------------------------------------------------------------- @@ -61,7 +65,7 @@ void classify_addresses(const std::vector &destinations, c } } } - LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses"); + GULPSF_LOG_L2("destinations include {} standard addresses and {} subaddresses", num_stdaddresses , num_subaddresses); } //--------------------------------------------------------------- bool construct_miner_tx(cryptonote::network_type nettype, size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction &tx, const blobdata &extra_nonce) @@ -79,12 +83,12 @@ bool construct_miner_tx(cryptonote::network_type nettype, size_t height, size_t uint64_t block_reward; if(!get_block_reward(nettype, median_size, current_block_size, already_generated_coins, block_reward, height)) { - LOG_PRINT_L0("Block is too big"); + GULPS_PRINT("Block is too big"); return false; } #if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - LOG_PRINT_L1("Creating block template: reward " << block_reward << ", fee " << fee); + GULPSF_LOG_L1("Creating block template: reward {}, fee {}", block_reward , fee); #endif block_reward += fee; @@ -92,27 +96,27 @@ bool construct_miner_tx(cryptonote::network_type nettype, size_t height, size_t crypto::key_derivation derivation = AUTO_VAL_INIT(derivation); crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" , miner_address.m_view_public_key , ", " , txkey.sec , ")"); r = crypto::derive_public_key(derivation, 0, miner_address.m_spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", 0, " << miner_address.m_spend_public_key << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" , derivation , ", 0, " , miner_address.m_spend_public_key , ")"); tx_out out = { block_reward, txout_to_key(out_eph_public_key) }; tx.vout.push_back(out); - + uint64_t dev_fund_amount; if(get_dev_fund_amount(nettype, height, dev_fund_amount)) { address_parse_info dev_addr; r = get_account_address_from_str(dev_addr, std::string(common_config::DEV_FUND_ADDRESS)); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse dev address"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse dev address"); r = crypto::generate_key_derivation(dev_addr.address.m_view_public_key, txkey.sec, derivation); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << dev_addr.address.m_view_public_key << ", " << txkey.sec << ")"); - + GULPS_CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" , dev_addr.address.m_view_public_key , ", " , txkey.sec , ")"); + r = crypto::derive_public_key(derivation, 1, dev_addr.address.m_spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", 1, " << dev_addr.address.m_spend_public_key << ")"); - + GULPS_CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" , derivation , ", 1, " , dev_addr.address.m_spend_public_key , ")"); + out = { dev_fund_amount, txout_to_key(out_eph_public_key) }; tx.vout.push_back(out); } @@ -127,14 +131,17 @@ bool construct_miner_tx(cryptonote::network_type nettype, size_t height, size_t tx.invalidate_hashes(); - //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee) + //GULPS_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee) // << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2); return true; } //--------------------------------------------------------------- -crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional &change_addr) +crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional &change_addr, bool allow_any_key) { - account_public_address addr = {null_pkey, null_pkey}; + if(allow_any_key && change_addr) + return change_addr->m_view_public_key; + + account_public_address addr(null_pkey, null_pkey); size_t count = 0; for(const auto &i : destinations) { @@ -145,7 +152,7 @@ crypto::public_key get_destination_view_key_pub(const std::vector 0) - return null_pkey; + return allow_any_key ? addr.m_view_public_key : null_pkey; addr = i.addr; ++count; } @@ -154,13 +161,13 @@ crypto::public_key get_destination_view_key_pub(const std::vector &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool bulletproof, rct::multisig_out *msout, bool use_uniform_pids) +bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool bulletproof, rct::multisig_out *msout) { hw::device &hwdev = sender_account_keys.get_device(); if(sources.empty()) { - LOG_ERROR("Empty sources"); + GULPS_LOG_ERROR("Empty sources"); return false; } @@ -176,13 +183,13 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std if(unlock_time > common_config::CRYPTONOTE_MAX_BLOCK_NUMBER) { - LOG_ERROR("Timed transaction lock is no longer supported. Please use a block number."); + GULPS_LOG_ERROR("Timed transaction lock is no longer supported. Please use a block number."); return false; } if(bulletproof && destinations.size() > common_config::BULLETPROOF_MAX_OUTPUTS) { - LOG_ERROR("Current bulletproof implementation supports up to 16 outputs (15 + change)."); + GULPS_ERROR("Current bulletproof implementation supports up to 16 outputs (15 + change)."); return false; } @@ -203,7 +210,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std ++idx; if(src_entr.real_output >= src_entr.outputs.size()) { - LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size()); + GULPSF_LOG_ERROR("real_output index ({})bigger than output_keys.size()={}", src_entr.real_output, src_entr.outputs.size()); return false; } summary_inputs_money += src_entr.amount; @@ -215,18 +222,17 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std const auto &out_key = reinterpret_cast(src_entr.outputs[src_entr.real_output].second.dest); if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral, img, hwdev)) { - LOG_ERROR("Key image generation failed!"); + GULPS_LOG_ERROR("Key image generation failed!"); return false; } //check that derivated key is equal with real output key (if non multisig) if(!msout && !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest)) { - LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! " << ENDL << "derived_key:" - << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" - << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second.dest)); - LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct); - LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index); + GULPSF_LOG_ERROR("derived public key mismatch with output public key at index{} , real out {}!\nderived_key:{}\nreal output_public_key:{}", idx, src_entr.real_output , + string_tools::pod_to_hex(in_ephemeral.pub), string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second.dest)); + GULPSF_LOG_ERROR("amount {}, rct {}", src_entr.amount, src_entr.rct); + GULPSF_LOG_ERROR("tx pubkey {}, real_output_in_tx_index {}", src_entr.real_out_tx_key, src_entr.real_output_in_tx_index); return false; } @@ -282,14 +288,14 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std // - there's only one destination which is a subaddress bool need_additional_txkeys = num_subaddresses > 0 && (num_stdaddresses > 0 || num_subaddresses > 1); if(need_additional_txkeys) - CHECK_AND_ASSERT_MES(destinations.size() == additional_tx_keys.size(), false, "Wrong amount of additional tx keys"); + GULPS_CHECK_AND_ASSERT_MES(destinations.size() == additional_tx_keys.size(), false, "Wrong amount of additional tx keys"); uint64_t summary_outs_money = 0; //fill outputs size_t output_index = 0; for(const tx_destination_entry &dst_entr : destinations) { - CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version >= 2, false, "Destination with wrong amount: " << dst_entr.amount); + GULPS_CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version >= 2, false, "Destination with wrong amount: " , dst_entr.amount); crypto::key_derivation derivation; crypto::public_key out_eph_public_key; @@ -309,13 +315,13 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std { // sending change to yourself; derivation = a*R r = hwdev.generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" , txkey_pub , ", " , sender_account_keys.m_view_secret_key , ")"); } else { // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme) r = hwdev.generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" , dst_entr.addr.m_view_public_key , ", " , (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) , ")"); } if(need_additional_txkeys) @@ -328,7 +334,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std amount_keys.push_back(rct::sk2rct(scalar1)); r = hwdev.derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", " << dst_entr.addr.m_spend_public_key << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" , derivation , ", " , output_index , ", " , dst_entr.addr.m_spend_public_key , ")"); hwdev.add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, output_index, amount_keys.back(), out_eph_public_key); @@ -341,98 +347,58 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std output_index++; summary_outs_money += dst_entr.amount; } - CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(), false, "Internal error creating additional public keys"); + GULPS_CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(), false, "Internal error creating additional public keys"); - LOG_PRINT_L2("tx pubkey: " << txkey_pub); + GULPS_LOG_L2("tx pubkey: ", txkey_pub); if(need_additional_txkeys) { - LOG_PRINT_L2("additional tx pubkeys: "); + GULPS_LOG_L2("additional tx pubkeys: "); for(size_t i = 0; i < additional_tx_public_keys.size(); ++i) - LOG_PRINT_L2(additional_tx_public_keys[i]); + GULPS_LOG_L2(additional_tx_public_keys[i]); add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys); } - if(use_uniform_pids) + + tx_extra_uniform_payment_id pid; + //Add payment id after pubkeys + if(payment_id != nullptr) { - //Add payment id after pubkeys - if(payment_id != nullptr) + if(payment_id->zero != 0) { - if(payment_id->zero != 0) - { - LOG_ERROR("Internal error. Invalid payment id."); - return false; - } - - LOG_PRINT_L2("Encrypting payment id " << payment_id->payment_id); - - crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr); - if(view_key_pub == null_pkey) - { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); - return false; - } - - tx_extra_uniform_payment_id pid; - pid.pid = *payment_id; + GULPS_ERROR("Internal error. Invalid payment id."); + return false; + } - if(!hwdev.encrypt_payment_id(pid.pid, view_key_pub, tx_key)) - { - LOG_ERROR("Failed to encrypt payment id"); - return false; - } + pid.pid = *payment_id; + } - if(!add_payment_id_to_tx_extra(tx.extra, &pid)) - { - LOG_ERROR("Failed to add encrypted payment id to tx extra"); - return false; - } + GULPSF_LOG_L2("Encrypting payment id {}", pid.pid.payment_id); - LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); - } - else - { - add_payment_id_to_tx_extra(tx.extra, nullptr); - } - } - else if(payment_id != nullptr) + crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr, payment_id == nullptr); + if(view_key_pub == null_pkey) { - blobdata extra_nonce; - const uint64_t* split_id = reinterpret_cast(&payment_id->payment_id); - if(split_id[1] == 0 && split_id[2] == 0 && split_id[3] == 0) - { - crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr); - if(view_key_pub == null_pkey) - { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); - return false; - } - - crypto::hash8 legacy_enc_pid; - memcpy(&legacy_enc_pid, &payment_id->payment_id, sizeof(crypto::hash8)); - if(!hwdev.encrypt_payment_id(legacy_enc_pid, view_key_pub, tx_key)) - { - LOG_ERROR("Failed to encrypt payment id"); - return false; - } + GULPS_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + return false; + } - set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, legacy_enc_pid); - } - else - { - set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id->payment_id); - } + if(!hwdev.encrypt_payment_id(pid.pid, view_key_pub, tx_key)) + { + GULPS_ERROR("Failed to encrypt payment id"); + return false; + } - if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) - { - LOG_ERROR("Failed to add extra_nonce"); - return false; - } + if(!add_payment_id_to_tx_extra(tx.extra, pid)) + { + GULPS_ERROR("Failed to add encrypted payment id to tx extra"); + return false; } + GULPSF_LOG_L1("Encrypted payment ID: {}", pid.pid.payment_id); + //check money if(summary_outs_money > summary_inputs_money) { - LOG_ERROR("Transaction inputs money (" << summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")"); + GULPSF_LOG_ERROR("Transaction inputs money ({}) less than outputs money ({})", summary_inputs_money, summary_outs_money); return false; } @@ -442,7 +408,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0); if(zero_secret_key) { - MDEBUG("Null secret key, skipping signatures"); + GULPS_LOG_L1("Null secret key, skipping signatures"); } size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct @@ -458,7 +424,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std { if(src_entr.real_output != sources.begin()->real_output) { - LOG_ERROR("All inputs must have the same index for non-simple ringct"); + GULPS_LOG_ERROR("All inputs must have the same index for non-simple ringct"); return false; } } @@ -468,7 +434,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std { if(n_total_outs != sources[i].outputs.size()) { - LOG_ERROR("Non-simple ringct transaction has varying ring size"); + GULPS_LOG_ERROR("Non-simple ringct transaction has varying ring size"); return false; } } @@ -551,16 +517,16 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std else tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations_keyV, outamounts, mixRing, amount_keys, msout ? &kLRki[0] : NULL, msout, sources[0].real_output, outSk, hwdev); // same index assumption - CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); + GULPS_CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); - MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL); + GULPS_CAT_INFO("construct_tx", "transaction_created: ", get_transaction_hash(tx), "\n", obj_to_json_str(tx), "\n"); tx.invalidate_hashes(); return true; } //--------------------------------------------------------------- -bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool bulletproof, rct::multisig_out *msout, bool use_uniform_pids) +bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool bulletproof, rct::multisig_out *msout) { hw::device &hwdev = sender_account_keys.get_device(); hwdev.open_tx(tx_key); @@ -580,8 +546,8 @@ bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const additional_tx_keys.push_back(keypair::generate(sender_account_keys.get_device()).sec); } - bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, - payment_id, tx, unlock_time, tx_key, additional_tx_keys, bulletproof, msout, use_uniform_pids); + bool r = construct_tx_with_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, + payment_id, tx, unlock_time, tx_key, additional_tx_keys, bulletproof, msout); hwdev.close_tx(); return r; @@ -599,16 +565,16 @@ bool construct_tx(const account_keys &sender_account_keys, std::vector(); blobdata tx_bl; bool r = string_tools::parse_hexstr_to_binbuff(genesis_tx, tx_bl); - CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); - CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); bl.major_version = 1; bl.minor_version = 1; bl.timestamp = 0; diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index bf00ff14..31c4954a 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -79,10 +79,10 @@ struct tx_destination_entry }; //--------------------------------------------------------------- -crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional &change_addr); +crypto::public_key get_destination_view_key_pub(const std::vector &destinations, const boost::optional &change_addr, bool allow_any_key = false); bool construct_tx(const account_keys &sender_account_keys, std::vector &sources, const std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time); -bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool bulletproof = false, rct::multisig_out *msout = NULL, bool use_uniform_pids = false); -bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool bulletproof = false, rct::multisig_out *msout = NULL, bool use_uniform_pids = false); +bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, bool bulletproof = false, rct::multisig_out *msout = NULL); +bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const std::unordered_map &subaddresses, std::vector &sources, std::vector &destinations, const boost::optional &change_addr, const crypto::uniform_payment_id* payment_id, transaction &tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector &additional_tx_keys, bool bulletproof = false, rct::multisig_out *msout = NULL); bool generate_genesis_block(network_type nettype, block &bl, std::string const &genesis_tx, uint32_t nonce); } diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 51953934..9039f88b 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,6 +18,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + #include #include #include @@ -36,12 +37,13 @@ #include "tx_pool.h" #include "warnings.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "txpool" +#include "common/gulps.hpp" + DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated using namespace crypto; +GULPS_CAT_MAJOR("tx_pool"); namespace cryptonote { @@ -92,7 +94,7 @@ class LockedTXN } catch(const std::exception &e) { - MWARNING("LockedTXN dtor filtering exception: " << e.what()); + GULPS_WARN("LockedTXN dtor filtering exception: ", e.what()); } } @@ -116,7 +118,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has if(tx.version == 0) { // v0 never accepted - LOG_PRINT_L1("transaction version 0 is invalid"); + GULPS_LOG_L1("transaction version 0 is invalid"); tvc.m_verifivation_failed = true; return false; } @@ -153,7 +155,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has size_t tx_size_limit = common_config::TRANSACTION_SIZE_LIMIT; if(!kept_by_block && blob_size > tx_size_limit) { - LOG_PRINT_L1("transaction is too big: " << blob_size << " bytes, maximum size: " << tx_size_limit); + GULPSF_LOG_L1("transaction is too big: {} bytes, maximum size: {}", blob_size, tx_size_limit); tvc.m_verifivation_failed = true; tvc.m_too_big = true; return false; @@ -167,7 +169,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has if(have_tx_keyimges_as_spent(tx)) { mark_double_spend(tx); - LOG_PRINT_L1("Transaction with id= " << id << " used already spent key images"); + GULPSF_LOG_L1("Transaction with id= {} used already spent key images", id ); tvc.m_verifivation_failed = true; tvc.m_double_spend = true; return false; @@ -176,7 +178,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has if(!m_blockchain.check_tx_outputs(tx, tvc)) { - LOG_PRINT_L1("Transaction with id= " << id << " has at least one invalid output"); + GULPSF_LOG_L1("Transaction with id= {} has at least one invalid output", id ); tvc.m_verifivation_failed = true; tvc.m_invalid_output = true; return false; @@ -221,7 +223,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has } catch(const std::exception &e) { - MERROR("transaction already exists at inserting in memory pool: " << e.what()); + GULPSF_ERROR("transaction already exists at inserting in memory pool: {}" , e.what()); return false; } tvc.m_verifivation_impossible = true; @@ -229,7 +231,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has } else { - LOG_PRINT_L1("tx used wrong inputs, rejected"); + GULPS_LOG_L1("tx used wrong inputs, rejected"); tvc.m_verifivation_failed = true; tvc.m_invalid_input = true; return false; @@ -264,7 +266,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has } catch(const std::exception &e) { - MERROR("internal error: transaction already exists at inserting in memory pool: " << e.what()); + GULPSF_ERROR("internal error: transaction already exists at inserting in memory pool: {}" , e.what()); return false; } tvc.m_added_to_pool = true; @@ -276,7 +278,7 @@ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_has tvc.m_verifivation_failed = false; m_txpool_size += blob_size; - MINFO("Transaction added to pool: txid " << id << " bytes: " << blob_size << " fee/byte: " << (fee / (double)blob_size)); + GULPSF_INFO("Transaction added to pool: txid {} bytes: {} fee/byte: {}", id , blob_size , (fee / (double)blob_size)); prune(m_txpool_max_size); @@ -324,7 +326,7 @@ void tx_memory_pool::prune(size_t bytes) txpool_tx_meta_t meta; if(!m_blockchain.get_txpool_tx_meta(txid, meta)) { - MERROR("Failed to find tx in txpool"); + GULPS_ERROR("Failed to find tx in txpool"); return; } // don't prune the kept_by_block ones, they're likely added because we're adding a block with those @@ -337,25 +339,25 @@ void tx_memory_pool::prune(size_t bytes) cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(txblob, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); return; } // remove first, in case this throws, so key images aren't removed - MINFO("Pruning tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first); + GULPSF_INFO("Pruning tx {} from txpool: size: {}, fee/byte: {}", txid , it->first.second , it->first.first); m_blockchain.remove_txpool_tx(txid); m_txpool_size -= txblob.size(); remove_transaction_keyimages(tx); - MINFO("Pruned tx " << txid << " from txpool: size: " << it->first.second << ", fee/byte: " << it->first.first); + GULPSF_INFO("Pruned tx {} from txpool: size: {}, fee/byte: {}", txid , it->first.second , it->first.first); m_txs_by_fee_and_receive_time.erase(it--); } catch(const std::exception &e) { - MERROR("Error while pruning txpool: " << e.what()); + GULPSF_ERROR("Error while pruning txpool: {}" , e.what()); return; } } if(m_txpool_size > bytes) - MINFO("Pool size after pruning is larger than limit: " << m_txpool_size << "/" << bytes); + GULPSF_INFO("Pool size after pruning is larger than limit: {}/{}", m_txpool_size, bytes); } //--------------------------------------------------------------------------------- bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block) @@ -365,11 +367,10 @@ bool tx_memory_pool::insert_key_images(const transaction &tx, bool kept_by_block const crypto::hash id = get_transaction_hash(tx); CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, txin, false); std::unordered_set &kei_image_set = m_spent_key_images[txin.k_image]; - CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=" << kept_by_block - << ", kei_image_set.size()=" << kei_image_set.size() << ENDL << "txin.k_image=" << txin.k_image << ENDL - << "tx_id=" << id); + GULPS_CHECK_AND_ASSERT_MES(kept_by_block || kei_image_set.size() == 0, false, "internal error: kept_by_block=", kept_by_block + ,", kei_image_set.size()=", kei_image_set.size(), "\ntxin.k_image=", txin.k_image, "\ntx_id=", id); auto ins_res = kei_image_set.insert(id); - CHECK_AND_ASSERT_MES(ins_res.second, false, "internal error: try to insert duplicate iterator in key_image set"); + GULPS_CHECK_AND_ASSERT_MES(ins_res.second, false, "internal error: try to insert duplicate iterator in key_image set"); } return true; } @@ -388,15 +389,15 @@ bool tx_memory_pool::remove_transaction_keyimages(const transaction &tx) { CHECKED_GET_SPECIFIC_VARIANT(vi, const txin_to_key, txin, false); auto it = m_spent_key_images.find(txin.k_image); - CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" << txin.k_image << ENDL - << "transaction id = " << get_transaction_hash(tx)); + GULPS_CHECK_AND_ASSERT_MES(it != m_spent_key_images.end(), false, "failed to find transaction input in key images. img=" , txin.k_image , "\n" + , "transaction id = " , get_transaction_hash(tx)); std::unordered_set &key_image_set = it->second; - CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" << txin.k_image << ENDL - << "transaction id = " << actual_hash); + GULPS_CHECK_AND_ASSERT_MES(key_image_set.size(), false, "empty key_image set, img=" , txin.k_image , "\n" + , "transaction id = " , actual_hash); auto it_in_set = key_image_set.find(actual_hash); - CHECK_AND_ASSERT_MES(it_in_set != key_image_set.end(), false, "transaction id not found in key_image set, img=" << txin.k_image << ENDL - << "transaction id = " << actual_hash); + GULPS_CHECK_AND_ASSERT_MES(it_in_set != key_image_set.end(), false, "transaction id not found in key_image set, img=" , txin.k_image , "\n" + , "transaction id = " , actual_hash); key_image_set.erase(it_in_set); if(!key_image_set.size()) { @@ -422,13 +423,13 @@ bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t &bl txpool_tx_meta_t meta; if(!m_blockchain.get_txpool_tx_meta(id, meta)) { - MERROR("Failed to find tx in txpool"); + GULPS_ERROR("Failed to find tx in txpool"); return false; } cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id); if(!parse_and_validate_tx_from_blob(txblob, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); return false; } blob_size = meta.blob_size; @@ -444,7 +445,7 @@ bool tx_memory_pool::take_tx(const crypto::hash &id, transaction &tx, size_t &bl } catch(const std::exception &e) { - MERROR("Failed to remove tx from txpool: " << e.what()); + GULPSF_ERROR("Failed to remove tx from txpool: {}" , e.what()); return false; } @@ -476,11 +477,11 @@ bool tx_memory_pool::remove_stuck_transactions() if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !meta.kept_by_block) || (tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && meta.kept_by_block)) { - LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age); + GULPSF_LOG_L1("Tx {} removed from tx pool due to outdated, age: {}", txid, tx_age); auto sorted_it = find_tx_in_sorted_container(txid); if(sorted_it == m_txs_by_fee_and_receive_time.end()) { - LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!"); + GULPSF_LOG_L1("Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid ); } else { @@ -504,7 +505,7 @@ bool tx_memory_pool::remove_stuck_transactions() cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(bd, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); // continue } else @@ -517,7 +518,7 @@ bool tx_memory_pool::remove_stuck_transactions() } catch(const std::exception &e) { - MWARNING("Failed to remove stuck transaction: " << txid); + GULPS_WARN("Failed to remove stuck transaction: ", txid); // ignore error } } @@ -548,7 +549,7 @@ bool tx_memory_pool::get_relayable_transactions(std::list &txs, bool include_ transaction tx; if(!parse_and_validate_tx_from_blob(*bd, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); // continue return true; } @@ -725,7 +726,7 @@ bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector & transaction tx; if(!parse_and_validate_tx_from_blob(*bd, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); // continue return true; } @@ -764,7 +765,7 @@ bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector & { if(!m_blockchain.get_txpool_tx_meta(tx_id_hash, meta)) { - MERROR("Failed to get tx meta from txpool"); + GULPS_ERROR("Failed to get tx meta from txpool"); return false; } if(!meta.relayed) @@ -773,7 +774,7 @@ bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector & } catch(const std::exception &e) { - MERROR("Failed to get tx meta from txpool: " << e.what()); + GULPSF_ERROR("Failed to get tx meta from txpool: {}" , e.what()); return false; } } @@ -796,7 +797,7 @@ bool tx_memory_pool::get_pool_for_rpc(std::vector & transaction tx; if(!parse_and_validate_tx_from_blob(*bd, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); // continue return true; } @@ -973,7 +974,7 @@ bool tx_memory_pool::append_key_images(std::unordered_set &k_ { CHECKED_GET_SPECIFIC_VARIANT(tx.vin[i], const txin_to_key, itk, false); auto i_res = k_images.insert(itk.k_image); - CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " << itk.k_image); + GULPS_CHECK_AND_ASSERT_MES(i_res.second, false, "internal error: key images pool cache - inserted duplicate image in set: " , itk.k_image); } return true; } @@ -994,13 +995,13 @@ void tx_memory_pool::mark_double_spend(const transaction &tx) txpool_tx_meta_t meta; if(!m_blockchain.get_txpool_tx_meta(txid, meta)) { - MERROR("Failed to find tx meta in txpool"); + GULPS_ERROR("Failed to find tx meta in txpool"); // continue, not fatal continue; } if(!meta.double_spend_seen) { - MDEBUG("Marking " << txid << " as double spending " << itk.k_image); + GULPS_LOG_L1("Marking ", txid, " as double spending ", itk.k_image); meta.double_spend_seen = true; try { @@ -1008,7 +1009,7 @@ void tx_memory_pool::mark_double_spend(const transaction &tx) } catch(const std::exception &e) { - MERROR("Failed to update tx meta: " << e.what()); + GULPSF_ERROR("Failed to update tx meta: {}" , e.what()); // continue, not fatal } } @@ -1029,7 +1030,7 @@ std::string tx_memory_pool::print_pool(bool short_format) const cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(*txblob, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); return true; // continue } ss << obj_to_json_str(tx) << std::endl; @@ -1069,7 +1070,7 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t size_t max_total_size = (200 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; std::unordered_set k_images; - LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool"); + GULPSF_LOG_L2("Filling block template, median size {}, {} txes in the pool", median_size, m_txs_by_fee_and_receive_time.size()); LockedTXN lock(m_blockchain); @@ -1078,15 +1079,15 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t txpool_tx_meta_t meta; if(!m_blockchain.get_txpool_tx_meta(tx_hash.second, meta)) { - MERROR(" failed to find tx meta"); + GULPS_ERROR(" failed to find tx meta"); continue; } - LOG_PRINT_L2("Considering " << tx_hash.second << ", size " << meta.blob_size << ", current block size " << total_size << "/" << max_total_size << ", current coinbase " << print_money(best_coinbase)); + GULPSF_LOG_L2("Considering {}, size {}, current block size {}/{}, current coinbase {}", tx_hash.second, meta.blob_size, total_size, max_total_size, print_money(best_coinbase)); // Can not exceed maximum block size if(max_total_size < total_size + meta.blob_size) { - LOG_PRINT_L2(" would exceed maximum block size"); + GULPS_LOG_L2(" would exceed maximum block size"); continue; } @@ -1095,13 +1096,13 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t uint64_t block_reward; if(!get_block_reward(m_blockchain.get_nettype(), median_size, total_size + meta.blob_size + CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, block_reward, height)) { - LOG_PRINT_L2(" would exceed maximum block size"); + GULPS_LOG_L2(" would exceed maximum block size"); continue; } uint64_t coinbase = block_reward + fee + meta.fee; if(coinbase < template_accept_threshold(best_coinbase)) { - LOG_PRINT_L2(" would decrease coinbase to " << print_money(coinbase)); + GULPS_LOG_L2(" would decrease coinbase to ", print_money(coinbase)); continue; } @@ -1109,7 +1110,7 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(txblob, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); continue; } @@ -1126,18 +1127,18 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t } catch(const std::exception &e) { - MERROR("Failed to update tx meta: " << e.what()); + GULPSF_ERROR("Failed to update tx meta: {}" , e.what()); // continue, not fatal } } if(!ready) { - LOG_PRINT_L2(" not ready to go"); + GULPS_LOG_L2(" not ready to go"); continue; } if(have_key_images(k_images, tx)) { - LOG_PRINT_L2(" key images already seen"); + GULPS_LOG_L2(" key images already seen"); continue; } @@ -1146,13 +1147,12 @@ bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t fee += meta.fee; best_coinbase = coinbase; append_key_images(k_images, tx); - LOG_PRINT_L2(" added, new block size " << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase)); + GULPSF_LOG_L2(" added, new block size {}/{}, coinbase {}", total_size, max_total_size, print_money(best_coinbase)); } expected_reward = best_coinbase; - LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, size " - << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase) - << " (including " << print_money(fee) << " in fees)"); + GULPSF_LOG_L2("Block template filled with {} txes, size {}/{}, coinbase {} (including {} in fees)", bl.tx_hashes.size(), + total_size, max_total_size , print_money(best_coinbase), print_money(fee)); return true; } //--------------------------------------------------------------------------------- @@ -1168,12 +1168,12 @@ size_t tx_memory_pool::validate() m_txpool_size += meta.blob_size; if(meta.blob_size > tx_size_limit) { - LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.blob_size << " bytes), removing it from pool"); + GULPSF_LOG_L1("Transaction {}, is too big ({}bytes), removing it from pool", txid, meta.blob_size); remove.insert(txid); } else if(m_blockchain.have_tx(txid)) { - LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool"); + GULPSF_LOG_L1("Transaction {} is in the blockchain, removing it from pool", txid ); remove.insert(txid); } return true; @@ -1192,7 +1192,7 @@ size_t tx_memory_pool::validate() cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(txblob, tx)) { - MERROR("Failed to parse tx from txpool"); + GULPS_ERROR("Failed to parse tx from txpool"); continue; } // remove tx from db first @@ -1202,7 +1202,7 @@ size_t tx_memory_pool::validate() auto sorted_it = find_tx_in_sorted_container(txid); if(sorted_it == m_txs_by_fee_and_receive_time.end()) { - LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!"); + GULPSF_LOG_L1("Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid ); } else { @@ -1212,7 +1212,7 @@ size_t tx_memory_pool::validate() } catch(const std::exception &e) { - MERROR("Failed to remove invalid tx from pool"); + GULPS_ERROR("Failed to remove invalid tx from pool"); // continue } } @@ -1242,12 +1242,12 @@ bool tx_memory_pool::init(size_t max_txpool_size) cryptonote::transaction tx; if(!parse_and_validate_tx_from_blob(*bd, tx)) { - MWARNING("Failed to parse tx from txpool, removing"); + GULPS_WARN("Failed to parse tx from txpool, removing"); remove.push_back(txid); } if(!insert_key_images(tx, meta.kept_by_block)) { - MFATAL("Failed to insert key images from txpool tx"); + GULPS_ERROR("Failed to insert key images from txpool tx"); return false; } m_txs_by_fee_and_receive_time.emplace(std::pair(meta.fee / (double)meta.blob_size, meta.receive_time), txid); @@ -1269,7 +1269,7 @@ bool tx_memory_pool::init(size_t max_txpool_size) } catch(const std::exception &e) { - MWARNING("Failed to remove corrupt transaction: " << txid); + GULPS_WARN("Failed to remove corrupt transaction: ", txid); // ignore error } } diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 69c1e489..3796b204 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/cryptonote_protocol/CMakeLists.txt b/src/cryptonote_protocol/CMakeLists.txt index 0978502d..2610fb24 100644 --- a/src/cryptonote_protocol/CMakeLists.txt +++ b/src/cryptonote_protocol/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -53,5 +53,6 @@ ryo_add_library(cryptonote_protocol ${CRYPTONOTE_PROTOCOL}) target_link_libraries(cryptonote_protocol PUBLIC p2p + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp index 1844f865..f7ec145b 100644 --- a/src/cryptonote_protocol/block_queue.cpp +++ b/src/cryptonote_protocol/block_queue.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -25,8 +25,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn.block_queue" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("blk_queue"); namespace std { @@ -56,7 +57,7 @@ void block_queue::add_blocks(uint64_t height, std::list 0, "Empty span"); + GULPS_CHECK_AND_ASSERT_THROW_MES(nblocks > 0, "Empty span"); boost::unique_lock lock(mutex); blocks.insert(span(height, nblocks, connection_id, time)); } @@ -136,9 +137,9 @@ uint64_t block_queue::get_max_block_height() const void block_queue::print() const { boost::unique_lock lock(mutex); - MDEBUG("Block queue has " << blocks.size() << " spans"); + GULPSF_LOG_L1("Block queue has {} spans", blocks.size() ); for(const auto &span : blocks) - MDEBUG(" " << span.start_block_height << " - " << (span.start_block_height + span.nblocks - 1) << " (" << span.nblocks << ") - " << (is_blockchain_placeholder(span) ? "blockchain" : span.blocks.empty() ? "scheduled" : "filled ") << " " << span.connection_id << " (" << ((unsigned)(span.rate * 10 / 1024.f)) / 10.f << " kB/s)"); + GULPSF_LOG_L1(" {} - {} ({}) - {} {} ({} kB/s)", span.start_block_height, (span.start_block_height + span.nblocks - 1), span.nblocks, (is_blockchain_placeholder(span) ? "blockchain" : span.blocks.empty() ? "scheduled" : "filled ") , boost::uuids::to_string(span.connection_id), ((unsigned)(span.rate * 10 / 1024.f)) / 10.f); } std::string block_queue::get_overview() const @@ -172,7 +173,7 @@ std::pair block_queue::reserve_span(uint64_t first_block_hei if(last_block_height < first_block_height || max_blocks == 0) { - MDEBUG("reserve_span: early out: first_block_height " << first_block_height << ", last_block_height " << last_block_height << ", max_blocks " << max_blocks); + GULPSF_LOG_L1("reserve_span: early out: first_block_height {}, last_block_height {}, max_blocks {}", first_block_height , last_block_height , max_blocks); return std::make_pair(0, 0); } @@ -193,7 +194,7 @@ std::pair block_queue::reserve_span(uint64_t first_block_hei } if(span_length == 0) return std::make_pair(0, 0); - MDEBUG("Reserving span " << span_start_height << " - " << (span_start_height + span_length - 1) << " for " << connection_id); + GULPSF_LOG_L1("Reserving span {} - {} for {}", span_start_height , (span_start_height + span_length - 1) , boost::uuids::to_string(connection_id)); add_blocks(span_start_height, span_length, connection_id, time); set_span_hashes(span_start_height, connection_id, hashes); return std::make_pair(span_start_height, span_length); @@ -219,7 +220,7 @@ std::pair block_queue::get_start_gap_span() const uint64_t first_span_height = i->start_block_height; if(first_span_height <= current_height + 1) return std::make_pair(0, 0); - MDEBUG("Found gap at start of spans: last blockchain block height " << current_height << ", first span's block height " << first_span_height); + GULPSF_LOG_L1("Found gap at start of spans: last blockchain block height {}, first span's block height {}", current_height , first_span_height); print(); return std::make_pair(current_height + 1, first_span_height - current_height - 1); } @@ -393,7 +394,7 @@ float block_queue::get_speed(const boost::uuids::uuid &connection_id) const return 1.0f; // everything dead ? Can't happen, but let's trap anyway const float speed = conn_rate / best_rate; - MTRACE(" Relative speed for " << connection_id << ": " << speed << " (" << conn_rate << "/" << best_rate); + GULPSF_LOG_L2(" Relative speed for {}: {} ({}/{})", boost::uuids::to_string(connection_id) , speed , conn_rate , best_rate); return speed; } diff --git a/src/cryptonote_protocol/block_queue.h b/src/cryptonote_protocol/block_queue.h index b8f3fd3c..bcd830a1 100644 --- a/src/cryptonote_protocol/block_queue.h +++ b/src/cryptonote_protocol/block_queue.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -27,8 +27,7 @@ #include #include "crypto/hash.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn.block_queue" + namespace cryptonote { diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 3e6d6d6a..2e679b9d 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -67,7 +67,7 @@ struct connection_info uint64_t height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(connection_info) KV_SERIALIZE(incoming) KV_SERIALIZE(localhost) KV_SERIALIZE(local_ip) @@ -97,9 +97,24 @@ struct connection_info /************************************************************************/ struct block_complete_entry { + block_complete_entry(blobdata block, std::list txs) : block(block), txs(txs) {} + blobdata block; std::list txs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(block_complete_entry) + KV_SERIALIZE(block) + KV_SERIALIZE(txs) + END_KV_SERIALIZE_MAP() +}; + +// As far as epee is concerned, those two are interchangeable +struct block_complete_entry_v +{ + block_complete_entry_v(blobdata block, std::vector txs) : block(block), txs(txs) {} + + blobdata block; + std::vector txs; + BEGIN_KV_SERIALIZE_MAP(block_complete_entry_v) KV_SERIALIZE(block) KV_SERIALIZE(txs) END_KV_SERIALIZE_MAP() @@ -117,7 +132,7 @@ struct NOTIFY_NEW_BLOCK block_complete_entry b; uint64_t current_blockchain_height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(b) KV_SERIALIZE(current_blockchain_height) END_KV_SERIALIZE_MAP() @@ -135,7 +150,7 @@ struct NOTIFY_NEW_TRANSACTIONS { std::list txs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(txs) END_KV_SERIALIZE_MAP() }; @@ -152,7 +167,7 @@ struct NOTIFY_REQUEST_GET_OBJECTS std::list txs; std::list blocks; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(txs) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(blocks) END_KV_SERIALIZE_MAP() @@ -170,7 +185,7 @@ struct NOTIFY_RESPONSE_GET_OBJECTS std::list missed_ids; uint64_t current_blockchain_height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(txs) KV_SERIALIZE(blocks) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(missed_ids) @@ -186,7 +201,7 @@ struct CORE_SYNC_DATA crypto::hash top_id; uint8_t top_version; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(CORE_SYNC_DATA) KV_SERIALIZE(current_height) KV_SERIALIZE(cumulative_difficulty) KV_SERIALIZE_VAL_POD_AS_BLOB(top_id) @@ -202,7 +217,7 @@ struct NOTIFY_REQUEST_CHAIN { std::list block_ids; /*IDs of the first 10 blocks are sequential, next goes with pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) END_KV_SERIALIZE_MAP() }; @@ -219,7 +234,7 @@ struct NOTIFY_RESPONSE_CHAIN_ENTRY uint64_t cumulative_difficulty; std::list m_block_ids; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(start_height) KV_SERIALIZE(total_height) KV_SERIALIZE(cumulative_difficulty) @@ -240,7 +255,7 @@ struct NOTIFY_NEW_FLUFFY_BLOCK block_complete_entry b; uint64_t current_blockchain_height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(b) KV_SERIALIZE(current_blockchain_height) END_KV_SERIALIZE_MAP() @@ -260,7 +275,7 @@ struct NOTIFY_REQUEST_FLUFFY_MISSING_TX uint64_t current_blockchain_height; std::vector missing_tx_indices; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_VAL_POD_AS_BLOB(block_hash) KV_SERIALIZE(current_blockchain_height) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(missing_tx_indices) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index 12edd08e..36b98af1 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief This is the place to implement our handlers for protocol network actions, e.g. for ratelimit for download-requests -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,6 +20,7 @@ // 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 #include #include @@ -40,7 +41,6 @@ #include "syncobj.h" #include "misc_language.h" -#include "misc_log_ex.h" #include "net/net_utils_base.h" #include "pragma_comp_defs.h" #include @@ -63,8 +63,9 @@ #include "cryptonote_core/cryptonote_core.h" // e.g. for the send_stop_signal() -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.cn" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("cnt_pct_hand_base"); // ################################################################################################ // ################################################################################################ @@ -125,16 +126,16 @@ void cryptonote_protocol_handler_base::handler_response_blocks_now(size_t packet { using namespace epee::net_utils; double delay = 0; // will be calculated - MDEBUG("Packet size: " << packet_size); + GULPSF_LOG_L1("Packet size: {}", packet_size); do { // rate limiting //XXX - /*if (::cryptonote::core::get_is_stopping()) { - MDEBUG("We are stopping - so abort sleep"); + /*if (::cryptonote::core::get_is_stopping()) { + GULPS_LOG_L1("We are stopping - so abort sleep"); return; }*/ - /*if (m_was_shutdown) { - MDEBUG("m_was_shutdown - so abort sleep"); + /*if (m_was_shutdown) { + GULPS_LOG_L1("m_was_shutdown - so abort sleep"); return; }*/ @@ -149,7 +150,7 @@ void cryptonote_protocol_handler_base::handler_response_blocks_now(size_t packet { //delay += rand2*0.1; long int ms = (long int)(delay * 1000); - MDEBUG("Sleeping for " << ms << " ms before packet_size=" << packet_size); // XXX debug sleep + GULPSF_LOG_L1("Sleeping for {} ms before packet_size=", ms, packet_size); // XXX debug sleep boost::this_thread::sleep(boost::posix_time::milliseconds(ms)); // TODO randomize sleeps } } while(delay > 0); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 17feca89..ccc45bd2 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -2,7 +2,7 @@ /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) /// @brief This is the original cryptonote protocol network-events handler, modified by us -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -37,6 +37,8 @@ #include "warnings.h" #include +#include "common/gulps.hpp" + PUSH_WARNINGS DISABLE_VS_WARNINGS(4355) @@ -48,6 +50,7 @@ namespace cryptonote class cryptonote_protocol_handler_base_pimpl; class cryptonote_protocol_handler_base { + GULPS_CAT_MAJOR("cn_pcl_hand"); private: std::unique_ptr mI; @@ -64,6 +67,7 @@ class cryptonote_protocol_handler_base template class t_cryptonote_protocol_handler : public i_cryptonote_protocol, cryptonote_protocol_handler_base { + GULPS_CAT_MAJOR("cn_pcl_hand"); public: typedef cryptonote_connection_context connection_context; typedef core_stat_info stat_info; @@ -143,7 +147,7 @@ class t_cryptonote_protocol_handler : public i_cryptonote_protocol, cryptonote_p template bool post_notify(typename t_parameter::request &arg, cryptonote_connection_context &context) { - LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parameter).name() << " -->"); + GULPSF_LOG_L2("[{}] post {} -->", epee::net_utils::print_connection_context_short(context), typeid(t_parameter).name()); std::string blob; epee::serialization::store_t_to_binary(arg, blob); //handler_response_blocks_now(blob.size()); // XXX @@ -153,7 +157,7 @@ class t_cryptonote_protocol_handler : public i_cryptonote_protocol, cryptonote_p template bool relay_post_notify(typename t_parameter::request &arg, cryptonote_connection_context &exclude_context) { - LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exclude_context) << "] post relay " << typeid(t_parameter).name() << " -->"); + GULPSF_LOG_L2("[{}] post relay {} -->", epee::net_utils::print_connection_context_short(exclude_context), typeid(t_parameter).name()); std::string arg_buff; epee::serialization::store_t_to_binary(arg, arg_buff); return m_p2p->relay_notify_to_all(t_parameter::ID, arg_buff, exclude_context); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index f54588a7..ebb4e8dd 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -2,7 +2,7 @@ /// @author rfree (current maintainer/user in monero.cc project - most of code is from CryptoNote) /// @brief This is the original cryptonote protocol network-events handler, modified by us -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -25,6 +25,7 @@ // (may contain code and/or modifications by other developers) // developer rfree: this code is caller of our new network code, and is modded; e.g. for rate limiting +//IGNORE #include #include #include @@ -34,10 +35,13 @@ #include "net/network_throttle-detail.hpp" #include "profile_tools.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.cn" +#include "common/gulps.hpp" -#define MLOG_P2P_MESSAGE(x) MCINFO("net.p2p.msg", context << x) + + +#define context_str std::string("[" + epee::net_utils::print_connection_context_short(context) + "]") + +#define GULPS_P2P_MESSAGE(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, "p2p", gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) #define BLOCK_QUEUE_NBLOCKS_THRESHOLD 10 // chunks of N blocks #define BLOCK_QUEUE_SIZE_THRESHOLD (100 * 1024 * 1024) // MB @@ -85,15 +89,15 @@ void t_cryptonote_protocol_handler::set_p2p_endpoint(nodetool::i_p2p_end template bool t_cryptonote_protocol_handler::on_callback(cryptonote_connection_context &context) { - LOG_PRINT_CCONTEXT_L2("callback fired"); - CHECK_AND_ASSERT_MES_CC(context.m_callback_request_count > 0, false, "false callback fired, but context.m_callback_request_count=" << context.m_callback_request_count); + GULPS_LOG_L1(context_str, " callback fired"); + GULPS_CHECK_AND_ASSERT_MES_CONTEXT(context.m_callback_request_count > 0, false, "false callback fired, but context.m_callback_request_count=", context.m_callback_request_count); --context.m_callback_request_count; if(context.m_state == cryptonote_connection_context::state_synchronizing) { NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size()); + GULPSF_LOG_L1("{} -->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}", context_str, r.block_ids.size()); post_notify(r, context); } else if(context.m_state == cryptonote_connection_context::state_standby) @@ -132,7 +136,7 @@ void t_cryptonote_protocol_handler::log_connections() << std::setw(14) << "Down(now)" << std::setw(10) << "Up (kB/s)" << std::setw(13) << "Up(now)" - << ENDL; + << "\n"; m_p2p->for_each_connection([&](const connection_context &cntxt, nodetool::peerid_type peer_id, uint32_t support_flags) { bool local_ip = cntxt.m_remote_address.is_local(); @@ -149,7 +153,7 @@ void t_cryptonote_protocol_handler::log_connections() << std::setw(13) << std::fixed << cntxt.m_current_speed_up / 1024 << (local_ip ? "[LAN]" : "") << std::left << (cntxt.m_remote_address.is_loopback() ? "[LOCALHOST]" : "") // 127.0.0.1 - << ENDL; + << "\n"; if(connection_time > 1) { @@ -162,14 +166,14 @@ void t_cryptonote_protocol_handler::log_connections() return true; }); - ss << ENDL + ss << "\n" << std::setw(125) << " " << std::setw(12) << down_sum << std::setw(14) << down_curr_sum << std::setw(10) << up_sum << std::setw(13) << up_curr_sum - << ENDL; - LOG_PRINT_L0("Connections: " << ENDL << ss.str()); + << "\n"; + GULPS_PRINT("Connections:\n", ss.str()); } //------------------------------------------------------------------------------------------------------------------------ // Returns a list of connection_info objects describing each open p2p connection @@ -258,7 +262,7 @@ bool t_cryptonote_protocol_handler::process_payload_sync_data(const CORE if(version >= 6 && version != hshd.top_version) { if(version < hshd.top_version && version == m_core.get_ideal_hard_fork_version()) - MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think (" << (unsigned)hshd.top_version << " for " << (hshd.current_height - 1) << " instead of " << (unsigned)version << ") - we may be forked from the network and a software upgrade may be needed"); + GULPSF_CAT_WARN("global", "{} peer claims higher version that we think ({} for {} instead of {}) - we may be forked from the network and a software upgrade may be needed", context_str, (unsigned)hshd.top_version, (hshd.current_height - 1), (unsigned)version); return false; } } @@ -288,17 +292,22 @@ bool t_cryptonote_protocol_handler::process_payload_sync_data(const CORE uint64_t max_block_height = std::max(hshd.current_height, m_core.get_current_blockchain_height()); uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1; uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0; - MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height - << " [Your node is " << abs_diff << " blocks (" << ((abs_diff - diff_v2) / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)) + (diff_v2 / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)) << " days) " - << (0 <= diff ? std::string("behind") : std::string("ahead")) - << "] " << ENDL << "SYNCHRONIZATION started"); + if(is_inital) + GULPSF_GLOBAL_PRINT("\n{} Sync data returned a new top block candidate: {} -> {} [Your node is {} blocks ({} days {})]\nSYNCHRONIZATION started", context_str, m_core.get_current_blockchain_height(), + hshd.current_height, abs_diff, ((abs_diff - diff_v2) / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)) + (diff_v2 / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)), + (0 <= diff ? std::string("behind") : std::string("ahead"))); + else + GULPSF_GLOBAL_PRINT("\n{} Sync data returned a new top block candidate: {} -> {} [Your node is {} blocks ({} days {})]\nSYNCHRONIZATION started", context_str, m_core.get_current_blockchain_height(), + hshd.current_height, abs_diff, ((abs_diff - diff_v2) / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)) + (diff_v2 / (24 * 60 * 60 / common_config::DIFFICULTY_TARGET)), + (0 <= diff ? std::string("behind") : std::string("ahead"))); + if(hshd.current_height >= m_core.get_current_blockchain_height() + 5) // don't switch to unsafe mode just for a few blocks m_core.safesyncmode(false); } - LOG_PRINT_L1("Remote blockchain height: " << hshd.current_height << ", id: " << hshd.top_id); + GULPSF_INFO("Remote blockchain height: {}, id: {}", hshd.current_height , hshd.top_id); context.m_state = cryptonote_connection_context::state_synchronizing; //let the socket to send response to handshake, but request callback, to let send request data after response - LOG_PRINT_CCONTEXT_L2("requesting callback"); + GULPS_LOG_L1( context_str, " requesting callback"); ++context.m_callback_request_count; m_p2p->request_callback(context); return true; @@ -326,12 +335,12 @@ bool t_cryptonote_protocol_handler::get_payload_sync_data(blobdata &data template int t_cryptonote_protocol_handler::handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_NEW_BLOCK (" << arg.b.txs.size() << " txes)"); + GULPS_P2P_MESSAGE("Received NOTIFY_NEW_BLOCK ({} txes)", arg.b.txs.size() ); if(context.m_state != cryptonote_connection_context::state_normal) return 1; if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks { - LOG_DEBUG_CC(context, "Received new block while syncing, ignored"); + GULPS_LOG_L1(context_str," Received new block while syncing, ignored"); return 1; } m_core.pause_mine(); @@ -344,7 +353,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_block(int command, m_core.handle_incoming_tx(*tx_blob_it, tvc, true, true, false); if(tvc.m_verifivation_failed) { - LOG_PRINT_CCONTEXT_L1("Block verification failed: transaction verification failed, dropping connection"); + GULPS_INFO( context_str, " Block verification failed: transaction verification failed, dropping connection"); drop_connection(context, false, false); m_core.cleanup_handle_incoming_blocks(); m_core.resume_mine(); @@ -356,14 +365,14 @@ int t_cryptonote_protocol_handler::handle_notify_new_block(int command, m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block if(!m_core.cleanup_handle_incoming_blocks(true)) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_PRINT( context_str, " Failure in cleanup_handle_incoming_blocks"); m_core.resume_mine(); return 1; } m_core.resume_mine(); if(bvc.m_verifivation_failed) { - LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); + GULPS_PRINT( context_str, " Block verification failed, dropping connection"); drop_connection(context, true, false); return 1; } @@ -377,7 +386,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_block(int command, context.m_state = cryptonote_connection_context::state_synchronizing; NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size()); + GULPSF_LOG_L1("{} -->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}", context_str, r.block_ids.size()); post_notify(r, context); } @@ -387,12 +396,12 @@ int t_cryptonote_protocol_handler::handle_notify_new_block(int command, template int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_NEW_FLUFFY_BLOCK (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)"); + GULPS_P2P_MESSAGE("Received NOTIFY_NEW_FLUFFY_BLOCK (height {}, {} txes)", arg.current_blockchain_height , arg.b.txs.size() ); if(context.m_state != cryptonote_connection_context::state_normal) return 1; if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks { - LOG_DEBUG_CC(context, "Received new block while syncing, ignored"); + GULPS_LOG_L1( context_str, " Received new block while syncing, ignored"); return 1; } @@ -408,12 +417,10 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co // What we asked for != to what we received .. if(context.m_requested_objects.size() != arg.b.txs.size()) { - LOG_ERROR_CCONTEXT( - "NOTIFY_NEW_FLUFFY_BLOCK -> request/response mismatch, " - << "block = " << epee::string_tools::pod_to_hex(get_blob_hash(arg.b.block)) - << ", requested = " << context.m_requested_objects.size() - << ", received = " << new_block.tx_hashes.size() - << ", dropping connection"); + GULPSF_LOG_ERROR("{} NOTIFY_NEW_FLUFFY_BLOCK -> request/response mismatch, block = {}, requested = {}, received = {}, dropping connection", context_str, epee::string_tools::pod_to_hex(get_blob_hash(arg.b.block)) + , context.m_requested_objects.size() + , new_block.tx_hashes.size() + ); drop_connection(context, false, false); m_core.resume_mine(); @@ -442,9 +449,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co { if(!get_transaction_hash(tx, tx_hash)) { - LOG_PRINT_CCONTEXT_L1( - "NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed" - << ", dropping connection"); + GULPS_INFO(context_str, " NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed, dropping connection"); drop_connection(context, false, false); m_core.resume_mine(); @@ -453,10 +458,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co } catch(...) { - LOG_PRINT_CCONTEXT_L1( - "NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed" - << ", exception thrown" - << ", dropping connection"); + GULPS_INFO( context_str, " NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed, exception thrown, dropping connection"); drop_connection(context, false, false); m_core.resume_mine(); @@ -475,10 +477,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co auto req_tx_it = context.m_requested_objects.find(tx_hash); if(req_tx_it == context.m_requested_objects.end()) { - LOG_ERROR_CCONTEXT( - "Peer sent wrong transaction (NOTIFY_NEW_FLUFFY_BLOCK): " - << "transaction with id = " << tx_hash << " wasn't requested, " - << "dropping connection"); + GULPSF_LOG_ERROR("{} Peer sent wrong transaction (NOTIFY_NEW_FLUFFY_BLOCK): transaction with id = {} wasn't requested, dropping connection", context_str, tx_hash ); drop_connection(context, false, false); m_core.resume_mine(); @@ -492,11 +491,11 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co // sent in our pool, so don't verify again.. if(!m_core.pool_has_tx(tx_hash)) { - MDEBUG("Incoming tx " << tx_hash << " not in pool, adding"); + GULPSF_LOG_L1("Incoming tx {} not in pool, adding", tx_hash ); cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc); if(!m_core.handle_incoming_tx(tx_blob, tvc, true, true, false) || tvc.m_verifivation_failed) { - LOG_PRINT_CCONTEXT_L1("Block verification failed: transaction verification failed, dropping connection"); + GULPS_INFO( context_str, " Block verification failed: transaction verification failed, dropping connection"); drop_connection(context, false, false); m_core.resume_mine(); return 1; @@ -512,10 +511,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co } else { - LOG_ERROR_CCONTEXT( - "sent wrong tx: failed to parse and validate transaction: " - << epee::string_tools::buff_to_hex_nodelimer(tx_blob) - << ", dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong tx: failed to parse and validate transaction: {}, dropping connection", context_str, epee::string_tools::buff_to_hex_nodelimer(tx_blob)); drop_connection(context, false, false); m_core.resume_mine(); @@ -529,11 +525,8 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co // ones we received. if(context.m_requested_objects.size()) { - MERROR( - "NOTIFY_NEW_FLUFFY_BLOCK: peer sent the number of transaction requested" - << ", but not the actual transactions requested" - << ", context.m_requested_objects.size() = " << context.m_requested_objects.size() - << ", dropping connection"); + GULPSF_LOG_ERROR("NOTIFY_NEW_FLUFFY_BLOCK: peer sent the number of transaction requested, but not the actual transactions requested, context.m_requested_objects.size() = {}, dropping connection" + , context.m_requested_objects.size()); drop_connection(context, false, false); m_core.resume_mine(); @@ -562,14 +555,14 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co } else { - MERROR("1 tx requested, none not found, but " << txes.size() << " returned"); + GULPSF_LOG_L1("1 tx requested, none not found, but {} returned", txes.size() ); m_core.resume_mine(); return 1; } } else { - MDEBUG("Tx " << tx_hash << " not found in pool"); + GULPSF_LOG_L1("Tx {} not found in pool", tx_hash ); need_tx_indices.push_back(tx_idx); } } @@ -580,9 +573,9 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co if(!need_tx_indices.empty()) // drats, we don't have everything.. { // request non-mempool txs - MDEBUG("We are missing " << need_tx_indices.size() << " txes for this fluffy block"); + GULPSF_LOG_L1("We are missing {} txes for this fluffy block", need_tx_indices.size() ); for(auto txidx : need_tx_indices) - MDEBUG(" tx " << new_block.tx_hashes[txidx]); + GULPSF_LOG_L1(" tx {}", new_block.tx_hashes[txidx]); NOTIFY_REQUEST_FLUFFY_MISSING_TX::request missing_tx_req; missing_tx_req.block_hash = get_block_hash(new_block); missing_tx_req.current_blockchain_height = arg.current_blockchain_height; @@ -593,7 +586,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co } else // whoo-hoo we've got em all .. { - MDEBUG("We have all needed txes for this fluffy block"); + GULPS_LOG_L1("We have all needed txes for this fluffy block"); block_complete_entry b; b.block = arg.b.block; @@ -607,7 +600,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block if(!m_core.cleanup_handle_incoming_blocks(true)) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_PRINT( context_str, " Failure in cleanup_handle_incoming_blocks"); m_core.resume_mine(); return 1; } @@ -615,7 +608,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co if(bvc.m_verifivation_failed) { - LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection"); + GULPS_PRINT( context_str, " Block verification failed, dropping connection"); drop_connection(context, true, false); return 1; } @@ -632,17 +625,15 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co context.m_state = cryptonote_connection_context::state_synchronizing; NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); m_core.get_short_chain_history(r.block_ids); - LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size()); + GULPSF_LOG_L1("{} -->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}", context_str, r.block_ids.size()); post_notify(r, context); } } } else { - LOG_ERROR_CCONTEXT( - "sent wrong block: failed to parse and validate block: " - << epee::string_tools::buff_to_hex_nodelimer(arg.b.block) - << ", dropping connection"); + GULPSF_LOG_ERROR("sent wrong block: failed to parse and validate block: {}, dropping connection", epee::string_tools::buff_to_hex_nodelimer(arg.b.block) + ); m_core.resume_mine(); drop_connection(context, false, false); @@ -656,7 +647,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_fluffy_block(int co template int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_FLUFFY_MISSING_TX (" << arg.missing_tx_indices.size() << " txes), block hash " << arg.block_hash); + GULPS_P2P_MESSAGE("Received NOTIFY_REQUEST_FLUFFY_MISSING_TX ({} txes), block hash {}", arg.missing_tx_indices.size() , arg.block_hash); std::list> local_blocks; std::list local_txs; @@ -664,7 +655,7 @@ int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int block b; if(!m_core.get_block_by_hash(arg.block_hash, b)) { - LOG_ERROR_CCONTEXT("failed to find block: " << arg.block_hash << ", dropping connection"); + GULPSF_LOG_ERROR("{} failed to find block: {}, dropping connection", context_str, arg.block_hash ); drop_connection(context, false, false); return 1; } @@ -677,17 +668,14 @@ int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int { if(tx_idx < b.tx_hashes.size()) { - MDEBUG(" tx " << b.tx_hashes[tx_idx]); + GULPSF_LOG_L1(" tx {}", b.tx_hashes[tx_idx]); txids.push_back(b.tx_hashes[tx_idx]); } else { - LOG_ERROR_CCONTEXT( - "Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX" - << ", request is asking for a tx whose index is out of bounds " - << ", tx index = " << tx_idx << ", block tx count " << b.tx_hashes.size() - << ", block_height = " << arg.current_blockchain_height - << ", dropping connection"); + GULPSF_LOG_ERROR("{} Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, request is asking for a tx whose index is out of bounds , tx index = {}, block tx count {}, block_height = {}, dropping connection", context_str, tx_idx , b.tx_hashes.size() + , arg.current_blockchain_height); + drop_connection(context, false, false); return 1; @@ -698,16 +686,13 @@ int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int std::list missed; if(!m_core.get_transactions(txids, txs, missed)) { - LOG_ERROR_CCONTEXT("Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, " - << "failed to get requested transactions"); + GULPS_LOG_ERROR( context_str, " Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, failed to get requested transactions"); drop_connection(context, false, false); return 1; } if(!missed.empty() || txs.size() != txids.size()) { - LOG_ERROR_CCONTEXT("Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, " - << missed.size() << " requested transactions not found" - << ", dropping connection"); + GULPSF_LOG_ERROR("{} Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX, {} requested transactions not found, dropping connection", context_str, missed.size() ); drop_connection(context, false, false); return 1; } @@ -717,10 +702,7 @@ int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int fluffy_response.b.txs.push_back(t_serializable_object_to_blob(tx)); } - LOG_PRINT_CCONTEXT_L2( - "-->>NOTIFY_RESPONSE_FLUFFY_MISSING_TX: " - << ", txs.size()=" << fluffy_response.b.txs.size() - << ", rsp.current_blockchain_height=" << fluffy_response.current_blockchain_height); + GULPSF_LOG_L1("{} -->>NOTIFY_RESPONSE_FLUFFY_MISSING_TX: , txs.size()={}, rsp.current_blockchain_height={}", context_str, fluffy_response.b.txs.size() , fluffy_response.current_blockchain_height); post_notify(fluffy_response, context); return 1; @@ -729,7 +711,7 @@ int t_cryptonote_protocol_handler::handle_request_fluffy_missing_tx(int template int t_cryptonote_protocol_handler::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS (" << arg.txs.size() << " txes)"); + GULPS_P2P_MESSAGE("Received NOTIFY_NEW_TRANSACTIONS ({} txes)", arg.txs.size() ); if(context.m_state != cryptonote_connection_context::state_normal) return 1; @@ -738,7 +720,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_transactions(int co // long block before replying if(!is_synchronized()) { - LOG_DEBUG_CC(context, "Received new tx while syncing, ignored"); + GULPS_LOG_L1( context_str, " Received new tx while syncing, ignored"); return 1; } @@ -748,7 +730,7 @@ int t_cryptonote_protocol_handler::handle_notify_new_transactions(int co m_core.handle_incoming_tx(*tx_blob_it, tvc, false, true, false); if(tvc.m_verifivation_failed) { - LOG_PRINT_CCONTEXT_L1("Tx verification failed, dropping connection"); + GULPS_INFO( context_str, " Tx verification failed, dropping connection"); drop_connection(context, false, false); return 1; } @@ -770,16 +752,15 @@ int t_cryptonote_protocol_handler::handle_notify_new_transactions(int co template int t_cryptonote_protocol_handler::handle_request_get_objects(int command, NOTIFY_REQUEST_GET_OBJECTS::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_GET_OBJECTS (" << arg.blocks.size() << " blocks, " << arg.txs.size() << " txes)"); + GULPS_P2P_MESSAGE("Received NOTIFY_REQUEST_GET_OBJECTS ({} blocks, {} txes)", arg.blocks.size() , arg.txs.size() ); NOTIFY_RESPONSE_GET_OBJECTS::request rsp; if(!m_core.handle_get_objects(arg, rsp, context)) { - LOG_ERROR_CCONTEXT("failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection"); + GULPS_ERROR( context_str," failed to handle request NOTIFY_REQUEST_GET_OBJECTS, dropping connection"); drop_connection(context, false, false); return 1; } - LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()=" << rsp.blocks.size() << ", txs.size()=" << rsp.txs.size() - << ", rsp.m_current_blockchain_height=" << rsp.current_blockchain_height << ", missed_ids.size()=" << rsp.missed_ids.size()); + GULPSF_LOG_L1("{} -->>NOTIFY_RESPONSE_GET_OBJECTS: blocks.size()={}, txs.size()={}, rsp.m_current_blockchain_height={}, missed_ids.size()={}", context_str, rsp.blocks.size() , rsp.txs.size() , rsp.current_blockchain_height , rsp.missed_ids.size()); post_notify(rsp, context); //handler_response_blocks_now(sizeof(rsp)); // XXX //handler_response_blocks_now(200); @@ -793,7 +774,7 @@ double t_cryptonote_protocol_handler::get_avg_block_size() CRITICAL_REGION_LOCAL(m_buffer_mutex); if(m_avg_buffer.empty()) { - MWARNING("m_avg_buffer.size() == 0"); + GULPS_WARN("m_avg_buffer.size() == 0"); return 500; } double avg = 0; @@ -805,7 +786,7 @@ double t_cryptonote_protocol_handler::get_avg_block_size() template int t_cryptonote_protocol_handler::handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_RESPONSE_GET_OBJECTS (" << arg.blocks.size() << " blocks, " << arg.txs.size() << " txes)"); + GULPS_P2P_MESSAGE("Received NOTIFY_RESPONSE_GET_OBJECTS ({} blocks, {} txes)", arg.blocks.size() , arg.txs.size() ); // calculate size of request size_t size = 0; @@ -829,7 +810,7 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma CRITICAL_REGION_LOCAL(m_buffer_mutex); m_avg_buffer.push_back(size); } - MDEBUG(context << " downloaded " << size << " bytes worth of blocks"); + GULPSF_LOG_L1("{} downloaded {} bytes worth of blocks", context_str, size); /*using namespace boost::chrono; auto point = steady_clock::now(); @@ -840,8 +821,8 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma if(context.m_last_response_height > arg.current_blockchain_height) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height=" << arg.current_blockchain_height - << " < m_last_response_height=" << context.m_last_response_height << ", dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong NOTIFY_HAVE_OBJECTS: arg.m_current_blockchain_height={} < m_last_response_height={}, dropping connection", context_str, arg.current_blockchain_height + , context.m_last_response_height ); drop_connection(context, false, false); return 1; } @@ -864,15 +845,13 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma if(!parse_and_validate_block_from_blob(block_entry.block, b)) { - LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: " - << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong block: failed to parse and validate block: {}, dropping connection", context_str, epee::string_tools::buff_to_hex_nodelimer(block_entry.block) ); drop_connection(context, false, false); return 1; } if(b.miner_tx.vin.size() != 1 || b.miner_tx.vin.front().type() != typeid(txin_gen)) { - LOG_ERROR_CCONTEXT("sent wrong block: block: miner tx does not have exactly one txin_gen input" - << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong block: block: miner tx does not have exactly one txin_gen input{}, dropping connection", context_str, epee::string_tools::buff_to_hex_nodelimer(block_entry.block) ); drop_connection(context, false, false); return 1; } @@ -883,15 +862,16 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma auto req_it = context.m_requested_objects.find(block_hash); if(req_it == context.m_requested_objects.end()) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) - << " wasn't requested, dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id={} wasn't requested, dropping connection", context_str, epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) + ); drop_connection(context, false, false); return 1; } if(b.tx_hashes.size() != block_entry.txs.size()) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) - << ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection"); + GULPSF_LOG_ERROR("{} sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id={}, tx_hashes.size()={} mismatch with block_complete_entry.m_txs.size()={}, dropping connection" + , context_str, epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block)) + , b.tx_hashes.size() , block_entry.txs.size()); drop_connection(context, false, false); return 1; } @@ -902,8 +882,7 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma if(context.m_requested_objects.size()) { - MERROR("returned not all requested objects (context.m_requested_objects.size()=" - << context.m_requested_objects.size() << "), dropping connection"); + GULPSF_LOG_L1("returned not all requested objects (context.m_requested_objects.size()={}), dropping connection", context.m_requested_objects.size() ); drop_connection(context, false, false); return 1; } @@ -913,19 +892,19 @@ int t_cryptonote_protocol_handler::handle_response_get_objects(int comma if(m_core.have_block(last_block_hash)) { const uint64_t subchain_height = start_height + arg.blocks.size(); - LOG_DEBUG_CC(context, "These are old blocks, ignoring: blocks " << start_height << " - " << (subchain_height - 1) << ", blockchain height " << m_core.get_current_blockchain_height()); + GULPSF_LOG_L1("{} These are old blocks, ignoring: blocks {} - {}, blockchain height {}", context_str, start_height , (subchain_height - 1) , m_core.get_current_blockchain_height()); m_block_queue.remove_spans(context.m_connection_id, start_height); goto skip; } { - MLOG_YELLOW(el::Level::Debug, context << " Got NEW BLOCKS inside of " << __FUNCTION__ << ": size: " << arg.blocks.size() - << ", blocks: " << start_height << " - " << (start_height + arg.blocks.size() - 1)); + GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_YELLOW, "{} Got NEW BLOCKS inside of {}: size: {}, blocks: {} - {}", + context_str, __FUNCTION__, arg.blocks.size(), start_height, (start_height + arg.blocks.size() - 1)); // add that new span to the block queue const boost::posix_time::time_duration dt = now - context.m_last_request_time; const float rate = size * 1e6 / (dt.total_microseconds() + 1); - MDEBUG(context << " adding span: " << arg.blocks.size() << " at height " << start_height << ", " << dt.total_microseconds() / 1e6 << " seconds, " << (rate / 1e3) << " kB/s, size now " << (m_block_queue.get_data_size() + blocks_size) / 1048576.f << " MB"); + GULPSF_LOG_L1("{} adding span: {} at height {}, {} seconds, {} kB/s, size now {} MB", context_str, arg.blocks.size() , start_height , dt.total_microseconds() / 1e6 , (rate / 1e3) , (m_block_queue.get_data_size() + blocks_size) / 1048576.f ); m_block_queue.add_blocks(start_height, arg.blocks, context.m_connection_id, rate, blocks_size); context.m_last_known_hash = last_block_hash; @@ -953,10 +932,10 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec const boost::unique_lock sync{m_sync_lock, boost::try_to_lock}; if(!sync.owns_lock()) { - MINFO("Failed to lock m_sync_lock, going back to download"); + GULPS_INFO("Failed to lock m_sync_lock, going back to download"); goto skip; } - MDEBUG(context << " lock m_sync_lock, adding blocks to chain..."); + GULPS_LOG_L1( context_str," lock m_sync_lock, adding blocks to chain..."); { m_core.pause_mine(); @@ -971,15 +950,14 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec boost::uuids::uuid span_connection_id; if(!m_block_queue.get_next_span(start_height, blocks, span_connection_id)) { - MDEBUG(context << " no next span found, going back to download"); + GULPS_LOG_L1( context_str," no next span found, going back to download"); break; } - MDEBUG(context << " next span in the queue has blocks " << start_height << "-" << (start_height + blocks.size() - 1) - << ", we need " << previous_height); + GULPSF_LOG_L1("{} next span in the queue has blocks {}-{}, we need {}", context_str, start_height , (start_height + blocks.size() - 1) , previous_height); if(blocks.empty()) { - MERROR("Next span has no blocks"); + GULPS_ERROR("Next span has no blocks"); m_block_queue.remove_spans(span_connection_id, start_height); break; } @@ -987,7 +965,7 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec block new_block; if(!parse_and_validate_block_from_blob(blocks.front().block, new_block)) { - MERROR("Failed to parse block, but it should already have been parsed"); + GULPS_ERROR("Failed to parse block, but it should already have been parsed"); m_block_queue.remove_spans(span_connection_id, start_height); break; } @@ -1004,7 +982,7 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec { // this can happen if a connection was sicced onto a late span, if it did not have those blocks, // since we don't know that at the sic time - LOG_ERROR_CCONTEXT("Got block with unknown parent which was not requested - querying block hashes"); + GULPS_ERROR( context_str, " Got block with unknown parent which was not requested - querying block hashes"); m_block_queue.remove_spans(span_connection_id, start_height); context.m_needed_objects.clear(); context.m_last_response_height = 0; @@ -1012,7 +990,7 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec } // parent was requested, so we wait for it to be retrieved - MINFO(context << " parent was requested, we'll get back to it"); + GULPS_INFO(" parent was requested, we'll get back to it"); break; } @@ -1038,7 +1016,7 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec m_core.handle_incoming_txs(block_entry.txs, tvc, true, true, false); if(tvc.size() != block_entry.txs.size()) { - LOG_ERROR_CCONTEXT("Internal error: tvc.size() != block_entry.txs.size()"); + GULPS_ERROR( context_str, " Internal error: tvc.size() != block_entry.txs.size()"); return 1; } std::list::const_iterator it = block_entry.txs.begin(); @@ -1047,16 +1025,15 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec if(tvc[i].m_verifivation_failed) { if(!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context &context, nodetool::peerid_type peer_id, uint32_t f) -> bool { - LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, tx_id = " - << epee::string_tools::pod_to_hex(get_blob_hash(*it)) << ", dropping connection"); + GULPSF_LOG_ERROR("{} transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, tx_id = {}, dropping connection", context_str, epee::string_tools::pod_to_hex(get_blob_hash(*it)) ); drop_connection(context, false, true); return 1; })) - LOG_ERROR_CCONTEXT("span connection id not found"); + GULPS_ERROR( context_str, " span connection id not found"); if(!m_core.cleanup_handle_incoming_blocks()) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_ERROR( context_str," Failure in cleanup_handle_incoming_blocks"); return 1; } // in case the peer had dropped beforehand, remove the span anyway so other threads can wake up and get it @@ -1077,15 +1054,15 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec if(bvc.m_verifivation_failed) { if(!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context &context, nodetool::peerid_type peer_id, uint32_t f) -> bool { - LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection"); + GULPS_INFO( context_str, " Block verification failed, dropping connection"); drop_connection(context, true, true); return 1; })) - LOG_ERROR_CCONTEXT("span connection id not found"); + GULPS_ERROR( context_str, " span connection id not found"); if(!m_core.cleanup_handle_incoming_blocks()) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_ERROR( context_str, " Failure in cleanup_handle_incoming_blocks"); return 1; } @@ -1096,15 +1073,15 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec if(bvc.m_marked_as_orphaned) { if(!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context &context, nodetool::peerid_type peer_id, uint32_t f) -> bool { - LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection"); + GULPS_INFO( context_str, " Block received at sync phase was marked as orphaned, dropping connection"); drop_connection(context, true, true); return 1; })) - LOG_ERROR_CCONTEXT("span connection id not found"); + GULPS_ERROR( context_str, " span connection id not found"); if(!m_core.cleanup_handle_incoming_blocks()) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_ERROR( context_str, " Failure in cleanup_handle_incoming_blocks"); return 1; } @@ -1118,11 +1095,12 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec } // each download block - MCINFO("sync-info", "Block process time (" << blocks.size() << " blocks, " << num_txs << " txs): " << block_process_time_full + transactions_process_time_full << " (" << transactions_process_time_full << "/" << block_process_time_full << ") ms"); + GULPSF_CAT_INFO("sync-info", "Block process time ({} blocks P{} txs):{} ({}/{}) ms", blocks.size(), num_txs, block_process_time_full + transactions_process_time_full, transactions_process_time_full, block_process_time_full); + if(!m_core.cleanup_handle_incoming_blocks()) { - LOG_PRINT_CCONTEXT_L0("Failure in cleanup_handle_incoming_blocks"); + GULPS_ERROR( context_str, " Failure in cleanup_handle_incoming_blocks"); return 1; } @@ -1131,13 +1109,10 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec if(m_core.get_current_blockchain_height() > previous_height) { const boost::posix_time::time_duration dt = boost::posix_time::microsec_clock::universal_time() - start; - std::string timing_message = ""; - if(ELPP->vRegistry()->allowed(el::Level::Info, "sync-info")) - timing_message = std::string(" (") + std::to_string(dt.total_microseconds() / 1e6) + " sec, " + std::to_string((m_core.get_current_blockchain_height() - previous_height) * 1e6 / dt.total_microseconds()) + " blocks/sec), " + std::to_string(m_block_queue.get_data_size() / 1048576.f) + " MB queued"; - if(ELPP->vRegistry()->allowed(el::Level::Debug, "sync-info")) - timing_message += std::string(": ") + m_block_queue.get_overview(); - MGINFO_YELLOW(context << " Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height() - << timing_message); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_BOLD_YELLOW, "{} Synced {}/{}", context_str, m_core.get_current_blockchain_height(), m_core.get_target_blockchain_height()); + GULPSF_CAT_INFO("global", "({}sec, {} blocks/sec), {} MB queued", std::to_string(dt.total_microseconds() / 1e6), std::to_string((m_core.get_current_blockchain_height() - previous_height) * 1e6 / dt.total_microseconds()), + std::to_string(m_block_queue.get_data_size() / 1048576.f)); + GULPS_CAT_LOG_L1("global","", m_block_queue.get_overview()); } } } @@ -1153,7 +1128,7 @@ int t_cryptonote_protocol_handler::try_add_next_blocks(cryptonote_connec skip: if(!request_missing_objects(context, true, force_next_span)) { - LOG_ERROR_CCONTEXT("Failed to request missing objects, dropping connection"); + GULPS_ERROR( context_str, " Failed to request missing objects, dropping connection"); drop_connection(context, false, false); return 1; } @@ -1170,7 +1145,7 @@ bool t_cryptonote_protocol_handler::on_idle() template bool t_cryptonote_protocol_handler::kick_idle_peers() { - MTRACE("Checking for idle peers..."); + GULPS_LOG_L2("Checking for idle peers..."); std::vector kick_connections; m_p2p->for_each_connection([&](cryptonote_connection_context &context, nodetool::peerid_type peer_id, uint32_t support_flags) -> bool { if(context.m_state == cryptonote_connection_context::state_synchronizing || context.m_state == cryptonote_connection_context::state_before_handshake) @@ -1181,7 +1156,7 @@ bool t_cryptonote_protocol_handler::kick_idle_peers() const int64_t threshold = passive ? PASSIVE_PEER_KICK_TIME : IDLE_PEER_KICK_TIME; if(dt.total_microseconds() > threshold) { - MINFO(context << " kicking " << (passive ? "passive" : "idle") << " peer"); + GULPS_INFO(context_str, " kicking ", passive ? "passive" : "idle", "peer"); kick_connections.push_back(context.m_connection_id); } } @@ -1200,15 +1175,15 @@ bool t_cryptonote_protocol_handler::kick_idle_peers() template int t_cryptonote_protocol_handler::handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_REQUEST_CHAIN (" << arg.block_ids.size() << " blocks"); + GULPS_P2P_MESSAGE("Received NOTIFY_REQUEST_CHAIN ({} blocks", arg.block_ids.size() ); NOTIFY_RESPONSE_CHAIN_ENTRY::request r; if(!m_core.find_blockchain_supplement(arg.block_ids, r)) { - LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN."); + GULPS_ERROR( context_str, " Failed to handle NOTIFY_REQUEST_CHAIN."); drop_connection(context, false, false); return 1; } - LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size()); + GULPSF_LOG_L1("{}-->>NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height={}, m_total_height={}, m_block_ids.size()={}", context_str, r.start_height , r.total_height , r.m_block_ids.size()); post_notify(r, context); return 1; } @@ -1224,7 +1199,7 @@ bool t_cryptonote_protocol_handler::should_download_next_span(cryptonote span = m_block_queue.get_start_gap_span(); if(span.second > 0) { - MDEBUG(context << " we should download it as there is a gap"); + GULPS_LOG_L1( context_str," we should download it as there is a gap"); return true; } @@ -1240,7 +1215,7 @@ bool t_cryptonote_protocol_handler::should_download_next_span(cryptonote return false; if(height > m_core.get_current_blockchain_height()) { - MDEBUG(context << " we should download it as the next block isn't scheduled"); + GULPS_LOG_L1( context_str," we should download it as the next block isn't scheduled"); return true; } return false; @@ -1251,7 +1226,7 @@ bool t_cryptonote_protocol_handler::should_download_next_span(cryptonote float span_speed = m_block_queue.get_speed(span_connection_id); float speed = m_block_queue.get_speed(context.m_connection_id); - MDEBUG(context << " next span is scheduled for " << span_connection_id << ", speed " << span_speed << ", ours " << speed); + GULPSF_LOG_L1("{} next span is scheduled for {}, speed {}, ours {}", context_str, boost::uuids::to_string(span_connection_id), span_speed , speed); // we try for that span too if: // - we're substantially faster, or: @@ -1259,18 +1234,18 @@ bool t_cryptonote_protocol_handler::should_download_next_span(cryptonote // - the other one asked at least 5 seconds ago if(span_speed < .25 && speed > .75f) { - MDEBUG(context << " we should download it as we're substantially faster"); + GULPS_LOG_L1( context_str, " we should download it as we're substantially faster"); return true; } if(speed == 1.0f && span_speed != 1.0f) { - MDEBUG(context << " we should download it as we're the fastest peer"); + GULPS_LOG_L1( context_str, " we should download it as we're the fastest peer"); return true; } const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); if((now - request_time).total_microseconds() > REQUEST_NEXT_SCHEDULED_SPAN_THRESHOLD) { - MDEBUG(context << " we should download it as this span was requested long ago"); + GULPS_LOG_L1( context_str, " we should download it as this span was requested long ago"); return true; } return false; @@ -1300,7 +1275,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c { if(!first) { - LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", resuming"); + GULPSF_LOG_L1("{} Block queue is {} and {}, resuming", context_str, nblocks , size ); } break; } @@ -1310,20 +1285,20 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c const boost::unique_lock sync{m_sync_lock, boost::try_to_lock}; if(sync.owns_lock()) { - LOG_DEBUG_CC(context, "No other thread is adding blocks, resuming"); + GULPS_LOG_L1( context_str, " No other thread is adding blocks, resuming"); break; } if(should_download_next_span(context)) { - MDEBUG(context << " we should try for that next span too, we think we could get it faster, resuming"); + GULPS_LOG_L1( context_str, " we should try for that next span too, we think we could get it faster, resuming"); force_next_span = true; break; } if(first) { - LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", pausing"); + GULPSF_LOG_L1("{} Block queue is {} and {}, pausing", context_str, nblocks , size ); first = false; context.m_state = cryptonote_connection_context::state_standby; } @@ -1332,7 +1307,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c bool filled; if(m_block_queue.has_next_span(context.m_connection_id, filled) && !filled) { - MDEBUG(context << " we have the next span, and it is scheduled, resuming"); + GULPS_LOG_L1( context_str, " we have the next span, and it is scheduled, resuming"); ++context.m_callback_request_count; m_p2p->request_callback(context); return true; @@ -1348,7 +1323,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c context.m_state = cryptonote_connection_context::state_synchronizing; } - MDEBUG(context << " request_missing_objects: check " << check_having_blocks << ", force_next_span " << force_next_span << ", m_needed_objects " << context.m_needed_objects.size() << " lrh " << context.m_last_response_height << ", chain " << m_core.get_current_blockchain_height()); + GULPSF_LOG_L1("{} request_missing_objects: check {}, force_next_span {}, m_needed_objects {} lrh {}, chain {}", context_str, check_having_blocks , force_next_span , context.m_needed_objects.size() , context.m_last_response_height , m_core.get_current_blockchain_height()); if(context.m_needed_objects.size() || force_next_span) { //we know objects that we need, request this objects @@ -1358,7 +1333,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c const size_t count_limit = m_core.get_block_sync_size(m_core.get_current_blockchain_height()); std::pair span = std::make_pair(0, 0); { - MDEBUG(context << " checking for gap"); + GULPS_LOG_L1(" checking for gap"); span = m_block_queue.get_start_gap_span(); if(span.second > 0) { @@ -1366,17 +1341,17 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c const uint64_t last_block_height_known = context.m_last_response_height; const uint64_t first_block_height_needed = span.first; const uint64_t last_block_height_needed = span.first + std::min(span.second, (uint64_t)count_limit) - 1; - MDEBUG(context << " gap found, span: " << span.first << " - " << span.first + span.second - 1 << " (" << last_block_height_needed << ")"); - MDEBUG(context << " current known hashes from " << first_block_height_known << " to " << last_block_height_known); + GULPSF_LOG_L1("{} gap found, span: {} - {} ({})", context_str, span.first , span.first + span.second - 1 , last_block_height_needed ); + GULPSF_LOG_L1("{} current known hashes from {} to {}", context_str, first_block_height_known , last_block_height_known); if(first_block_height_needed < first_block_height_known || last_block_height_needed > last_block_height_known) { - MDEBUG(context << " we are missing some of the necessary hashes for this gap, requesting chain again"); + GULPS_LOG_L1( context_str, " we are missing some of the necessary hashes for this gap, requesting chain again"); context.m_needed_objects.clear(); context.m_last_response_height = 0; start_from_current_chain = true; goto skip; } - MDEBUG(context << " we have the hashes for this gap"); + GULPS_LOG_L1( context_str, " we have the hashes for this gap"); } } if(force_next_span) @@ -1400,10 +1375,10 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c } if(span.second == 0) { - MDEBUG(context << " span size is 0"); + GULPS_LOG_L1( context_str, " span size is 0"); if(context.m_last_response_height + 1 < context.m_needed_objects.size()) { - MERROR(context << " ERROR: inconsistent context: lrh " << context.m_last_response_height << ", nos " << context.m_needed_objects.size()); + GULPSF_LOG_L1("{} ERROR: inconsistent context: lrh {}, nos {}", context_str, context.m_last_response_height , context.m_needed_objects.size()); context.m_needed_objects.clear(); context.m_last_response_height = 0; goto skip; @@ -1419,11 +1394,11 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c } const uint64_t first_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1; span = m_block_queue.reserve_span(first_block_height, context.m_last_response_height, count_limit, context.m_connection_id, context.m_needed_objects); - MDEBUG(context << " span from " << first_block_height << ": " << span.first << "/" << span.second); + GULPSF_LOG_L1("{} span from {}: {}/{}", context_str, first_block_height , span.first , span.second); } if(span.second == 0 && !force_next_span) { - MDEBUG(context << " still no span reserved, we may be in the corner case of next span scheduled and everything else scheduled/filled"); + GULPS_LOG_L1( context_str, " still no span reserved, we may be in the corner case of next span scheduled and everything else scheduled/filled"); std::list hashes; boost::uuids::uuid span_connection_id; boost::posix_time::ptime time; @@ -1443,7 +1418,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c } } } - MDEBUG(context << " span: " << span.first << "/" << span.second << " (" << span.first << " - " << (span.first + span.second - 1) << ")"); + GULPSF_LOG_L1("{} span: {}/{} ({} - {})", context_str, span.first , span.second , span.first , (span.first + span.second - 1) ); if(span.second > 0) { if(!is_next) @@ -1452,14 +1427,14 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c uint64_t skip = span.first - first_context_block_height; if(skip > context.m_needed_objects.size()) { - MERROR("ERROR: skip " << skip << ", m_needed_objects " << context.m_needed_objects.size() << ", first_context_block_height" << first_context_block_height); + GULPS_ERROR("ERROR: skip {}, m_needed_objects {}, first_context_block_height{}", skip , context.m_needed_objects.size() , first_context_block_height); return false; } while(skip--) context.m_needed_objects.pop_front(); if(context.m_needed_objects.size() < span.second) { - MERROR("ERROR: span " << span.first << "/" << span.second << ", m_needed_objects " << context.m_needed_objects.size()); + GULPS_ERROR("ERROR: span {}/{}, m_needed_objects {}", span.first , span.second , context.m_needed_objects.size()); return false; } @@ -1475,8 +1450,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c } context.m_last_request_time = boost::posix_time::microsec_clock::universal_time(); - LOG_PRINT_CCONTEXT_L1("-->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()=" << req.blocks.size() << ", txs.size()=" << req.txs.size() - << "requested blocks count=" << count << " / " << count_limit << " from " << span.first << ", first hash " << req.blocks.front()); + GULPSF_INFO("{} -->>NOTIFY_REQUEST_GET_OBJECTS: blocks.size()={}, txs.size()={}requested blocks count={} / {} from {}, first hash {}", context_str, req.blocks.size() , req.txs.size() , count , count_limit , span.first , req.blocks.front()); //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size()); post_notify(req, context); @@ -1491,7 +1465,7 @@ skip: NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized(); m_core.get_short_chain_history(r.block_ids); - CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty"); + GULPS_CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty"); if(!start_from_current_chain) { @@ -1505,33 +1479,33 @@ skip: //std::string blob; // for calculate size of request //epee::serialization::store_t_to_binary(r, blob); //epee::net_utils::network_throttle_manager::get_global_throttle_inreq().logger_handle_net("log/dr-monero/net/req-all.data", sec, get_avg_block_size()); - //LOG_PRINT_CCONTEXT_L1("r = " << 200); + //GULPS_INFO( context_str, "r = ", 200); context.m_last_request_time = boost::posix_time::microsec_clock::universal_time(); - LOG_PRINT_CCONTEXT_L1("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() << ", start_from_current_chain " << start_from_current_chain); + GULPSF_INFO("{} -->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}, start_from_current_chain {}", context_str, r.block_ids.size() , start_from_current_chain); post_notify(r, context); } else { - CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height - 1 && !context.m_needed_objects.size() && !context.m_requested_objects.size(), false, "request_missing_blocks final condition failed!" - << "\r\nm_last_response_height=" << context.m_last_response_height - << "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height - << "\r\nm_needed_objects.size()=" << context.m_needed_objects.size() - << "\r\nm_requested_objects.size()=" << context.m_requested_objects.size() - << "\r\non connection [" << epee::net_utils::print_connection_context_short(context) << "]"); + GULPS_CHECK_AND_ASSERT_MES(context.m_last_response_height == context.m_remote_blockchain_height - 1 && !context.m_needed_objects.size() && !context.m_requested_objects.size(), false, "request_missing_blocks final condition failed!" + ,"\r\nm_last_response_height=", context.m_last_response_height + ,"\r\nm_remote_blockchain_height=", context.m_remote_blockchain_height + ,"\r\nm_needed_objects.size()=", context.m_needed_objects.size() + ,"\r\nm_requested_objects.size()=", context.m_requested_objects.size() + ,"\r\non connection [", epee::net_utils::print_connection_context_short(context), "]"); context.m_state = cryptonote_connection_context::state_normal; if(context.m_remote_blockchain_height >= m_core.get_target_blockchain_height()) { if(m_core.get_current_blockchain_height() >= m_core.get_target_blockchain_height()) { - MGINFO_GREEN("SYNCHRONIZED OK"); + GULPS_GLOBAL_PRINT_CLR(gulps::COLOR_GREEN, "SYNCHRONIZED OK"); on_connection_synchronized(); } } else { - MINFO(context << " we've reached this peer's blockchain height"); + GULPS_INFO( context_str, " we've reached this peer's blockchain height"); } } return true; @@ -1543,11 +1517,10 @@ bool t_cryptonote_protocol_handler::on_connection_synchronized() bool val_expected = false; if(m_synchronized.compare_exchange_strong(val_expected, true)) { - MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL - << "You are now synchronized with the network. You may now start ryo-wallet-cli." << ENDL - << ENDL - << "Use the \"help\" command to see the list of available commands." << ENDL - << "**********************************************************************"); + GULPS_GLOBAL_PRINT_CLR(gulps::COLOR_BOLD_YELLOW, "\n**********************************************************************\n", + "You are now synchronized with the network. You may now start ryo-wallet-cli.\n\n", + "Use the \"help\" command to see the list of available commands.\n", + "**********************************************************************\n"); m_core.on_synchronized(); } m_core.safesyncmode(true); @@ -1569,18 +1542,17 @@ size_t t_cryptonote_protocol_handler::get_synchronizing_connections_coun template int t_cryptonote_protocol_handler::handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request &arg, cryptonote_connection_context &context) { - MLOG_P2P_MESSAGE("Received NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()=" << arg.m_block_ids.size() - << ", m_start_height=" << arg.start_height << ", m_total_height=" << arg.total_height); + GULPS_P2P_MESSAGE("Received NOTIFY_RESPONSE_CHAIN_ENTRY: m_block_ids.size()={}, m_start_height={}, m_total_height={}", arg.m_block_ids.size() , arg.start_height , arg.total_height); if(!arg.m_block_ids.size()) { - LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection"); + GULPS_ERROR( context_str, "sent empty m_block_ids, dropping connection"); drop_connection(context, true, false); return 1; } if(arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size()) { - LOG_ERROR_CCONTEXT("sent invalid start/nblocks/height, dropping connection"); + GULPS_ERROR( context_str, " sent invalid start/nblocks/height, dropping connection"); drop_connection(context, true, false); return 1; } @@ -1589,9 +1561,10 @@ int t_cryptonote_protocol_handler::handle_response_chain_entry(int comma context.m_last_response_height = arg.start_height + arg.m_block_ids.size() - 1; if(context.m_last_response_height > context.m_remote_blockchain_height) { - LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with m_total_height=" << arg.total_height - << ", m_start_height=" << arg.start_height - << ", m_block_ids.size()=" << arg.m_block_ids.size()); + GULPSF_LOG_ERROR("{} sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with m_total_height={}, m_start_height={}, m_block_ids.size()={}", context_str + , arg.total_height + , arg.start_height + , arg.m_block_ids.size()); drop_connection(context, false, false); return 1; } @@ -1599,7 +1572,7 @@ int t_cryptonote_protocol_handler::handle_response_chain_entry(int comma uint64_t n_use_blocks = m_core.prevalidate_block_hashes(arg.start_height, arg.m_block_ids); if(n_use_blocks + HASH_OF_HASHES_STEP <= arg.m_block_ids.size()) { - LOG_ERROR_CCONTEXT("Most blocks are invalid, dropping connection"); + GULPS_ERROR( context_str, " Most blocks are invalid, dropping connection"); drop_connection(context, true, false); return 1; } @@ -1615,7 +1588,7 @@ int t_cryptonote_protocol_handler::handle_response_chain_entry(int comma if(!request_missing_objects(context, false)) { - LOG_ERROR_CCONTEXT("Failed to request missing objects, dropping connection"); + GULPS_ERROR( context_str, " Failed to request missing objects, dropping connection"); drop_connection(context, false, false); return 1; } @@ -1647,12 +1620,12 @@ bool t_cryptonote_protocol_handler::relay_block(NOTIFY_NEW_BLOCK::reques { if(m_core.fluffy_blocks_enabled() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS)) { - LOG_DEBUG_CC(context, "PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK"); + GULPS_LOG_L1( context_str, " PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK"); fluffyConnections.push_back(context.m_connection_id); } else { - LOG_DEBUG_CC(context, "PEER DOESN'T SUPPORT FLUFFY BLOCKS - RELAYING FULL BLOCK"); + GULPS_LOG_L1( context_str, " PEER DOESN'T SUPPORT FLUFFY BLOCKS - RELAYING FULL BLOCK"); fullConnections.push_back(context.m_connection_id); } } @@ -1697,7 +1670,7 @@ void t_cryptonote_protocol_handler::on_connection_close(cryptonote_conne const uint64_t previous_target = m_core.get_target_blockchain_height(); if(target < previous_target) { - MINFO("Target height decreasing from " << previous_target << " to " << target); + GULPSF_INFO("Target height decreasing from {} to {}", previous_target , target); m_core.set_target_blockchain_height(target); } diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h index 7be9f627..68c2f9e3 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index b39c70e9..c5a8b195 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -120,7 +120,8 @@ target_link_libraries(daemon ${CMAKE_THREAD_LIBS_INIT} ${ZMQ_LIB} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) set_property(TARGET daemon PROPERTY OUTPUT_NAME "ryod") diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index f3ec4895..e468c6d4 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -45,10 +45,10 @@ const command_line::arg_descriptor arg_log_file = { return (daemonizer::get_default_data_dir() / "stagenet" / std::string(CRYPTONOTE_NAME ".log")).string(); return val; }}; -const command_line::arg_descriptor arg_max_log_file_size = { - "max-log-file-size", "Specify maximum log file size [B]", MAX_LOG_FILE_SIZE}; const command_line::arg_descriptor arg_log_level = { - "log-level", "", ""}; + "log-level", "Screen log level", ""}; +const command_line::arg_descriptor arg_log_file_level = { + "file-log-level", "File log level", ""}; const command_line::arg_descriptor> arg_command = { "daemon_command", "Hidden"}; const command_line::arg_descriptor arg_os_version = { @@ -67,6 +67,9 @@ const command_line::arg_descriptor arg_zmq_rpc_bind return std::to_string(cryptonote::config::ZMQ_RPC_DEFAULT_PORT); return val; }}; +const command_line::arg_descriptor arg_display_timestamps = { + "display-timestamps", "Display screen log with timestamps"}; + } // namespace daemon_args #endif // DAEMON_COMMAND_LINE_ARGS_H diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 1b316b12..168c1c19 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,12 +16,14 @@ // 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 "daemon/command_parser_executor.h" #include "common/dns_utils.h" #include "version.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { @@ -100,19 +102,19 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector 1 && !epee::string_tools::get_xtype_from_string(end_index, args[1])) { - std::cout << "wrong end block index parameter" << std::endl; + GULPS_PRINT("wrong end block index parameter"); return false; } @@ -123,7 +125,7 @@ bool t_command_parser_executor::set_log_level(const std::vector &ar { if(args.size() > 1) { - std::cout << "use: set_log [ | ]" << std::endl; + GULPS_PRINT("use: set_log [ | ]"); return true; } @@ -137,7 +139,7 @@ bool t_command_parser_executor::set_log_level(const std::vector &ar { if(4 < l) { - std::cout << "wrong number range, use: set_log " << std::endl; + GULPS_PRINT("wrong number range, use: set_log "); return true; } return m_executor.set_log_level(l); @@ -160,17 +162,14 @@ bool t_command_parser_executor::print_block(const std::vector &args { if(args.empty()) { - std::cout << "expected: print_block ( | )" << std::endl; + GULPS_PRINT("expected: print_block ( | )"); return false; } const std::string &arg = args.front(); - try - { - uint64_t height = boost::lexical_cast(arg); - return m_executor.print_block_by_height(height); - } - catch(const boost::bad_lexical_cast &) + + bool is_hash = !(std::find_if(arg.begin(), arg.end(), [](char c) { return !std::isdigit(c); }) == arg.end()); + if(is_hash) { crypto::hash block_hash; if(parse_hash256(arg, block_hash)) @@ -178,7 +177,18 @@ bool t_command_parser_executor::print_block(const std::vector &args return m_executor.print_block_by_hash(block_hash); } } - + else + { + try + { + uint64_t height = boost::lexical_cast(arg); + return m_executor.print_block_by_height(height); + } + catch(const boost::bad_lexical_cast &e) + { + return false; + } + } return false; } @@ -196,13 +206,13 @@ bool t_command_parser_executor::print_transaction(const std::vector include_json = true; else { - std::cout << "unexpected argument: " << args[i] << std::endl; + GULPSF_PRINT("unexpected argument: {}", args[i]); return true; } } if(args.empty()) { - std::cout << "expected: print_tx [+hex] [+json]" << std::endl; + GULPS_PRINT("expected: print_tx [+hex] [+json]"); return true; } @@ -220,7 +230,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector" << std::endl; + GULPS_PRINT("expected: is_key_image_spent "); return true; } @@ -264,7 +274,7 @@ bool t_command_parser_executor::start_mining(const std::vector &arg { if(!args.size()) { - std::cout << "Please specify a wallet address to mine for: start_mining []" << std::endl; + GULPS_PRINT("Please specify a wallet address to mine for: start_mining []"); return true; } @@ -276,7 +286,7 @@ bool t_command_parser_executor::start_mining(const std::vector &arg { if(!cryptonote::get_account_address_from_str(cryptonote::STAGENET, info, args.front())) { - std::cout << "target account address has wrong format" << std::endl; + GULPS_PRINT("target account address has wrong format"); return true; } else @@ -296,14 +306,15 @@ bool t_command_parser_executor::start_mining(const std::vector &arg return true; } - if(args.front() == cryptonote::common_config::DEV_FUND_ADDRESS) - { + if(args.front() == cryptonote::common_config::DEV_FUND_ADDRESS) + { tools::fail_msg_writer() << "Dev fund address is not mineable. If you would like to support the dev team please mine to " << cryptonote::common_config::RYO_DONATION_ADDR << std::endl; - return true; + return true; } if(nettype != cryptonote::MAINNET) - std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << "address, make sure this is intentional!" << std::endl; + + GULPSF_PRINT("Mining to a {} address, make sure this is intentional!", (nettype == cryptonote::TESTNET ? "testnet" : "stagenet")); uint64_t threads_count = 1; bool do_background_mining = false; bool ignore_battery = false; @@ -372,7 +383,7 @@ bool t_command_parser_executor::set_limit(const std::vector &args) } catch(const std::exception &ex) { - std::cout << "failed to parse argument" << std::endl; + GULPS_PRINT("failed to parse argument"); return false; } @@ -394,7 +405,7 @@ bool t_command_parser_executor::set_limit_up(const std::vector &arg } catch(const std::exception &ex) { - std::cout << "failed to parse argument" << std::endl; + GULPS_PRINT("failed to parse argument"); return false; } @@ -416,7 +427,7 @@ bool t_command_parser_executor::set_limit_down(const std::vector &a } catch(const std::exception &ex) { - std::cout << "failed to parse argument" << std::endl; + GULPS_PRINT("failed to parse argument"); return false; } @@ -436,7 +447,7 @@ bool t_command_parser_executor::out_peers(const std::vector &args) catch(const std::exception &ex) { - _erro("stoi exception"); + GULPS_ERROR("stoi exception"); return false; } @@ -456,7 +467,7 @@ bool t_command_parser_executor::in_peers(const std::vector &args) catch(const std::exception &ex) { - _erro("stoi exception"); + GULPS_ERROR("stoi exception"); return false; } @@ -540,7 +551,7 @@ bool t_command_parser_executor::flush_txpool(const std::vector &arg crypto::hash hash; if(!parse_hash256(args[0], hash)) { - std::cout << "failed to parse tx id" << std::endl; + GULPS_PRINT("failed to parse tx id"); return true; } txid = args[0]; @@ -573,7 +584,7 @@ bool t_command_parser_executor::output_histogram(const std::vector } else { - std::cout << "Invalid syntax: more than two non-amount parameters" << std::endl; + GULPS_PRINT("Invalid syntax: more than two non-amount parameters"); return true; } } @@ -584,19 +595,19 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector 1 && !epee::string_tools::get_xtype_from_string(count, args[1])) { - std::cout << "wrong count parameter" << std::endl; + GULPS_PRINT("wrong count parameter"); return false; } @@ -607,7 +618,7 @@ bool t_command_parser_executor::alt_chain_info(const std::vector &a { if(args.size()) { - std::cout << "No parameters allowed" << std::endl; + GULPS_PRINT("No parameters allowed"); return false; } @@ -618,14 +629,14 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector { if(args.size() != 1) { - std::cout << "Exactly one parameter is needed" << std::endl; + GULPS_PRINT("Exactly one parameter is needed"); return false; } uint64_t nblocks = 0; if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]) || nblocks == 0) { - std::cout << "wrong number of blocks" << std::endl; + GULPS_PRINT("wrong number of blocks"); return false; } @@ -636,7 +647,7 @@ bool t_command_parser_executor::update(const std::vector &args) { if(args.size() != 1) { - std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl; + GULPS_PRINT("Exactly one parameter is needed: check, download, or update"); return false; } @@ -652,7 +663,7 @@ bool t_command_parser_executor::relay_tx(const std::vector &args) crypto::hash hash; if(!parse_hash256(args[0], hash)) { - std::cout << "failed to parse tx id" << std::endl; + GULPS_PRINT("failed to parse tx id"); return true; } txid = args[0]; @@ -669,7 +680,7 @@ bool t_command_parser_executor::sync_info(const std::vector &args) bool t_command_parser_executor::version(const std::vector &args) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << std::endl; + GULPSF_PRINT("Ryo '{}' ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); return true; } diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index 82ba4e68..5fa2de2d 100644 --- a/src/daemon/command_parser_executor.h +++ b/src/daemon/command_parser_executor.h @@ -6,7 +6,7 @@ */ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -37,6 +37,7 @@ namespace daemonize class t_command_parser_executor final { + GULPS_CAT_MAJOR("cmd_pars_exe"); private: t_rpc_command_executor m_executor; diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index ff6a128f..65051148 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -22,8 +22,7 @@ #include "version.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { diff --git a/src/daemon/command_server.h b/src/daemon/command_server.h index 0c4ca06a..5d6205d1 100644 --- a/src/daemon/command_server.h +++ b/src/daemon/command_server.h @@ -9,7 +9,7 @@ Passing RPC commands: */ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/daemon/core.h b/src/daemon/core.h index 3af3f0f4..d67c33f6 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,16 +20,17 @@ #include "cryptonote_core/cryptonote_core.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" -#include "misc_log_ex.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { class t_core final { + GULPS_CAT_MAJOR("daemon_core"); public: static void init_options(boost::program_options::options_description &option_spec) { @@ -72,13 +73,13 @@ class t_core final bool run() { //initialize core here - MGINFO("Initializing core..."); + GULPS_GLOBAL_PRINT("Initializing core..."); std::string config_subdir = get_config_subdir(); if(!m_core.init(m_vm_HACK, config_subdir.empty() ? NULL : config_subdir.c_str())) { return false; } - MGINFO("Core initialized OK"); + GULPS_GLOBAL_PRINT("Core initialized OK"); return true; } @@ -89,7 +90,7 @@ class t_core final ~t_core() { - MGINFO("Deinitializing core..."); + GULPS_GLOBAL_PRINT("Deinitializing core..."); try { m_core.deinit(); @@ -97,7 +98,7 @@ class t_core final } catch(...) { - MERROR("Failed to deinitialize core..."); + GULPS_ERROR("Failed to deinitialize core..."); } } }; diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index a8133567..d697df5a 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -19,7 +19,6 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include "daemon/daemon.h" -#include "misc_log_ex.h" #include "rpc/daemon_handler.h" #include "rpc/zmq_server.h" #include @@ -37,13 +36,12 @@ #include "daemon/rpc.h" #include "version.h" +#include "common/gulps.hpp" + using namespace epee; #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" - namespace daemonize { @@ -147,7 +145,7 @@ bool t_daemon::run(bool interactive) if(!zmq_server.addTCPSocket(zmq_rpc_bind_address, zmq_rpc_bind_port)) { - LOG_ERROR(std::string("Failed to add TCP Socket (") + zmq_rpc_bind_address + ":" + zmq_rpc_bind_port + ") to ZMQ RPC Server"); + GULPSF_ERROR("Failed to add TCP Socket ({}:{}) to ZMQ RPC Server", zmq_rpc_bind_address, zmq_rpc_bind_port); if(rpc_commands) rpc_commands->stop_handling(); @@ -158,10 +156,10 @@ bool t_daemon::run(bool interactive) return false; } - MINFO("Starting ZMQ server..."); + GULPS_INFO("Starting ZMQ server..."); zmq_server.run(); - MINFO(std::string("ZMQ server started at ") + zmq_rpc_bind_address + ":" + zmq_rpc_bind_port + "."); + GULPSF_INFO("ZMQ server started at {}:{}.", zmq_rpc_bind_address, zmq_rpc_bind_port); mp_internals->p2p.run(); // blocks until p2p goes down @@ -173,17 +171,17 @@ bool t_daemon::run(bool interactive) for(auto &rpc : mp_internals->rpcs) rpc->stop(); mp_internals->core.get().get_miner().stop(); - MGINFO("Node stopped."); + GULPS_GLOBAL_PRINT("Node stopped."); return true; } catch(std::exception const &ex) { - MFATAL("Uncaught exception! " << ex.what()); + GULPSF_ERROR("Uncaught exception! {}", ex.what()); return false; } catch(...) { - MFATAL("Uncaught exception!"); + GULPS_ERROR("Uncaught exception!"); return false; } } diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h index 8a2a33b1..2b2f1238 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -17,10 +17,9 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma once -#include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" +#include namespace daemonize { @@ -29,6 +28,7 @@ struct t_internals; class t_daemon final { + GULPS_CAT_MAJOR("daemon"); public: static void init_options(boost::program_options::options_description &option_spec); diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp index d0153368..cf5b7195 100644 --- a/src/daemon/executor.cpp +++ b/src/daemon/executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,8 +16,6 @@ // 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 "misc_log_ex.h" - #include "daemon/executor.h" #include "cryptonote_config.h" @@ -25,8 +23,9 @@ #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { @@ -46,7 +45,7 @@ std::string const &t_executor::name() t_daemon t_executor::create_daemon( boost::program_options::variables_map const &vm) { - LOG_PRINT_L0("Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ") Daemonised"); + GULPS_PRINT("Ryo '{} ({}) Daemonised", RYO_RELEASE_NAME, RYO_VERSION_FULL); return t_daemon{vm}; } diff --git a/src/daemon/executor.h b/src/daemon/executor.h index 3a9e586c..fea49820 100644 --- a/src/daemon/executor.h +++ b/src/daemon/executor.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -23,13 +23,13 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { class t_executor final { + GULPS_CAT_MAJOR("daemon_exe"); public: typedef ::daemonize::t_daemon t_daemon; diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index 48981aab..222cfbbf 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,6 @@ #include "daemon/daemon.h" #include "daemon/executor.h" #include "daemonizer/daemonizer.h" -#include "misc_log_ex.h" #include "p2p/net_node.h" #include "rpc/core_rpc_server.h" #include "rpc/rpc_args.h" @@ -40,12 +39,15 @@ #include "common/stack_trace.h" #endif // STACK_TRACE -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("main_daemon"); namespace po = boost::program_options; namespace bf = boost::filesystem; +gulps_log_level log_scr, log_dsk; + int main(int argc, char* argv[]) { #ifdef WIN32 @@ -58,6 +60,13 @@ int main(int argc, char* argv[]) } #endif + gulps::inst().set_thread_tag("RYOD_MAIN"); + + // Temporary output + std::unique_ptr gout_ptr(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + gout_ptr->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { if(msg.lvl != gulps::LEVEL_INFO ) return !printed; return false; }); + uint64_t temp_out_id = gulps::inst().add_output(std::move(gout_ptr)); + try { // TODO parse the debug options like set log level right here at start @@ -82,11 +91,12 @@ int main(int argc, char* argv[]) // Settings command_line::add_arg(core_settings, daemon_args::arg_log_file); + command_line::add_arg(core_settings, daemon_args::arg_log_file_level); command_line::add_arg(core_settings, daemon_args::arg_log_level); - command_line::add_arg(core_settings, daemon_args::arg_max_log_file_size); command_line::add_arg(core_settings, daemon_args::arg_max_concurrency); command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_ip); command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_port); + command_line::add_arg(core_settings, daemon_args::arg_display_timestamps); daemonizer::init_options(hidden_options, visible_options); daemonize::t_executor::init_options(core_settings); @@ -119,24 +129,23 @@ int main(int argc, char* argv[]) if(command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << "Usage: " + std::string{argv[0]} + " [options|settings] [daemon_command...]" << std::endl - << std::endl; - std::cout << visible_options << std::endl; + GULPSF_PRINT("Ryo '{}' ({})\n", RYO_RELEASE_NAME , RYO_VERSION_FULL ); + GULPSF_PRINT("\nUsage: {} [options|settings] [daemon_command...]\n\n", std::string{argv[0]}); + GULPS_PRINT(visible_options); return 0; } - // Monero Version + // Ryo Version if(command_line::get_arg(vm, command_line::arg_version)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL; + GULPSF_PRINT("Ryo '{}' ({})\n", RYO_RELEASE_NAME , RYO_VERSION_FULL ); return 0; } // OS if(command_line::get_arg(vm, daemon_args::arg_os_version)) { - std::cout << "OS: " << tools::get_os_version_string() << ENDL; + GULPS_PRINT("OS: ", tools::get_os_version_string()); return 0; } @@ -152,13 +161,13 @@ int main(int argc, char* argv[]) catch(const std::exception &e) { // log system isn't initialized yet - std::cerr << "Error parsing config file: " << e.what() << std::endl; + GULPSF_ERROR("Error parsing config file: {}", e.what()); throw; } } else if(!command_line::is_arg_defaulted(vm, daemon_args::arg_config_file)) { - std::cerr << "Can't find config file " << config << std::endl; + GULPS_ERROR("Can't find config file ", config); return 1; } @@ -166,7 +175,7 @@ int main(int argc, char* argv[]) const bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on); if(testnet && stagenet) { - std::cerr << "Can't specify more than one of --tesnet and --stagenet" << ENDL; + GULPS_ERROR("Can't specify more than one of --tesnet and --stagenet"); return 1; } @@ -175,7 +184,7 @@ int main(int argc, char* argv[]) // verify that blockchaindb type is valid if(!cryptonote::blockchain_valid_db_type(db_type)) { - std::cout << "Invalid database type (" << db_type << "), available types are: " << cryptonote::blockchain_db_types(", ") << std::endl; + GULPSF_PRINT("Invalid database type ({}), available types are: {}", db_type, cryptonote::blockchain_db_types(", ")); return 0; } @@ -203,16 +212,28 @@ int main(int argc, char* argv[]) if(!command_line::is_arg_defaulted(vm, daemon_args::arg_log_file)) log_file_path = command_line::get_arg(vm, daemon_args::arg_log_file); log_file_path = bf::absolute(log_file_path, relative_path_base); - mlog_configure(log_file_path.string(), true, command_line::get_arg(vm, daemon_args::arg_max_log_file_size)); - // Set log level + tools::create_directories_if_necessary(data_dir.string()); + if(!command_line::is_arg_defaulted(vm, daemon_args::arg_log_level)) { - mlog_set_log(command_line::get_arg(vm, daemon_args::arg_log_level).c_str()); + if(!log_scr.parse_cat_string(command_line::get_arg(vm, daemon_args::arg_log_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, daemon_args::arg_log_level).c_str()); + return 1; + } } + else + log_scr.parse_cat_string(""); - // after logs initialized - tools::create_directories_if_necessary(data_dir.string()); + if(!command_line::is_arg_defaulted(vm, daemon_args::arg_log_file_level)) + { + if(!log_dsk.parse_cat_string(command_line::get_arg(vm, daemon_args::arg_log_file_level).c_str())) + { + GULPS_ERROR("Failed to parse filter string ", command_line::get_arg(vm, daemon_args::arg_log_file_level).c_str()); + return 1; + } + } // If there are positional options, we're running a daemon command { @@ -228,12 +249,12 @@ int main(int argc, char* argv[]) uint16_t rpc_port; if(!epee::string_tools::get_ip_int32_from_string(rpc_ip, rpc_ip_str)) { - std::cerr << "Invalid IP: " << rpc_ip_str << std::endl; + GULPS_ERROR("Invalid IP: ", rpc_ip_str); return 1; } if(!epee::string_tools::get_xtype_from_string(rpc_port, rpc_port_str)) { - std::cerr << "Invalid port: " << rpc_port_str << std::endl; + GULPS_ERROR("Invalid port: ", rpc_port_str); return 1; } @@ -249,7 +270,7 @@ int main(int argc, char* argv[]) }); if(!login) { - std::cerr << "Failed to obtain password" << std::endl; + GULPS_ERROR("Failed to obtain password"); return 1; } } @@ -261,7 +282,7 @@ int main(int argc, char* argv[]) } else { - std::cerr << "Unknown command: " << command.front() << std::endl; + GULPSF_ERROR("Unknown command: {}", command.front()); return 1; } } @@ -274,20 +295,52 @@ int main(int argc, char* argv[]) if(!command_line::is_arg_defaulted(vm, daemon_args::arg_max_concurrency)) tools::set_max_concurrency(command_line::get_arg(vm, daemon_args::arg_max_concurrency)); + gout_ptr.reset(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + gout_ptr->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(msg.out == gulps::OUT_USER_1) + return true; + return false; + }); + gulps::inst().add_output(std::move(gout_ptr)); + + // OS + if(command_line::get_arg(vm, daemon_args::arg_display_timestamps)) + { + gout_ptr.reset(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + } + else + { + gout_ptr.reset(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + } + gout_ptr->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + if(printed) + return false; + return log_scr.match_msg(msg); + }); + gulps::inst().add_output(std::move(gout_ptr)); + + if(log_dsk.is_active()) + { + gout_ptr.reset(new gulps::gulps_async_file_output(log_file_path.string())); + gout_ptr->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return log_dsk.match_msg(msg); }); + gulps::inst().add_output(std::move(gout_ptr)); + } + gulps::inst().remove_output(temp_out_id); + // logging is now set up - MGINFO("Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")"); + GULPSF_GLOBAL_PRINT("Ryo '{}' ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); - MINFO("Moving from main() into the daemonize now."); + GULPS_INFO("Moving from main() into the daemonize now."); return daemonizer::daemonize(argc, argv, daemonize::t_executor{}, vm) ? 0 : 1; } catch(std::exception const &ex) { - LOG_ERROR("Exception in main! " << ex.what()); + GULPSF_LOG_ERROR("Exception in main! {}", ex.what()); } catch(...) { - LOG_ERROR("Exception in main!"); + GULPS_LOG_ERROR("Exception in main!"); } return 1; } diff --git a/src/daemon/p2p.h b/src/daemon/p2p.h index ee942114..6c4df792 100644 --- a/src/daemon/p2p.h +++ b/src/daemon/p2p.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -24,14 +24,16 @@ #include "daemon/protocol.h" #include "p2p/net_node.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { class t_p2p final { + GULPS_CAT_MAJOR("daemon_p2p"); private: typedef cryptonote::t_cryptonote_protocol_handler t_protocol_raw; typedef nodetool::node_server t_node_server; @@ -51,12 +53,12 @@ class t_p2p final : m_server{protocol.get()} { //initialize objects - MGINFO("Initializing p2p server..."); + GULPS_GLOBAL_PRINT("Initializing p2p server..."); if(!m_server.init(vm)) { throw std::runtime_error("Failed to initialize p2p server."); } - MGINFO("p2p server initialized OK"); + GULPS_GLOBAL_PRINT("p2p server initialized OK"); } t_node_server &get() @@ -66,9 +68,9 @@ class t_p2p final void run() { - MGINFO("Starting p2p net loop..."); + GULPS_GLOBAL_PRINT("Starting p2p net loop..."); m_server.run(); - MGINFO("p2p net loop stopped"); + GULPS_GLOBAL_PRINT("p2p net loop stopped"); } void stop() @@ -78,14 +80,14 @@ class t_p2p final ~t_p2p() { - MGINFO("Deinitializing p2p..."); + GULPS_GLOBAL_PRINT("Deinitializing p2p..."); try { m_server.deinit(); } catch(...) { - MERROR("Failed to deinitialize p2p..."); + GULPS_ERROR("Failed to deinitialize p2p..."); } } }; diff --git a/src/daemon/protocol.h b/src/daemon/protocol.h index daca67bb..90b6c789 100644 --- a/src/daemon/protocol.h +++ b/src/daemon/protocol.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,14 +20,16 @@ #pragma once -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { class t_protocol final { + GULPS_CAT_MAJOR("daemon_proto"); private: typedef cryptonote::t_cryptonote_protocol_handler t_protocol_raw; typedef nodetool::node_server t_node_server; @@ -39,12 +41,12 @@ class t_protocol final boost::program_options::variables_map const &vm, t_core &core, bool offline = false) : m_protocol{core.get(), nullptr, offline} { - MGINFO("Initializing cryptonote protocol..."); + GULPS_GLOBAL_PRINT("Initializing cryptonote protocol..."); if(!m_protocol.init(vm)) { throw std::runtime_error("Failed to initialize cryptonote protocol."); } - MGINFO("Cryptonote protocol initialized OK"); + GULPS_GLOBAL_PRINT("Cryptonote protocol initialized OK"); } t_protocol_raw &get() @@ -60,16 +62,16 @@ class t_protocol final ~t_protocol() { - MGINFO("Stopping cryptonote protocol..."); + GULPS_GLOBAL_PRINT("Stopping cryptonote protocol..."); try { m_protocol.deinit(); m_protocol.set_p2p_endpoint(nullptr); - MGINFO("Cryptonote protocol stopped successfully"); + GULPS_GLOBAL_PRINT("Cryptonote protocol stopped successfully"); } catch(...) { - LOG_ERROR("Failed to stop cryptonote protocol!"); + GULPS_ERROR("Failed to stop cryptonote protocol!"); } } }; diff --git a/src/daemon/rpc.h b/src/daemon/rpc.h index 05b1ce27..7408391c 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -22,14 +22,16 @@ #include "rpc/core_rpc_server.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { class t_rpc final { + GULPS_CAT_MAJOR("daemon_rpc"); public: static void init_options(boost::program_options::options_description &option_spec) { @@ -45,28 +47,28 @@ class t_rpc final boost::program_options::variables_map const &vm, t_core &core, t_p2p &p2p, const bool restricted, const cryptonote::network_type nettype, const std::string &port, const std::string &description) : m_server{core.get(), p2p.get()}, m_description{description} { - MGINFO("Initializing " << m_description << " RPC server..."); + GULPSF_GLOBAL_PRINT("Initializing {} RPC server...", m_description); if(!m_server.init(vm, restricted, nettype, port)) { throw std::runtime_error("Failed to initialize " + m_description + " RPC server."); } - MGINFO(m_description << " RPC server initialized OK on port: " << m_server.get_binded_port()); + GULPSF_GLOBAL_PRINT("{} RPC server initialized OK on port: {}", m_description, m_server.get_binded_port()); } void run() { - MGINFO("Starting " << m_description << " RPC server..."); + GULPSF_GLOBAL_PRINT("Starting {} RPC server...",m_description); if(!m_server.run(2, false)) { throw std::runtime_error("Failed to start " + m_description + " RPC server."); } - MGINFO(m_description << " RPC server started ok"); + GULPSF_GLOBAL_PRINT("{} RPC server started ok", m_description); } void stop() { - MGINFO("Stopping " << m_description << " RPC server..."); + GULPSF_GLOBAL_PRINT("Stopping {} RPC server...", m_description); m_server.send_stop_signal(); m_server.timed_wait_server_stop(5000); } @@ -78,14 +80,14 @@ class t_rpc final ~t_rpc() { - MGINFO("Deinitializing " << m_description << " RPC server..."); + GULPSF_GLOBAL_PRINT("Deinitializing {} RPC server...", m_description); try { m_server.deinit(); } catch(...) { - MERROR("Failed to deinitialize " << m_description << " RPC server..."); + GULPSF_ERROR("Failed to deinitialize {} RPC server...", m_description); } } }; diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index bd591221..717b3bec 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,6 +18,7 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + #include "daemon/rpc_command_executor.h" #include "common/password.h" #include "common/scoped_message_writer.h" @@ -30,8 +31,15 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + +GULPS_CAT_MAJOR("rpc_cmd_exe"); + +#define GULPS_PRINT_FAIL(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_ERROR, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_RED, "Error: ", __VA_ARGS__) +#define GULPS_PRINT_SUCCESS(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_GREEN, __VA_ARGS__) +#define GULPSF_PRINT_SUCCESS(...) GULPS_OUTPUTF(gulps::OUT_USER_1, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_BOLD_GREEN, __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPSF_PRINT_OK(...) GULPS_OUTPUTF(gulps::OUT_USER_1, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), gulps_minor_cat::c_str(), gulps::COLOR_WHITE, __VA_ARGS__) namespace daemonize { @@ -53,21 +61,21 @@ void print_peer(std::string const &prefix, cryptonote::peer const &peer) peer_id_str >> id_str; epee::string_tools::xtype_to_string(peer.port, port_str); std::string addr_str = ip_str + ":" + port_str; - tools::msg_writer() << boost::format("%-10s %-25s %-25s %s") % prefix % id_str % addr_str % elapsed; + GULPSF_PRINT_OK("{:<10} {:<25} {:<25} {:<}", prefix, id_str, addr_str, elapsed); } void print_block_header(cryptonote::block_header_response const &header) { - tools::success_msg_writer() - << "timestamp: " << boost::lexical_cast(header.timestamp) << std::endl - << "previous hash: " << header.prev_hash << std::endl - << "nonce: " << boost::lexical_cast(header.nonce) << std::endl - << "is orphan: " << header.orphan_status << std::endl - << "height: " << boost::lexical_cast(header.height) << std::endl - << "depth: " << boost::lexical_cast(header.depth) << std::endl - << "hash: " << header.hash << std::endl - << "difficulty: " << boost::lexical_cast(header.difficulty) << std::endl - << "reward: " << boost::lexical_cast(header.reward); + GULPS_PRINT_CLR(gulps::COLOR_GREEN, + "timestamp: ", boost::lexical_cast(header.timestamp), + "\nprevious hash: ", header.prev_hash, + "\nnonce: ", boost::lexical_cast(header.nonce), + "\nis orphan: ", header.orphan_status, + "\nheight: ", boost::lexical_cast(header.height), + "\ndepth: ", boost::lexical_cast(header.depth), + "\nhash: ", header.hash, + "\ndifficulty: ", boost::lexical_cast(header.difficulty), + "\nreward: ", boost::lexical_cast(header.reward)); } std::string get_human_time_ago(time_t t, time_t now) @@ -155,7 +163,7 @@ bool t_rpc_command_executor::print_peer_list() { if(!m_rpc_server->on_get_peer_list(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << failure_message; + GULPS_PRINT_FAIL( failure_message); return false; } } @@ -190,14 +198,13 @@ bool t_rpc_command_executor::print_peer_list_stats() { if(!m_rpc_server->on_get_peer_list(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << failure_message; + GULPS_PRINT_FAIL( failure_message); return false; } } - tools::msg_writer() - << "White list size: " << res.white_list.size() << "/" << P2P_LOCAL_WHITE_PEERLIST_LIMIT << " (" << res.white_list.size() * 100.0 / P2P_LOCAL_WHITE_PEERLIST_LIMIT << "%)" << std::endl - << "Gray list size: " << res.gray_list.size() << "/" << P2P_LOCAL_GRAY_PEERLIST_LIMIT << " (" << res.gray_list.size() * 100.0 / P2P_LOCAL_GRAY_PEERLIST_LIMIT << "%)"; + GULPSF_PRINT_OK("White list size: {}/{} ({}%)\nGray list size: {}/{} ({}%)", res.white_list.size() , P2P_LOCAL_WHITE_PEERLIST_LIMIT , res.white_list.size() * 100.0 / P2P_LOCAL_WHITE_PEERLIST_LIMIT , + res.gray_list.size() , P2P_LOCAL_GRAY_PEERLIST_LIMIT , res.gray_list.size() * 100.0 / P2P_LOCAL_GRAY_PEERLIST_LIMIT ); return true; } @@ -220,12 +227,12 @@ bool t_rpc_command_executor::save_blockchain() { if(!m_rpc_server->on_save_bc(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Blockchain saved"; + GULPS_PRINT_SUCCESS( "Blockchain saved"); return true; } @@ -249,11 +256,11 @@ bool t_rpc_command_executor::show_hash_rate() { if(!m_rpc_server->on_set_log_hash_rate(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); } } - tools::success_msg_writer() << "Hash rate logging is on"; + GULPS_PRINT_SUCCESS( "Hash rate logging is on"); return true; } @@ -277,12 +284,12 @@ bool t_rpc_command_executor::hide_hash_rate() { if(!m_rpc_server->on_set_log_hash_rate(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Hash rate logging is off"; + GULPS_PRINT_SUCCESS( "Hash rate logging is off"); return true; } @@ -305,15 +312,15 @@ bool t_rpc_command_executor::show_difficulty() { if(!m_rpc_server->on_get_info(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message.c_str(), res.status); + GULPS_PRINT_FAIL( make_error(fail_message.c_str(), res.status)); return true; } } - tools::success_msg_writer() << "BH: " << res.height - << ", TH: " << res.top_block_hash - << ", DIFF: " << res.difficulty - << ", HR: " << res.difficulty / res.target << " H/s"; + GULPSF_PRINT_SUCCESS("BH: {}, TH: {}, DIFF: {}, HR: {} H/s", res.height, + res.top_block_hash, + res.difficulty, + res.difficulty / res.target); return true; } @@ -321,12 +328,12 @@ bool t_rpc_command_executor::show_difficulty() static std::string get_mining_speed(uint64_t hr) { if(hr > 1e9) - return (boost::format("%.2f GH/s") % (hr / 1e9)).str(); + return fmt::format("{:.2f} GH/s", (hr / 1.0e9)); if(hr > 1e6) - return (boost::format("%.2f MH/s") % (hr / 1e6)).str(); + return fmt::format("{:.2f} MH/s", (hr / 1.0e6)); if(hr > 1e3) - return (boost::format("%.2f kH/s") % (hr / 1e3)).str(); - return (boost::format("%.0f H/s") % hr).str(); + return fmt::format("{:.2f} kH/s", (hr / 1.0e3)); + return fmt::format("{} H/s", hr); } static std::string get_fork_extra_info(uint64_t t, uint64_t now, uint64_t block_time) @@ -340,11 +347,11 @@ static std::string get_fork_extra_info(uint64_t t, uint64_t now, uint64_t block_ { uint64_t dblocks = t - now; if(dblocks <= 30) - return (boost::format(" (next fork in %u blocks)") % (unsigned)dblocks).str(); + return fmt::format(" (next fork in {} blocks)", (unsigned)dblocks); if(dblocks <= blocks_per_day / 2) - return (boost::format(" (next fork in %.1f hours)") % (dblocks / (float)(blocks_per_day / 24))).str(); + return fmt::format(" (next fork in {:.1f) hours)", (dblocks / (float)(blocks_per_day / 24))); if(dblocks <= blocks_per_day * 30) - return (boost::format(" (next fork in %.1f days)") % (dblocks / (float)blocks_per_day)).str(); + return fmt::format(" (next fork in {:.1f} days)", (dblocks / (float)blocks_per_day)); return ""; } return ""; @@ -395,17 +402,17 @@ bool t_rpc_command_executor::show_status() { if(!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, ires.status); + GULPS_PRINT_FAIL( make_error(fail_message, ires.status)); return true; } if(!m_rpc_server->on_hard_fork_info(hfreq, hfres, error_resp) || hfres.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, hfres.status); + GULPS_PRINT_FAIL( make_error(fail_message, hfres.status)); return true; } if(!m_rpc_server->on_mining_status(mreq, mres)) { - tools::fail_msg_writer() << fail_message.c_str(); + GULPS_PRINT_FAIL( fail_message.c_str()); return true; } @@ -415,7 +422,7 @@ bool t_rpc_command_executor::show_status() } else if(mres.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, mres.status); + GULPS_PRINT_FAIL( make_error(fail_message, mres.status)); return true; } } @@ -428,7 +435,7 @@ bool t_rpc_command_executor::show_status() bootstrap_msg = ", bootstrapping from " + ires.bootstrap_daemon_address; if(ires.untrusted) { - bootstrap_msg += (boost::format(", local height: %llu (%.1f%%)") % ires.height_without_bootstrap % get_sync_percentage(ires.height_without_bootstrap, net_height)).str(); + bootstrap_msg += fmt::format(", local height: {} ({:.1f}%)", ires.height_without_bootstrap, get_sync_percentage(ires.height_without_bootstrap, net_height)); } else { @@ -436,7 +443,23 @@ bool t_rpc_command_executor::show_status() } } - tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections, uptime %ud %uh %um %us") % (unsigned long long)ires.height % (unsigned long long)net_height % get_sync_percentage(ires) % (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet") % bootstrap_msg % (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ((mres.is_background_mining_enabled ? "smart " : "") + std::string("mining at ") + get_mining_speed(mres.speed)) : "not mining") % get_mining_speed(ires.difficulty / ires.target) % (unsigned)hfres.version % get_fork_extra_info(hfres.earliest_height, net_height, ires.target) % (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked") % (unsigned)ires.outgoing_connections_count % (unsigned)ires.incoming_connections_count % (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0) % (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0)) % (unsigned int)floor(fmod((uptime / 60.0), 60.0)) % (unsigned int)fmod(uptime, 60.0); + GULPSF_PRINT_SUCCESS("Height: {}/{} ({:.1f}) on {}{}, {}, net hash {}, v{}{}, {}, {}(out)+{}(in) connections, uptime {}d {}h {}m {}s", + (unsigned long long)ires.height, + (unsigned long long)net_height, + get_sync_percentage(ires), + (ires.testnet ? "testnet" : ires.stagenet ? "stagenet" : "mainnet"), + bootstrap_msg, + (!has_mining_info ? "mining info unavailable" : mining_busy ? "syncing" : mres.active ? ((mres.is_background_mining_enabled ? "smart " : "") + std::string("mining at ") + get_mining_speed(mres.speed)) : "not mining"), + get_mining_speed(ires.difficulty / ires.target), + (unsigned)hfres.version, + get_fork_extra_info(hfres.earliest_height, net_height, ires.target), + (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked"), + (unsigned)ires.outgoing_connections_count, + (unsigned)ires.incoming_connections_count, + (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0), + (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0)), + (unsigned int)floor(fmod((uptime / 60.0), 60.0)), + (unsigned int)fmod(uptime, 60.0)); return true; } @@ -460,44 +483,44 @@ bool t_rpc_command_executor::print_connections() { if(!m_rpc_server->on_get_connections(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::msg_writer() << std::setw(30) << std::left << "Remote Host" - << std::setw(20) << "Peer id" - << std::setw(20) << "Support Flags" - << std::setw(30) << "Recv/Sent (inactive,sec)" - << std::setw(25) << "State" - << std::setw(20) << "Livetime(sec)" - << std::setw(12) << "Down (kB/s)" - << std::setw(14) << "Down(now)" - << std::setw(10) << "Up (kB/s)" - << std::setw(13) << "Up(now)" - << std::endl; +GULPSF_PRINT_OK("{:<30}{:<20}{:<20}{:<30}{:<25}{:<20}{:<12}{:<14}{:<10}{:<13}", + "Remote Host", + "Peer id", + "Support Flags", + "Recv/Sent (inactive,sec)", + "State", + "Livetime(sec)", + "Down (kB/s)", + "Down(now)", + "Up (kB/s)", + "Up(now)\n"); for(auto &info : res.connections) { std::string address = info.incoming ? "INC " : "OUT "; address += info.ip + ":" + info.port; //std::string in_out = info.incoming ? "INC " : "OUT "; - tools::msg_writer() + GULPSF_PRINT_OK("{:<30}{:<20}{:<20}{:<30}{:<25}{:<20}{:<12}{:<14}{:<10}{:<13}{:<}{:<}", //<< std::setw(30) << std::left << in_out - << std::setw(30) << std::left << address - << std::setw(20) << epee::string_tools::pad_string(info.peer_id, 16, '0', true) - << std::setw(20) << info.support_flags - << std::setw(30) << std::to_string(info.recv_count) + "(" + std::to_string(info.recv_idle_time) + ")/" + std::to_string(info.send_count) + "(" + std::to_string(info.send_idle_time) + ")" - << std::setw(25) << info.state - << std::setw(20) << info.live_time - << std::setw(12) << info.avg_download - << std::setw(14) << info.current_download - << std::setw(10) << info.avg_upload - << std::setw(13) << info.current_upload - - << std::left << (info.localhost ? "[LOCALHOST]" : "") - << std::left << (info.local_ip ? "[LAN]" : ""); - //tools::msg_writer() << boost::format("%-25s peer_id: %-25s %s") % address % info.peer_id % in_out; + address, + epee::string_tools::pad_string(info.peer_id, 16, '0', true), + info.support_flags, + std::to_string(info.recv_count) + "(" + std::to_string(info.recv_idle_time) + ")/" + std::to_string(info.send_count) + "(" + std::to_string(info.send_idle_time) + ")", + info.state, + info.live_time, + info.avg_download, + info.current_download, + info.avg_upload, + info.current_upload, + + (info.localhost ? "[LOCALHOST]" : ""), + (info.local_ip ? "[LAN]" : "")); + //GULPSF_PRINT_OK("{}-25s peer_id: {}-25s {}", address, info.peer_id, in_out); } return true; @@ -525,7 +548,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u { if(!m_rpc_server->on_get_block_headers_range(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -534,13 +557,10 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u for(auto &header : res.headers) { if(!first) - std::cout << std::endl; - std::cout - << "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty - << ", size: " << header.block_size << ", transactions: " << header.num_txes << std::endl - << "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl - << "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl - << "difficulty: " << header.difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; + + GULPSF_PRINT_OK("\nheight: {}, timestamp: {}, difficulty: {}, size: {}, transactions: {}\nmajor version: {}, minor version: {}\nblock id: {}, previous block id: {}\ndifficulty: {}, nonce {}, reward {}", + header.height, header.timestamp, header.difficulty, header.block_size, header.num_txes, (unsigned)header.major_version, (unsigned)header.minor_version, + header.hash, header.prev_hash, header.difficulty, header.nonce, cryptonote::print_money(header.reward)); first = false; } @@ -566,12 +586,12 @@ bool t_rpc_command_executor::set_log_level(int8_t level) { if(!m_rpc_server->on_set_log_level(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Log level is now " << std::to_string(level); + GULPSF_PRINT_SUCCESS("Log level is now {}", level); return true; } @@ -595,12 +615,12 @@ bool t_rpc_command_executor::set_log_categories(const std::string &categories) { if(!m_rpc_server->on_set_log_categories(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Log categories are now " << res.categories; + GULPSF_PRINT_SUCCESS("Log categories are now {}", res.categories); return true; } @@ -623,12 +643,12 @@ bool t_rpc_command_executor::print_height() { if(!m_rpc_server->on_get_height(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << boost::lexical_cast(res.height); + GULPS_PRINT_SUCCESS(boost::lexical_cast(res.height)); return true; } @@ -654,13 +674,13 @@ bool t_rpc_command_executor::print_block_by_hash(crypto::hash block_hash) { if(!m_rpc_server->on_get_block(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } print_block_header(res.block_header); - tools::success_msg_writer() << res.json << ENDL; + GULPS_PRINT_CLR( gulps::COLOR_GREEN, res.json ); return true; } @@ -686,13 +706,13 @@ bool t_rpc_command_executor::print_block_by_height(uint64_t height) { if(!m_rpc_server->on_get_block(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } print_block_header(res.block_header); - tools::success_msg_writer() << res.json << ENDL; + GULPS_PRINT_CLR( gulps::COLOR_GREEN, res.json ); return true; } @@ -720,7 +740,7 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash, { if(!m_rpc_server->on_get_transactions(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -731,15 +751,15 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash, { // only available for new style answers if(res.txs.front().in_pool) - tools::success_msg_writer() << "Found in pool"; + GULPS_PRINT_SUCCESS( "Found in pool"); else - tools::success_msg_writer() << "Found in blockchain at height " << res.txs.front().block_height; + GULPSF_PRINT_SUCCESS("Found in blockchain at height {}", res.txs.front().block_height); } const std::string &as_hex = (1 == res.txs.size()) ? res.txs.front().as_hex : res.txs_as_hex.front(); // Print raw hex if requested if(include_hex) - tools::success_msg_writer() << as_hex << std::endl; + GULPS_PRINT_CLR( gulps::COLOR_GREEN, as_hex ); // Print json if requested if(include_json) @@ -749,21 +769,21 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash, cryptonote::blobdata blob; if(!string_tools::parse_hexstr_to_binbuff(as_hex, blob)) { - tools::fail_msg_writer() << "Failed to parse tx to get json format"; + GULPS_PRINT_FAIL( "Failed to parse tx to get json format"); } else if(!cryptonote::parse_and_validate_tx_from_blob(blob, tx, tx_hash, tx_prefix_hash)) { - tools::fail_msg_writer() << "Failed to parse tx blob to get json format"; + GULPS_PRINT_FAIL( "Failed to parse tx blob to get json format"); } else { - tools::success_msg_writer() << cryptonote::obj_to_json_str(tx) << std::endl; + GULPSF_PRINT_CLR( gulps::COLOR_GREEN, cryptonote::obj_to_json_str(tx) ); } } } else { - tools::fail_msg_writer() << "Transaction wasn't found: " << transaction_hash << std::endl; + GULPS_PRINT_FAIL( "Transaction wasn't found: ", transaction_hash); } return true; @@ -788,19 +808,19 @@ bool t_rpc_command_executor::is_key_image_spent(const crypto::key_image &ki) { if(!m_rpc_server->on_is_key_image_spent(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } if(1 == res.spent_status.size()) { - // first as hex - tools::success_msg_writer() << ki << ": " << (res.spent_status.front() ? "spent" : "unspent") << (res.spent_status.front() == cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_POOL ? " (in pool)" : ""); + GULPS_PRINT_SUCCESS(ki, ": ", (res.spent_status.front() ? "spent" : "unspent"), + (res.spent_status.front() == cryptonote::COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_POOL ? " (in pool)" : "")); } else { - tools::fail_msg_writer() << "key image status could not be determined" << std::endl; + GULPS_PRINT_FAIL( "key image status could not be determined"); } return true; @@ -824,68 +844,68 @@ bool t_rpc_command_executor::print_transaction_pool_long() { if(!m_rpc_server->on_get_transaction_pool(req, res, false) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } if(res.transactions.empty() && res.spent_key_images.empty()) { - tools::msg_writer() << "Pool is empty" << std::endl; + GULPS_PRINT_OK("Pool is empty"); } if(!res.transactions.empty()) { const time_t now = time(NULL); - tools::msg_writer() << "Transactions: "; + GULPS_PRINT_OK( "Transactions: "); for(auto &tx_info : res.transactions) { - tools::msg_writer() << "id: " << tx_info.id_hash << std::endl - << tx_info.tx_json << std::endl - << "blob_size: " << tx_info.blob_size << std::endl - << "fee: " << cryptonote::print_money(tx_info.fee) << std::endl - << "fee/byte: " << cryptonote::print_money(tx_info.fee / (double)tx_info.blob_size) << std::endl - << "receive_time: " << tx_info.receive_time << " (" << get_human_time_ago(tx_info.receive_time, now) << ")" << std::endl - << "relayed: " << [&](const cryptonote::tx_info &tx_info) -> std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; }(tx_info) << std::endl - << "do_not_relay: " << (tx_info.do_not_relay ? 'T' : 'F') << std::endl - << "kept_by_block: " << (tx_info.kept_by_block ? 'T' : 'F') << std::endl - << "double_spend_seen: " << (tx_info.double_spend_seen ? 'T' : 'F') << std::endl - << "max_used_block_height: " << tx_info.max_used_block_height << std::endl - << "max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl - << "last_failed_height: " << tx_info.last_failed_height << std::endl - << "last_failed_id: " << tx_info.last_failed_id_hash << std::endl; + GULPSF_PRINT_OK("id: {}\n{}\nblob_size: {}\nfee: {}\nfee/byte: {}\nreceive_time: {} ({})relayed: {}\ndo_not_relay: {}\nkept_by_block: {}\ndouble_spend_seen: {}\nmax_used_block_height: {}\nmax_used_block_id: {}\nlast_failed_height: {}\nlast_failed_id: {}" + , tx_info.id_hash + , tx_info.tx_json + , tx_info.blob_size + , cryptonote::print_money(tx_info.fee) + , cryptonote::print_money(tx_info.fee / (double)tx_info.blob_size) + , tx_info.receive_time + , get_human_time_ago(tx_info.receive_time, now) + , [&](const cryptonote::tx_info &tx_info) -> std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; }(tx_info) , (tx_info.do_not_relay ? 'T' : 'F') + , (tx_info.kept_by_block ? 'T' : 'F') + , (tx_info.double_spend_seen ? 'T' : 'F') + , tx_info.max_used_block_height + , tx_info.max_used_block_id_hash + , tx_info.last_failed_height + , tx_info.last_failed_id_hash); } if(res.spent_key_images.empty()) { - tools::msg_writer() << "WARNING: Inconsistent pool state - no spent key images"; + GULPS_PRINT_OK( "WARNING: Inconsistent pool state - no spent key images"); } } if(!res.spent_key_images.empty()) { - tools::msg_writer() << ""; // one newline - tools::msg_writer() << "Spent key images: "; + GULPS_PRINT_OK( "\nSpent key images: "); for(const cryptonote::spent_key_image_info &kinfo : res.spent_key_images) { - tools::msg_writer() << "key image: " << kinfo.id_hash; + GULPSF_PRINT_OK("key image: {}", kinfo.id_hash); if(kinfo.txs_hashes.size() == 1) { - tools::msg_writer() << " tx: " << kinfo.txs_hashes[0]; + GULPSF_PRINT_OK(" tx: {}", kinfo.txs_hashes[0]); } else if(kinfo.txs_hashes.size() == 0) { - tools::msg_writer() << " WARNING: spent key image has no txs associated"; + GULPS_PRINT_OK( " WARNING: spent key image has no txs associated"); } else { - tools::msg_writer() << " NOTE: key image for multiple txs: " << kinfo.txs_hashes.size(); + GULPSF_PRINT_OK(" NOTE: key image for multiple txs: {}", kinfo.txs_hashes.size()); for(const std::string &tx_id : kinfo.txs_hashes) { - tools::msg_writer() << " tx: " << tx_id; + GULPSF_PRINT_OK(" tx: {}", tx_id); } } } if(res.transactions.empty()) { - tools::msg_writer() << "WARNING: Inconsistent pool state - no transactions"; + GULPS_PRINT_OK( "WARNING: Inconsistent pool state - no transactions"); } } @@ -910,33 +930,35 @@ bool t_rpc_command_executor::print_transaction_pool_short() { if(!m_rpc_server->on_get_transaction_pool(req, res, false) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } if(res.transactions.empty()) { - tools::msg_writer() << "Pool is empty" << std::endl; + GULPS_PRINT_OK("Pool is empty"); } else { const time_t now = time(NULL); for(auto &tx_info : res.transactions) { - tools::msg_writer() << "id: " << tx_info.id_hash << std::endl - << "blob_size: " << tx_info.blob_size << std::endl - << "fee: " << cryptonote::print_money(tx_info.fee) << std::endl - << "fee/byte: " << cryptonote::print_money(tx_info.fee / (double)tx_info.blob_size) << std::endl - << "receive_time: " << tx_info.receive_time << " (" << get_human_time_ago(tx_info.receive_time, now) << ")" << std::endl - << "relayed: " << [&](const cryptonote::tx_info &tx_info) -> std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; }(tx_info) << std::endl - << "do_not_relay: " << (tx_info.do_not_relay ? 'T' : 'F') << std::endl - << "kept_by_block: " << (tx_info.kept_by_block ? 'T' : 'F') << std::endl - << "double_spend_seen: " << (tx_info.double_spend_seen ? 'T' : 'F') << std::endl - << "max_used_block_height: " << tx_info.max_used_block_height << std::endl - << "max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl - << "last_failed_height: " << tx_info.last_failed_height << std::endl - << "last_failed_id: " << tx_info.last_failed_id_hash << std::endl; + GULPSF_PRINT_OK("id: {}\n{}\nblob_size: {}\nfee: {}\nfee/byte: {}\nreceive_time: {} ({})relayed: {}\ndo_not_relay: {}\nkept_by_block: {}\ndouble_spend_seen: {}\nmax_used_block_height: {}\nmax_used_block_id: {}\nlast_failed_height: {}\nlast_failed_id: {}" + , tx_info.id_hash + , tx_info.tx_json + , tx_info.blob_size + , cryptonote::print_money(tx_info.fee) + , cryptonote::print_money(tx_info.fee / (double)tx_info.blob_size) + , tx_info.receive_time + , get_human_time_ago(tx_info.receive_time, now) + , [&](const cryptonote::tx_info &tx_info) -> std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; }(tx_info) , (tx_info.do_not_relay ? 'T' : 'F') + , (tx_info.kept_by_block ? 'T' : 'F') + , (tx_info.double_spend_seen ? 'T' : 'F') + , tx_info.max_used_block_height + , tx_info.max_used_block_id_hash + , tx_info.last_failed_height + , tx_info.last_failed_id_hash); } } @@ -968,12 +990,12 @@ bool t_rpc_command_executor::print_transaction_pool_stats() res.pool_stats.clear(); if(!m_rpc_server->on_get_transaction_pool_stats(req, res, false) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } if(!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, ires.status); + GULPS_PRINT_FAIL( make_error(fail_message, ires.status)); return true; } } @@ -991,13 +1013,14 @@ bool t_rpc_command_executor::print_transaction_pool_stats() else { uint64_t backlog = (res.pool_stats.bytes_total + full_reward_zone - 1) / full_reward_zone; - backlog_message = (boost::format("estimated %u block (%u minutes) backlog") % backlog % (backlog * cryptonote::common_config::DIFFICULTY_TARGET / 60)).str(); + backlog_message = fmt::format("estimated {} block ({} minutes) backlog", backlog, (backlog * cryptonote::common_config::DIFFICULTY_TARGET / 60)); } - tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ", median " << res.pool_stats.bytes_med << ")" << std::endl - << "fees " << cryptonote::print_money(res.pool_stats.fee_total) << " (avg " << cryptonote::print_money(n_transactions ? res.pool_stats.fee_total / n_transactions : 0) << " per tx" - << ", " << cryptonote::print_money(res.pool_stats.bytes_total ? res.pool_stats.fee_total / res.pool_stats.bytes_total : 0) << " per byte)" << std::endl - << res.pool_stats.num_double_spends << " double spends, " << res.pool_stats.num_not_relayed << " not relayed, " << res.pool_stats.num_failing << " failing, " << res.pool_stats.num_10m << " older than 10 minutes (oldest " << (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) << "), " << backlog_message; + GULPSF_PRINT_OK("{} tx(es), {} bytes total (min {}, max {}, avg {}, median {})\nfees {} (avg {} per tx, {} per byte)\n{} double spends, {} not relayed, {} failing, {} older than 10 minutes (oldest {}), {}", + n_transactions , res.pool_stats.bytes_total , res.pool_stats.bytes_min , res.pool_stats.bytes_max , avg_bytes , res.pool_stats.bytes_med , + cryptonote::print_money(res.pool_stats.fee_total) , cryptonote::print_money(n_transactions ? res.pool_stats.fee_total / n_transactions : 0) , + cryptonote::print_money(res.pool_stats.bytes_total ? res.pool_stats.fee_total / res.pool_stats.bytes_total : 0) , res.pool_stats.num_double_spends , + res.pool_stats.num_not_relayed , res.pool_stats.num_failing , res.pool_stats.num_10m , (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) , backlog_message); if(n_transactions > 1 && res.pool_stats.histo.size()) { @@ -1020,13 +1043,12 @@ bool t_rpc_command_executor::print_transaction_pool_stats() for(i = 0; i < denom; i++) times[i] = i * numer / denom; } - tools::msg_writer() << " Age Txes Bytes"; + GULPS_PRINT_OK(" Age Txes Bytes"); for(i = 0; i < n; i++) { - tools::msg_writer() << get_time_hms(times[i]) << std::setw(8) << res.pool_stats.histo[i].txs << std::setw(12) << res.pool_stats.histo[i].bytes; + GULPSF_PRINT_OK("{}{:>8}{:>12}", get_time_hms(times[i]), res.pool_stats.histo[i].txs, res.pool_stats.histo[i].bytes); } } - tools::msg_writer(); return true; } @@ -1046,14 +1068,14 @@ bool t_rpc_command_executor::start_mining(cryptonote::account_public_address add { if(m_rpc_client->rpc_request(req, res, "/start_mining", fail_message.c_str())) { - tools::success_msg_writer() << "Mining started"; + GULPS_PRINT_SUCCESS( "Mining started"); } } else { if(!m_rpc_server->on_start_mining(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -1079,12 +1101,12 @@ bool t_rpc_command_executor::stop_mining() { if(!m_rpc_server->on_stop_mining(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Mining stopped"; + GULPS_PRINT_SUCCESS( "Mining stopped"); return true; } @@ -1120,12 +1142,12 @@ bool t_rpc_command_executor::stop_daemon() { if(!m_rpc_server->on_stop_daemon(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Stop signal sent"; + GULPS_PRINT_SUCCESS( "Stop signal sent"); return true; } @@ -1134,7 +1156,7 @@ bool t_rpc_command_executor::print_status() { if(!m_is_rpc) { - tools::success_msg_writer() << "print_status makes no sense in interactive mode"; + GULPS_PRINT_SUCCESS( "print_status makes no sense in interactive mode"); return true; } @@ -1142,11 +1164,11 @@ bool t_rpc_command_executor::print_status() if(daemon_is_alive) { - tools::success_msg_writer() << "ryod is running"; + GULPS_PRINT_SUCCESS( "ryod is running"); } else { - tools::fail_msg_writer() << "ryod is NOT running"; + GULPS_PRINT_FAIL( "ryod is NOT running"); } return true; @@ -1170,13 +1192,13 @@ bool t_rpc_command_executor::get_limit() { if(!m_rpc_server->on_get_limit(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(failure_message, res.status); + GULPS_PRINT_FAIL( make_error(failure_message, res.status)); return true; } } - tools::msg_writer() << "limit-down is " << res.limit_down << " kB/s"; - tools::msg_writer() << "limit-up is " << res.limit_up << " kB/s"; + GULPSF_PRINT_OK("limit-down is {} kB/s", res.limit_down ); + GULPSF_PRINT_OK("limit-up is {} kB/s", res.limit_up ); return true; } @@ -1201,13 +1223,13 @@ bool t_rpc_command_executor::set_limit(int64_t limit_down, int64_t limit_up) { if(!m_rpc_server->on_set_limit(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(failure_message, res.status); + GULPS_PRINT_FAIL( make_error(failure_message, res.status)); return true; } } - tools::msg_writer() << "Set limit-down to " << res.limit_down << " kB/s"; - tools::msg_writer() << "Set limit-up to " << res.limit_up << " kB/s"; + GULPSF_PRINT_OK("Set limit-down to {} kB/s", res.limit_down ); + GULPSF_PRINT_OK("Set limit-up to {} kB/s", res.limit_up ); return true; } @@ -1229,12 +1251,12 @@ bool t_rpc_command_executor::get_limit_up() { if(!m_rpc_server->on_get_limit(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(failure_message, res.status); + GULPS_PRINT_FAIL( make_error(failure_message, res.status)); return true; } } - tools::msg_writer() << "limit-up is " << res.limit_up << " kB/s"; + GULPSF_PRINT_OK("limit-up is {} kB/s", res.limit_up ); return true; } @@ -1256,12 +1278,12 @@ bool t_rpc_command_executor::get_limit_down() { if(!m_rpc_server->on_get_limit(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(failure_message, res.status); + GULPS_PRINT_FAIL( make_error(failure_message, res.status)); return true; } } - tools::msg_writer() << "limit-down is " << res.limit_down << " kB/s"; + GULPSF_PRINT_OK("limit-down is {} kB/s", res.limit_down ); return true; } @@ -1287,12 +1309,12 @@ bool t_rpc_command_executor::out_peers(uint64_t limit) { if(!m_rpc_server->on_out_peers(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - std::cout << "Max number of out peers set to " << limit << std::endl; + GULPSF_PRINT_OK("Max number of out peers set to {}", limit); return true; } @@ -1319,12 +1341,12 @@ bool t_rpc_command_executor::in_peers(uint64_t limit) { if(!m_rpc_server->on_in_peers(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - std::cout << "Max number of in peers set to " << limit << std::endl; + GULPS_PRINT_OK("Max number of in peers set to ", limit); return true; } @@ -1349,14 +1371,14 @@ bool t_rpc_command_executor::hard_fork_info(uint8_t version) { if(!m_rpc_server->on_hard_fork_info(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } version = version > 0 ? version : res.voting; - tools::msg_writer() << "version " << (uint32_t)version << " " << (res.enabled ? "enabled" : "not enabled") << ", " << res.votes << "/" << res.window << " votes, threshold " << res.threshold; - tools::msg_writer() << "current version " << (uint32_t)res.version << ", voting for version " << (uint32_t)res.voting; + GULPSF_PRINT_OK("version {} {}, {}/{} votes, threshold {}", (uint32_t)version , (res.enabled ? "enabled" : "not enabled") , res.votes , res.window , res.threshold); + GULPSF_PRINT_OK("current version {}, voting for version {}", (uint32_t)res.version , (uint32_t)res.voting); return true; } @@ -1379,14 +1401,14 @@ bool t_rpc_command_executor::print_bans() { if(!m_rpc_server->on_get_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } for(auto i = res.bans.begin(); i != res.bans.end(); ++i) { - tools::msg_writer() << epee::string_tools::get_ip_string_from_int32(i->ip) << " banned for " << i->seconds << " seconds"; + GULPSF_PRINT_OK("{} banned for {} seconds", epee::string_tools::get_ip_string_from_int32(i->ip), i->seconds); } return true; @@ -1399,10 +1421,10 @@ bool t_rpc_command_executor::ban(const std::string &ip, time_t seconds) std::string fail_message = "Unsuccessful"; epee::json_rpc::error error_resp; - cryptonote::COMMAND_RPC_SETBANS::ban ban; + cryptonote::COMMAND_RPC_SETBANS::ban_data ban; if(!epee::string_tools::get_ip_int32_from_string(ban.ip, ip)) { - tools::fail_msg_writer() << "Invalid IP"; + GULPS_PRINT_FAIL( "Invalid IP"); return true; } ban.ban = true; @@ -1420,7 +1442,7 @@ bool t_rpc_command_executor::ban(const std::string &ip, time_t seconds) { if(!m_rpc_server->on_set_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -1435,10 +1457,10 @@ bool t_rpc_command_executor::unban(const std::string &ip) std::string fail_message = "Unsuccessful"; epee::json_rpc::error error_resp; - cryptonote::COMMAND_RPC_SETBANS::ban ban; + cryptonote::COMMAND_RPC_SETBANS::ban_data ban; if(!epee::string_tools::get_ip_int32_from_string(ban.ip, ip)) { - tools::fail_msg_writer() << "Invalid IP"; + GULPS_PRINT_FAIL( "Invalid IP"); return true; } ban.ban = false; @@ -1456,7 +1478,7 @@ bool t_rpc_command_executor::unban(const std::string &ip) { if(!m_rpc_server->on_set_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -1485,12 +1507,12 @@ bool t_rpc_command_executor::flush_txpool(const std::string &txid) { if(!m_rpc_server->on_flush_txpool(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Pool successfully flushed"; + GULPS_PRINT_SUCCESS( "Pool successfully flushed"); return true; } @@ -1518,7 +1540,7 @@ bool t_rpc_command_executor::output_histogram(const std::vector &amoun { if(!m_rpc_server->on_get_output_histogram(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } @@ -1527,7 +1549,7 @@ bool t_rpc_command_executor::output_histogram(const std::vector &amoun [](const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e1, const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e2) -> bool { return e1.total_instances < e2.total_instances; }); for(const auto &e : res.histogram) { - tools::msg_writer() << e.total_instances << " " << cryptonote::print_money(e.amount); + GULPSF_PRINT_OK("{} {}", e.total_instances, cryptonote::print_money(e.amount)); } return true; @@ -1555,16 +1577,14 @@ bool t_rpc_command_executor::print_coinbase_tx_sum(uint64_t height, uint64_t cou { if(!m_rpc_server->on_get_coinbase_tx_sum(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::msg_writer() << "Sum of coinbase transactions between block heights [" - << height << ", " << (height + count) << ") is " - << cryptonote::print_money(res.emission_amount + res.fee_amount) << " " - << "consisting of " << cryptonote::print_money(res.emission_amount) - << " in emissions, and " << cryptonote::print_money(res.fee_amount) << " in fees"; + GULPSF_PRINT_OK("Sum of coinbase transactions between block heights [{}, {}) is {} consisting of {} in emissions, and {} in fees", height , (height + count) , cryptonote::print_money(res.emission_amount + res.fee_amount) + , cryptonote::print_money(res.emission_amount) + , cryptonote::print_money(res.fee_amount) ); return true; } @@ -1593,22 +1613,22 @@ bool t_rpc_command_executor::alt_chain_info() { if(!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, ires.status); + GULPS_PRINT_FAIL( make_error(fail_message, ires.status)); return true; } if(!m_rpc_server->on_get_alternate_chains(req, res, error_resp)) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::msg_writer() << boost::lexical_cast(res.chains.size()) << " alternate chains found:"; + GULPS_PRINT_OK(boost::lexical_cast(res.chains.size()), " alternate chains found:"); for(const auto &chain : res.chains) { uint64_t start_height = (chain.height - chain.length + 1); - tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1) - << " deep), diff " << chain.difficulty << ": " << chain.block_hash; + GULPSF_PRINT_OK("{} blocks long, from height {} ({} deep), diff {}: {}", chain.length , start_height , (ires.height - start_height - 1) + , chain.difficulty , chain.block_hash); } return true; } @@ -1634,13 +1654,13 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) { if(!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, ires.status); + GULPS_PRINT_FAIL( make_error(fail_message, ires.status)); return true; } } - tools::msg_writer() << "Height: " << ires.height << ", diff " << ires.difficulty << ", cum. diff " << ires.cumulative_difficulty - << ", target " << ires.target << " sec"; + GULPSF_PRINT_OK("Height: {}, diff {}, cum. diff {}, target {} sec", ires.height , ires.difficulty , ires.cumulative_difficulty + , ires.target); if(nblocks > 0) { @@ -1660,7 +1680,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) { if(!m_rpc_server->on_get_block_headers_range(bhreq, bhres, error_resp) || bhres.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, bhres.status); + GULPS_PRINT_FAIL( make_error(fail_message, bhres.status)); return true; } } @@ -1689,8 +1709,8 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) avgnumtxes /= nblocks; avgreward /= nblocks; uint64_t median_block_size = epee::misc_utils::median(sizes); - tools::msg_writer() << "Last " << nblocks << ": avg. diff " << (uint64_t)avgdiff << ", " << (latest - earliest) / nblocks << " avg sec/block, avg num txes " << avgnumtxes - << ", avg. reward " << cryptonote::print_money(avgreward) << ", median block size " << median_block_size; + GULPSF_PRINT_OK("Last {}: avg. diff {}, {} avg sec/block, avg num txes {}, avg. reward {}, median block size {}", nblocks , (uint64_t)avgdiff , (latest - earliest) / nblocks , avgnumtxes + , cryptonote::print_money(avgreward) , median_block_size); unsigned int max_major = 256, max_minor = 256; while(max_major > 0 && !major_versions[--max_major]) @@ -1701,12 +1721,12 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) for(unsigned n = 0; n <= max_major; ++n) if(major_versions[n]) s += (s.empty() ? "" : ", ") + boost::lexical_cast(major_versions[n]) + std::string(" v") + boost::lexical_cast(n); - tools::msg_writer() << "Block versions: " << s; + GULPSF_PRINT_OK("Block versions: {}", s); s = ""; for(unsigned n = 0; n <= max_minor; ++n) if(minor_versions[n]) s += (s.empty() ? "" : ", ") + boost::lexical_cast(minor_versions[n]) + std::string(" v") + boost::lexical_cast(n); - tools::msg_writer() << "Voting for: " << s; + GULPSF_PRINT_OK("Voting for: {}", s); } return true; } @@ -1731,29 +1751,29 @@ bool t_rpc_command_executor::update(const std::string &command) { if(!m_rpc_server->on_update(req, res) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } if(!res.update) { - tools::msg_writer() << "No update available"; + GULPS_PRINT_OK( "No update available"); return true; } - tools::msg_writer() << "Update available: v" << res.version << ": " << res.user_uri << ", hash " << res.hash; + GULPSF_PRINT_OK("Update available: v{}: {}, hash {}", res.version , res.user_uri , res.hash); if(command == "check") return true; if(!res.path.empty()) - tools::msg_writer() << "Update downloaded to: " << res.path; + GULPSF_PRINT_OK("Update downloaded to: {}", res.path); else - tools::msg_writer() << "Update download failed: " << res.status; + GULPSF_PRINT_OK("Update download failed: {}", res.status); if(command == "download") return true; - tools::msg_writer() << "'update' not implemented yet"; + GULPS_PRINT_OK( "'update' not implemented yet"); return true; } @@ -1778,12 +1798,12 @@ bool t_rpc_command_executor::relay_tx(const std::string &txid) { if(!m_rpc_server->on_relay_tx(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } - tools::success_msg_writer() << "Transaction successfully relayed"; + GULPS_PRINT_SUCCESS( "Transaction successfully relayed"); return true; } @@ -1805,19 +1825,19 @@ bool t_rpc_command_executor::sync_info() { if(!m_rpc_server->on_sync_info(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK) { - tools::fail_msg_writer() << make_error(fail_message, res.status); + GULPS_PRINT_FAIL( make_error(fail_message, res.status)); return true; } } uint64_t target = res.target_height < res.height ? res.height : res.target_height; - tools::success_msg_writer() << "Height: " << res.height << ", target: " << target << " (" << (100.0 * res.height / target) << "%)"; + GULPSF_PRINT_SUCCESS("Height: {}, target: {} ({}%)", res.height, target, (100.0 * res.height / target)); uint64_t current_download = 0; for(const auto &p : res.peers) current_download += p.info.current_download; - tools::success_msg_writer() << "Downloading at " << current_download << " kB/s"; + GULPS_PRINT_CLR(gulps::COLOR_GREEN,"Downloading at ", current_download, " kB/s"); - tools::success_msg_writer() << std::to_string(res.peers.size()) << " peers"; + GULPS_PRINT_SUCCESS(std::to_string(res.peers.size()), " peers"); for(const auto &p : res.peers) { std::string address = epee::string_tools::pad_string(p.info.address, 24); @@ -1825,23 +1845,23 @@ bool t_rpc_command_executor::sync_info() for(const auto &s : res.spans) if(s.rate > 0.0f && s.connection_id == p.info.connection_id) nblocks += s.nblocks, size += s.size; - tools::success_msg_writer() << address << " " << epee::string_tools::pad_string(p.info.peer_id, 16, '0', true) << " " << p.info.height << " " << p.info.current_download << " kB/s, " << nblocks << " blocks / " << size / 1e6 << " MB queued"; + GULPSF_PRINT_SUCCESS("{} {} {} {} kB/s, {} blocks / {} MB queued", address, epee::string_tools::pad_string(p.info.peer_id, 16, '0', true), p.info.height, p.info.current_download, nblocks, size / 1e6); } uint64_t total_size = 0; for(const auto &s : res.spans) total_size += s.size; - tools::success_msg_writer() << std::to_string(res.spans.size()) << " spans, " << total_size / 1e6 << " MB"; + GULPSF_PRINT_SUCCESS("{} spand, {} MB", std::to_string(res.spans.size()), total_size / 1e6); for(const auto &s : res.spans) { std::string address = epee::string_tools::pad_string(s.remote_address, 24); if(s.size == 0) { - tools::success_msg_writer() << address << " " << s.nblocks << " (" << s.start_block_height << " - " << (s.start_block_height + s.nblocks - 1) << ") -"; + GULPSF_PRINT_SUCCESS("{} {} ({} - {}) -", address, s.nblocks, s.start_block_height, (s.start_block_height + s.nblocks - 1)); } else { - tools::success_msg_writer() << address << " " << s.nblocks << " (" << s.start_block_height << " - " << (s.start_block_height + s.nblocks - 1) << ", " << (uint64_t)(s.size / 1e3) << " kB) " << (unsigned)(s.rate / 1e3) << " kB/s (" << s.speed / 100.0f << ")"; + GULPSF_PRINT_SUCCESS("{} {} ({} - {}, {}kB) {} kB/s ({})", address, s.nblocks, s.start_block_height, (s.start_block_height + s.nblocks - 1), (uint64_t)(s.size / 1e3), (unsigned)(s.rate / 1e3), s.speed / 100.0f); } } diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index dd8c62ee..c8d37654 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -6,7 +6,7 @@ */ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -35,8 +35,7 @@ #include "cryptonote_basic/cryptonote_basic.h" #include "rpc/core_rpc_server.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { diff --git a/src/daemonizer/CMakeLists.txt b/src/daemonizer/CMakeLists.txt index 622b1792..6ec44b37 100644 --- a/src/daemonizer/CMakeLists.txt +++ b/src/daemonizer/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -86,5 +86,6 @@ target_link_libraries(daemonizer ${Boost_CHRONO_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/daemonizer/daemonizer.h b/src/daemonizer/daemonizer.h index a0ff7e4c..31763e99 100644 --- a/src/daemonizer/daemonizer.h +++ b/src/daemonizer/daemonizer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/daemonizer/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl index 44d78c3c..bae127f6 100644 --- a/src/daemonizer/posix_daemonizer.inl +++ b/src/daemonizer/posix_daemonizer.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -25,8 +25,12 @@ #include #include +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) + namespace daemonizer { +GULPS_CAT_MAJOR("posix_dmnzer"); +extern gulps_log_level log_scr, log_dsk; namespace { const command_line::arg_descriptor arg_detach = { @@ -62,9 +66,10 @@ inline bool daemonize( , boost::program_options::variables_map const &vm) { + if(command_line::has_arg(vm, arg_detach)) { - tools::success_msg_writer() << "Forking to background..."; + GULPS_PRINT_OK("Forking to background..."); std::string pidfile; if(command_line::has_arg(vm, arg_pidfile)) { @@ -80,7 +85,7 @@ inline bool daemonize( } else { - //LOG_PRINT_L0("Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL); + //GULPS_PRINT("Ryo '", RYO_RELEASE_NAME, " (", RYO_VERSION_FULL, ")"); return executor.run_interactive(vm); } } diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp index 6dad2880..7b744819 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -5,7 +5,6 @@ // #include "daemonizer/posix_fork.h" -#include "misc_log_ex.h" #include #include @@ -13,19 +12,23 @@ #include #include #include +#include #ifndef TMPDIR #define TMPDIR "/tmp" #endif +#include "common/gulps.hpp" + + namespace posix { - + GULPS_CAT_MAJOR("posix_fork"); namespace { void quit(const std::string &message) { - LOG_ERROR(message); + GULPS_ERROR(message); throw std::runtime_error(message); } } diff --git a/src/daemonizer/posix_fork.h b/src/daemonizer/posix_fork.h index 7df689e5..4d71c8a7 100644 --- a/src/daemonizer/posix_fork.h +++ b/src/daemonizer/posix_fork.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 45ff7357..ccb621b6 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -28,6 +28,9 @@ namespace daemonizer { +GULPS_CAT_MAJOR("win_dmnzer"); +extern gulps_log_level log_scr, log_dsk; + namespace { const command_line::arg_descriptor arg_install_service = { @@ -147,7 +150,6 @@ inline bool daemonize( } else // interactive { - //LOG_PRINT_L0("Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL); return executor.run_interactive(vm); } diff --git a/src/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp index 0d8ba991..0d1839f1 100644 --- a/src/daemonizer/windows_service.cpp +++ b/src/daemonizer/windows_service.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -33,9 +33,16 @@ #include #include +#include "common/gulps.hpp" + + +#define GULPS_PRINT_FAIL(...) GULPS_ERROR("Error: ", __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) + + namespace windows { - +GULPS_CAT_MAJOR("win_ser"); namespace { typedef std::unique_ptr::type, decltype(&::CloseServiceHandle)> service_handle; @@ -71,7 +78,7 @@ bool relaunch_as_admin( info.nShow = SW_SHOWNORMAL; if(!ShellExecuteEx(&info)) { - tools::fail_msg_writer() << "Admin relaunch failed: " << get_last_error(); + GULPS_PRINT_FAIL("Admin relaunch failed: ", get_last_error()); return false; } else @@ -99,14 +106,14 @@ bool check_admin(bool &result) if(!AllocateAndInitializeSid( &nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &p_administrators_group)) { - tools::fail_msg_writer() << "Security Identifier creation failed: " << get_last_error(); + GULPS_PRINT_FAIL("Security Identifier creation failed: ", get_last_error()); return false; } if(!CheckTokenMembership( nullptr, p_administrators_group, &is_admin)) { - tools::fail_msg_writer() << "Permissions check failed: " << get_last_error(); + GULPS_PRINT_FAIL("Permissions check failed: ", get_last_error()); return false; } @@ -149,7 +156,7 @@ bool install_service( &::CloseServiceHandle}; if(p_manager == nullptr) { - tools::fail_msg_writer() << "Couldn't connect to service manager: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't connect to service manager: ", get_last_error()); return false; } @@ -167,11 +174,11 @@ bool install_service( &::CloseServiceHandle}; if(p_service == nullptr) { - tools::fail_msg_writer() << "Couldn't create service: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't create service: ", get_last_error()); return false; } - tools::success_msg_writer() << "Service installed"; + GULPS_PRINT_FAIL("Service installed", get_last_error()); pause_to_display_admin_window_messages(); @@ -181,7 +188,7 @@ bool install_service( bool start_service( std::string const &service_name) { - tools::msg_writer() << "Starting service"; + GULPS_INFO("Starting service"); SERVICE_STATUS_PROCESS service_status = {}; DWORD unused = 0; @@ -192,7 +199,7 @@ bool start_service( &::CloseServiceHandle}; if(p_manager == nullptr) { - tools::fail_msg_writer() << "Couldn't connect to service manager: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't connect to service manager: ", get_last_error()); return false; } @@ -205,18 +212,18 @@ bool start_service( &::CloseServiceHandle}; if(p_service == nullptr) { - tools::fail_msg_writer() << "Couldn't find service: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't find service: ", get_last_error()); return false; } if(!StartService( p_service.get(), 0, nullptr)) { - tools::fail_msg_writer() << "Service start request failed: " << get_last_error(); + GULPS_PRINT_FAIL("Service start request failed: ", get_last_error()); return false; } - tools::success_msg_writer() << "Service started"; + GULPS_PRINT_FAIL("Service started", get_last_error()); pause_to_display_admin_window_messages(); @@ -226,7 +233,7 @@ bool start_service( bool stop_service( std::string const &service_name) { - tools::msg_writer() << "Stopping service"; + GULPS_INFO("Stopping service"); service_handle p_manager{ OpenSCManager( @@ -234,7 +241,7 @@ bool stop_service( &::CloseServiceHandle}; if(p_manager == nullptr) { - tools::fail_msg_writer() << "Couldn't connect to service manager: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't connect to service manager: ", get_last_error()); return false; } @@ -244,18 +251,18 @@ bool stop_service( &::CloseServiceHandle}; if(p_service == nullptr) { - tools::fail_msg_writer() << "Couldn't find service: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't find service: ", get_last_error()); return false; } SERVICE_STATUS status = {}; if(!ControlService(p_service.get(), SERVICE_CONTROL_STOP, &status)) { - tools::fail_msg_writer() << "Couldn't request service stop: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't request service stop: ", get_last_error()); return false; } - tools::success_msg_writer() << "Service stopped"; + GULPS_PRINT_FAIL("Service stopped", get_last_error()); pause_to_display_admin_window_messages(); @@ -271,7 +278,7 @@ bool uninstall_service( &::CloseServiceHandle}; if(p_manager == nullptr) { - tools::fail_msg_writer() << "Couldn't connect to service manager: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't connect to service manager: ", get_last_error()); return false; } @@ -281,18 +288,18 @@ bool uninstall_service( &::CloseServiceHandle}; if(p_service == nullptr) { - tools::fail_msg_writer() << "Couldn't find service: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't find service: ", get_last_error()); return false; } SERVICE_STATUS status = {}; if(!DeleteService(p_service.get())) { - tools::fail_msg_writer() << "Couldn't uninstall service: " << get_last_error(); + GULPS_PRINT_FAIL("Couldn't uninstall service: ", get_last_error()); return false; } - tools::success_msg_writer() << "Service uninstalled"; + GULPS_PRINT_FAIL("Service uninstalled", get_last_error()); pause_to_display_admin_window_messages(); diff --git a/src/daemonizer/windows_service.h b/src/daemonizer/windows_service.h index 5ba71890..b6362648 100644 --- a/src/daemonizer/windows_service.h +++ b/src/daemonizer/windows_service.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/daemonizer/windows_service_runner.h b/src/daemonizer/windows_service_runner.h index 6704df92..0b9a1fe0 100644 --- a/src/daemonizer/windows_service_runner.h +++ b/src/daemonizer/windows_service_runner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/debug_utilities/CMakeLists.txt b/src/debug_utilities/CMakeLists.txt index 4d3bf3b4..5ee972bf 100644 --- a/src/debug_utilities/CMakeLists.txt +++ b/src/debug_utilities/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 diff --git a/src/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp index da5fb771..91cc1a78 100644 --- a/src/debug_utilities/cn_deserialize.cpp +++ b/src/debug_utilities/cn_deserialize.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 "common/command_line.h" #include "cryptonote_basic/cryptonote_basic.h" #include "cryptonote_basic/tx_extra.h" @@ -23,33 +24,36 @@ #include "version.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "debugtools.deserialize" +#include "common/gulps.hpp" + + + namespace po = boost::program_options; using namespace epee; using namespace cryptonote; +GULPS_CAT_MAJOR("cn_deser"); + static void print_extra_fields(const std::vector &fields) { - std::cout << "tx_extra has " << fields.size() << " field(s)" << std::endl; + GULPSF_PRINT("tx_extra has {} field(s)", fields.size() ); for(size_t n = 0; n < fields.size(); ++n) { - std::cout << "field " << n << ": "; + GULPSF_PRINT("field {}: ", n ); if(typeid(cryptonote::tx_extra_padding) == fields[n].type()) - std::cout << "extra padding: " << boost::get(fields[n]).size << " bytes"; + GULPSF_PRINT("extra padding: {} bytes", boost::get(fields[n]).size); else if(typeid(cryptonote::tx_extra_pub_key) == fields[n].type()) - std::cout << "extra pub key: " << boost::get(fields[n]).pub_key; + GULPSF_PRINT("extra pub key: {}", boost::get(fields[n]).pub_key); else if(typeid(cryptonote::tx_extra_nonce) == fields[n].type()) - std::cout << "extra nonce: " << epee::string_tools::buff_to_hex_nodelimer(boost::get(fields[n]).nonce); + GULPSF_PRINT("extra nonce: {}", epee::string_tools::buff_to_hex_nodelimer(boost::get(fields[n]).nonce)); else if(typeid(cryptonote::tx_extra_merge_mining_tag) == fields[n].type()) - std::cout << "extra merge mining tag: depth " << boost::get(fields[n]).depth << ", merkle root " << boost::get(fields[n]).merkle_root; + GULPSF_PRINT("extra merge mining tag: depth {}, merkle root {}", boost::get(fields[n]).depth , boost::get(fields[n]).merkle_root); else if(typeid(cryptonote::tx_extra_mysterious_minergate) == fields[n].type()) - std::cout << "extra minergate custom: " << epee::string_tools::buff_to_hex_nodelimer(boost::get(fields[n]).data); + GULPSF_PRINT("extra minergate custom: {}", epee::string_tools::buff_to_hex_nodelimer(boost::get(fields[n]).data)); else - std::cout << "unknown"; - std::cout << std::endl; + GULPS_PRINT("unknown"); } } @@ -86,10 +90,16 @@ int main(int argc, char *argv[]) if(!r) return 1; + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + return msg.lvl >= gulps::LEVEL_PRINT; + }); + gulps::inst().add_output(std::move(out)); + if(command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; + GULPSF_PRINT("Ryo '{} ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); + GULPS_PRINT( desc_options ); return 0; } @@ -97,12 +107,10 @@ int main(int argc, char *argv[]) input = command_line::get_arg(vm, arg_input); if(input.empty()) { - std::cerr << "--input is mandatory" << std::endl; + GULPS_ERROR("--input is mandatory"); return 1; } - mlog_configure("", true); - std::string m_config_folder; std::ostream *output; @@ -118,7 +126,7 @@ int main(int argc, char *argv[]) { if(!boost::filesystem::is_directory(dir_path)) { - std::cerr << "output directory path is a file: " << dir_path << std::endl; + GULPS_ERROR("output directory path is a file: ", dir_path); return 1; } } @@ -126,7 +134,7 @@ int main(int argc, char *argv[]) { if(!boost::filesystem::create_directory(dir_path)) { - std::cerr << "Failed to create directory " << dir_path << std::endl; + GULPS_ERROR("Failed to create directory ", dir_path); return 1; } } @@ -147,8 +155,8 @@ int main(int argc, char *argv[]) cryptonote::blobdata blob; if(!epee::string_tools::parse_hexstr_to_binbuff(input, blob)) { - std::cerr << "Invalid hex input" << std::endl; - std::cerr << "Invalid hex input: " << input << std::endl; + GULPS_ERROR("Invalid hex input"); + GULPS_ERROR("Invalid hex input: ", input); return 1; } @@ -157,17 +165,17 @@ int main(int argc, char *argv[]) std::vector fields; if(cryptonote::parse_and_validate_block_from_blob(blob, block)) { - std::cout << "Parsed block:" << std::endl; - std::cout << cryptonote::obj_to_json_str(block) << std::endl; + GULPS_PRINT("Parsed block:"); + GULPS_PRINT( cryptonote::obj_to_json_str(block) ); } else if(cryptonote::parse_and_validate_tx_from_blob(blob, tx)) { - std::cout << "Parsed transaction:" << std::endl; - std::cout << cryptonote::obj_to_json_str(tx) << std::endl; + GULPS_PRINT("Parsed transaction:"); + GULPS_PRINT( cryptonote::obj_to_json_str(tx) ); bool parsed = cryptonote::parse_tx_extra(tx.extra, fields); if(!parsed) - std::cout << "Failed to parse tx_extra" << std::endl; + GULPS_PRINT("Failed to parse tx_extra"); if(!fields.empty()) { @@ -175,17 +183,17 @@ int main(int argc, char *argv[]) } else { - std::cout << "No fields were found in tx_extra" << std::endl; + GULPS_PRINT("No fields were found in tx_extra"); } } else if(cryptonote::parse_tx_extra(std::vector(blob.begin(), blob.end()), fields) && !fields.empty()) { - std::cout << "Parsed tx_extra:" << std::endl; + GULPS_PRINT("Parsed tx_extra:"); print_extra_fields(fields); } else { - std::cerr << "Not a recognized CN type" << std::endl; + GULPS_ERROR("Not a recognized CN type"); return 1; } diff --git a/src/debug_utilities/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index a8c0018e..ee0461a4 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -33,16 +33,18 @@ #include "wallet/wallet2.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "debugtools.objectsizes" +#include "common/gulps.hpp" + + class size_logger { public: ~size_logger() { + GULPS_CAT_MAJOR("obj_sizes"); for(const auto &i : types) - std::cout << std::to_string(i.first) << "\t" << i.second << std::endl; + GULPSF_PRINT("{}\t{}",i.first, i.second); } void add(const char *type, size_t size) { types.insert(std::make_pair(size, type)); } private: @@ -56,7 +58,10 @@ int main(int argc, char *argv[]) tools::on_startup(); - mlog_configure("", true); + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TIMESTAMP_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { + return true; + }); SL(boost::thread); SL(boost::asio::io_service); diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 9b4a93d1..695fb27a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -85,6 +85,8 @@ target_link_libraries(device cncrypto ringct_basic ${OPENSSL_CRYPTO_LIBRARIES} + fmt::fmt-header-only PRIVATE ${Blocks} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) diff --git a/src/device/device.cpp b/src/device/device.cpp index 672afb40..e8376d8d 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -22,7 +22,8 @@ #ifdef HAVE_PCSC #include "device_ledger.hpp" #endif -#include "misc_log_ex.h" + +#include "common/gulps.hpp" namespace hw { @@ -50,12 +51,12 @@ device &get_device(const std::string device_descriptor) auto device = devices.registry.find(device_descriptor); if(device == devices.registry.end()) { - MERROR("device not found in registry: '" << device_descriptor << "'\n" - << "known devices:"); + GULPS_CAT_MAJOR("device"); + GULPS_ERROR("device not found in registry: '", device_descriptor, "'\nknown devices:"); for(const auto &sm_pair : devices.registry) { - MERROR(" - " << sm_pair.first); + GULPS_ERROR(" - " , sm_pair.first); } throw std::runtime_error("device not found: " + device_descriptor); } diff --git a/src/device/device.hpp b/src/device/device.hpp index 2acea071..83594992 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -119,6 +119,9 @@ class device /* SUB ADDRESS */ /* ======================================================================= */ virtual bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) = 0; +#ifdef HAVE_EC_64 + virtual bool derive_subaddress_public_key_64(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) = 0; +#endif virtual crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) = 0; virtual std::vector get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) = 0; virtual cryptonote::account_public_address get_subaddress(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) = 0; @@ -133,6 +136,9 @@ class device virtual bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) = 0; virtual crypto::secret_key generate_legacy_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key &recovery_key = crypto::secret_key(), bool recover = false) = 0; virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0; +#ifdef HAVE_EC_64 + virtual bool generate_key_derivation_64(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0; +#endif virtual bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) = 0; virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) = 0; virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0; @@ -174,7 +180,7 @@ class device // Encryption and decryption are the same operation (xor with a key) return encrypt_payment_id(payment_id, public_key, secret_key); } - + virtual bool ecdhEncode(rct::ecdhTuple &unmasked, const rct::key &sharedSec) = 0; virtual bool ecdhDecode(rct::ecdhTuple &masked, const rct::key &sharedSec) = 0; diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index d1738180..0bd85a4f 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -127,6 +127,12 @@ bool device_default::derive_subaddress_public_key(const crypto::public_key &out_ { return crypto::derive_subaddress_public_key(out_key, derivation, output_index, derived_key); } +#ifdef HAVE_EC_64 +bool device_default::derive_subaddress_public_key_64(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_key) +{ + return crypto::derive_subaddress_public_key_64(out_key, derivation, output_index, derived_key); +} +#endif crypto::public_key device_default::get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) { @@ -147,15 +153,15 @@ crypto::public_key device_default::get_subaddress_spend_public_key(const crypton std::vector device_default::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { - CHECK_AND_ASSERT_THROW_MES(begin <= end, "begin > end"); + GULPS_CHECK_AND_ASSERT_THROW_MES(begin <= end, "begin > end"); std::vector pkeys; pkeys.reserve(end - begin); - cryptonote::subaddress_index index = {account, begin}; + cryptonote::subaddress_index index(account, begin); ge_p3 p3; ge_cached cached; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char *)keys.m_account_address.m_spend_public_key.data) == 0, + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char *)keys.m_account_address.m_spend_public_key.data) == 0, "ge_frombytes_vartime failed to convert spend public key"); ge_p3_to_cached(&cached, &p3); @@ -254,6 +260,12 @@ bool device_default::generate_key_derivation(const crypto::public_key &key1, con { return crypto::generate_key_derivation(key1, key2, derivation); } +#ifdef HAVE_EC_64 +bool device_default::generate_key_derivation_64(const crypto::public_key &key1, const crypto::secret_key &key2, crypto::key_derivation &derivation) +{ + return crypto::generate_key_derivation_64(key1, key2, derivation); +} +#endif bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) { @@ -383,10 +395,10 @@ bool device_default::mlsag_hash(const rct::keyV &toHash, rct::key &c_old) bool device_default::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) { - CHECK_AND_ASSERT_THROW_MES(dsRows <= rows, "dsRows greater than rows"); - CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows"); - CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match rows"); - CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match rows"); + GULPS_CHECK_AND_ASSERT_THROW_MES(dsRows <= rows, "dsRows greater than rows"); + GULPS_CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows"); + GULPS_CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match rows"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match rows"); for(size_t j = 0; j < rows; j++) { sc_mulsub(ss[j].bytes, c.bytes, xx[j].bytes, alpha[j].bytes); diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index f65d1d90..28e307a7 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,6 +20,7 @@ #pragma once #include "device.hpp" +#include "common/gulps.hpp" namespace hw { @@ -31,6 +32,7 @@ void register_all(std::map> ®istry); class device_default : public hw::device { + GULPS_CAT_MAJOR("device"); public: device_default(); ~device_default(); @@ -72,6 +74,9 @@ class device_default : public hw::device /* SUB ADDRESS */ /* ======================================================================= */ bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; +#ifdef HAVE_EC_64 + bool derive_subaddress_public_key_64(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override; +#endif crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) override; std::vector get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override; cryptonote::account_public_address get_subaddress(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) override; @@ -86,6 +91,9 @@ class device_default : public hw::device bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; crypto::secret_key generate_legacy_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key &recovery_key = crypto::secret_key(), bool recover = false) override; bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; +#ifdef HAVE_EC_64 + bool generate_key_derivation_64(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; +#endif bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector &additional_derivations) override; bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; @@ -101,7 +109,7 @@ class device_default : public hw::device bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool encrypt_payment_id(crypto::uniform_payment_id &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; - + bool ecdhEncode(rct::ecdhTuple &unmasked, const rct::key &sharedSec) override; bool ecdhDecode(rct::ecdhTuple &masked, const rct::key &sharedSec) override; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index 05d005c9..fad1e468 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -35,7 +35,7 @@ namespace ledger #ifdef WITH_DEVICE_LEDGER //#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "device.ledger" +//#define RYO_DEFAULT_LOG_CATEGORY /* ===================================================================== */ /* === Debug ==== */ diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 9f784f6f..70d0d157 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/device/log.cpp b/src/device/log.cpp index edfca7a5..8ca93bec 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -18,7 +18,7 @@ // #include "log.hpp" -#include "misc_log_ex.h" +#include "common/gulps.hpp" namespace hw { @@ -27,8 +27,7 @@ namespace hw namespace ledger { -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "device.ledger" +//undef RYO_DEFAULT_LOG_CATEGORY void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) { diff --git a/src/device/log.hpp b/src/device/log.hpp index 21843adb..92f60591 100644 --- a/src/device/log.hpp +++ b/src/device/log.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/gen_multisig/CMakeLists.txt b/src/gen_multisig/CMakeLists.txt index c9858181..d7a79d0e 100644 --- a/src/gen_multisig/CMakeLists.txt +++ b/src/gen_multisig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -62,7 +62,8 @@ target_link_libraries(gen_multisig ${Boost_LOCALE_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${GNU_READLINE_LIBRARY} - ${EXTRA_LIBRARIES}) + ${EXTRA_LIBRARIES} + fmt::fmt-header-only) add_dependencies(gen_multisig version) set_property(TARGET gen_multisig diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index 64bf2288..3184925c 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,31 +20,36 @@ /*! * \file gen_multisig.cpp - * + * * \brief Generates a set of multisig wallets */ + #include "common/command_line.h" #include "common/i18n.h" -#include "common/scoped_message_writer.h" #include "common/util.h" #include "crypto/crypto.h" // for crypto::secret_key definition #include "include_base_utils.h" #include "wallet/wallet2.h" #include "wallet/wallet_args.h" #include -#include #include #include #include +#include "common/gulps.hpp" + +#define GULPS_PRINT_FAIL(...) GULPS_ERROR(tr("Error: "), __VA_ARGS__) +#define GULPSF_PRINT_FAIL(...) GULPSF_ERROR(tr("Error: "), __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) +#define GULPSF_PRINT_OK(...) GULPSF_PRINT(__VA_ARGS__) + using namespace std; using namespace epee; using namespace cryptonote; using boost::lexical_cast; namespace po = boost::program_options; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "wallet.gen_multisig" +GULPS_CAT_MAJOR("gen_multisig"); namespace genms { @@ -69,7 +74,7 @@ const command_line::arg_descriptor> arg_command = {"com static bool generate_multisig(uint32_t threshold, uint32_t total, const std::string &basename, network_type nettype, bool create_address_file) { - tools::msg_writer() << (boost::format(genms::tr("Generating %u %u/%u multisig wallets")) % total % threshold % total).str(); + GULPSF_PRINT_OK(genms::tr("Generating {} {}/{} multisig wallets"), total, threshold, total); const auto pwd_container = tools::password_container::prompt(true, "Enter password for new multisig wallets"); @@ -93,7 +98,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str { if(!tools::wallet2::verify_multisig_info(wallets[n]->get_multisig_info(), sk[n], pk[n])) { - tools::fail_msg_writer() << tr("Failed to verify multisig info"); + GULPS_PRINT_FAIL( tr("Failed to verify multisig info")); return false; } } @@ -127,7 +132,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str { if(!tools::wallet2::verify_extra_multisig_info(extra_info[n], pkeys, signers[n])) { - tools::fail_msg_writer() << genms::tr("Error verifying multisig extra info"); + GULPS_PRINT_FAIL( genms::tr("Error verifying multisig extra info")); return false; } } @@ -135,19 +140,18 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const std::str { if(!wallets[n]->finalize_multisig(pwd_container->password(), pkeys, signers)) { - tools::fail_msg_writer() << genms::tr("Error finalizing multisig"); + GULPS_PRINT_FAIL( genms::tr("Error finalizing multisig")); return false; } } } std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype()); - tools::success_msg_writer() << genms::tr("Generated multisig wallets for address ") << address << std::endl - << ss.str(); + GULPSF_PRINT_OK(genms::tr("Generated multisig wallets for address {}\n{}"), address, ss.str()); } catch(const std::exception &e) { - tools::fail_msg_writer() << genms::tr("Error creating multisig wallets: ") << e.what(); + GULPS_PRINT_FAIL( genms::tr("Error creating multisig wallets: ") , e.what()); return false; } @@ -166,6 +170,13 @@ int main(int argc, char *argv[]) } #endif + gulps::inst().set_thread_tag("GEN_MULTISIG"); + + //Ordinary output + std::unique_ptr out(new gulps::gulps_print_output(gulps::COLOR_WHITE, gulps::TEXT_ONLY)); + out->add_filter([](const gulps::message& msg, bool printed, bool logged) -> bool { return msg.out == gulps::OUT_USER_0 && msg.lvl <= gulps::LEVEL_WARN; }); + gulps::inst().add_output(std::move(out)); + po::options_description desc_params(wallet_args::tr("Wallet options")); command_line::add_arg(desc_params, arg_filename_base); command_line::add_arg(desc_params, arg_scheme); @@ -182,9 +193,11 @@ int main(int argc, char *argv[]) genms::tr("This program generates a set of multisig wallets - use this simpler scheme only if all the participants trust each other"), desc_params, boost::program_options::positional_options_description(), - [](const std::string &s, bool emphasis) { tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; }, + /*[](const std::string &s, bool emphasis) { tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; }, + * \todo-gulps*/ "ryo-gen-multisig.log", - vm_error_code); + vm_error_code, + true); if(!vm) return vm_error_code; @@ -196,14 +209,14 @@ int main(int argc, char *argv[]) stagenet = command_line::get_arg(*vm, arg_stagenet); if(testnet && stagenet) { - tools::fail_msg_writer() << genms::tr("Error: Can't specify more than one of --testnet and --stagenet"); + GULPS_PRINT_FAIL( genms::tr("Error: Can't specify more than one of --testnet and --stagenet")); return 1; } if(command_line::has_arg(*vm, arg_scheme)) { if(sscanf(command_line::get_arg(*vm, arg_scheme).c_str(), "%u/%u", &threshold, &total) != 2) { - tools::fail_msg_writer() << genms::tr("Error: expected N/M, but got: ") << command_line::get_arg(*vm, arg_scheme); + GULPS_PRINT_FAIL( genms::tr("Error: expected N/M, but got: ") , command_line::get_arg(*vm, arg_scheme)); return 1; } } @@ -211,7 +224,7 @@ int main(int argc, char *argv[]) { if(threshold) { - tools::fail_msg_writer() << genms::tr("Error: either --scheme or both of --threshold and --participants may be given"); + GULPS_PRINT_FAIL( genms::tr("Error: either --scheme or both of --threshold and --participants may be given")); return 1; } threshold = command_line::get_arg(*vm, arg_threshold); @@ -220,14 +233,14 @@ int main(int argc, char *argv[]) { if(total) { - tools::fail_msg_writer() << genms::tr("Error: either --scheme or both of --threshold and --participants may be given"); + GULPS_PRINT_FAIL( genms::tr("Error: either --scheme or both of --threshold and --participants may be given")); return 1; } total = command_line::get_arg(*vm, arg_participants); } if(threshold <= 1 || threshold > total) { - tools::fail_msg_writer() << (boost::format(genms::tr("Error: expected N > 1 and N <= M, but got N==%u and M==%d")) % threshold % total).str(); + GULPSF_PRINT_FAIL( (genms::tr("Error: expected N > 1 and N <= M, but got N=={} and M=={}")), threshold, total); return 1; } if(!(*vm)["filename-base"].defaulted() && !command_line::get_arg(*vm, arg_filename_base).empty()) @@ -236,13 +249,13 @@ int main(int argc, char *argv[]) } else { - tools::fail_msg_writer() << genms::tr("Error: --filename-base is required"); + GULPS_PRINT_FAIL( genms::tr("Error: --filename-base is required")); return 1; } if(threshold != total - 1 && threshold != total) { - tools::fail_msg_writer() << genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported"); + GULPS_PRINT_FAIL( genms::tr("Error: unsupported scheme: only N/N and N-1/N are supported")); return 1; } bool create_address_file = command_line::get_arg(*vm, arg_create_address_file); @@ -250,5 +263,5 @@ int main(int argc, char *argv[]) return 1; return 0; - //CATCH_ENTRY_L0("main", 1); + //GULPS_CATCH_ENTRY_L0("main", 1); } diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index 3a304cdf..598d57ce 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -73,8 +73,8 @@ ryo_add_library(mnemonics target_link_libraries(mnemonics PUBLIC epee - easylogging ${Boost_SYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE common ${Boost_LOCALE_LIBRARY} diff --git a/src/mnemonics/dutch.h b/src/mnemonics/dutch.h index 20788034..19c29a18 100644 --- a/src/mnemonics/dutch.h +++ b/src/mnemonics/dutch.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index bf4cb399..3e486df6 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -26,14 +26,15 @@ * that method of "backing up" one's wallet keys. */ -#include "mnemonics/electrum-words.h" -#include "crypto/crypto.h" // for declaration of crypto::secret_key #include #include #include #include #include #include "common/boost_locale.hpp" + +#include "mnemonics/electrum-words.h" +#include "crypto/crypto.h" // for declaration of crypto::secret_key #include #include #include diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h index aa10fc2f..f0759128 100644 --- a/src/mnemonics/electrum-words.h +++ b/src/mnemonics/electrum-words.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/english.h b/src/mnemonics/english.h index c8fbd393..a9a77b18 100644 --- a/src/mnemonics/english.h +++ b/src/mnemonics/english.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/esperanto.h b/src/mnemonics/esperanto.h index ee0e415c..118e5db6 100644 --- a/src/mnemonics/esperanto.h +++ b/src/mnemonics/esperanto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/french.h b/src/mnemonics/french.h index be6ff06d..c2724e72 100644 --- a/src/mnemonics/french.h +++ b/src/mnemonics/french.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/german.h b/src/mnemonics/german.h index d2f96eea..545e2879 100644 --- a/src/mnemonics/german.h +++ b/src/mnemonics/german.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor Shrikez // -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/italian.h b/src/mnemonics/italian.h index 93665fc3..9ce1a11d 100644 --- a/src/mnemonics/italian.h +++ b/src/mnemonics/italian.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor Shrikez // -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/language_base.h b/src/mnemonics/language_base.h index 46bfbcae..98dafe38 100644 --- a/src/mnemonics/language_base.h +++ b/src/mnemonics/language_base.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,18 +30,19 @@ /*! * \file language_base.h - * + * * \brief Language Base class for Polymorphism. */ #ifndef LANGUAGE_BASE_H #define LANGUAGE_BASE_H -#include "misc_log_ex.h" #include #include #include +#include "common/gulps.hpp" + /*! * \namespace Language * \brief Mnemonic language related namespace. @@ -75,6 +76,7 @@ inline std::string utf8prefix(const std::string &s, size_t count) */ class Base { + GULPS_CAT_MAJOR("lan_base"); protected: enum { @@ -102,7 +104,7 @@ class Base if((*it).size() < unique_prefix_length) { if(flags & ALLOW_SHORT_WORDS) - MWARNING(language_name << " word '" << *it << "' is shorter than its prefix length, " << unique_prefix_length); + GULPS_LOG_L2("{} word {}' is shorter than its prefix length, {}'", language_name, *it, unique_prefix_length); else throw std::runtime_error("Too short word in " + language_name + " word list: " + *it); } @@ -118,7 +120,7 @@ class Base if(trimmed_word_map.find(trimmed) != trimmed_word_map.end()) { if(flags & ALLOW_DUPLICATE_PREFIXES) - MWARNING("Duplicate prefix in " << language_name << " word list: " << trimmed); + GULPS_WARN("Duplicate prefix in ", language_name, " word list: ", trimmed); else throw std::runtime_error("Duplicate prefix in " + language_name + " word list: " + trimmed); } diff --git a/src/mnemonics/lojban.h b/src/mnemonics/lojban.h index 6a9b09c0..d416950f 100644 --- a/src/mnemonics/lojban.h +++ b/src/mnemonics/lojban.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/russian.h b/src/mnemonics/russian.h index e945b961..b91fe96a 100644 --- a/src/mnemonics/russian.h +++ b/src/mnemonics/russian.h @@ -1,6 +1,6 @@ // Word list created by Monero contributor sammy007 // -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/mnemonics/singleton.h b/src/mnemonics/singleton.h index 2aff1712..0ffed8cc 100644 --- a/src/mnemonics/singleton.h +++ b/src/mnemonics/singleton.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/multisig/CMakeLists.txt b/src/multisig/CMakeLists.txt index 7526ce4d..2f4967e8 100644 --- a/src/multisig/CMakeLists.txt +++ b/src/multisig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -64,5 +64,6 @@ target_link_libraries(multisig cryptonote_basic common cncrypto + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index 3bf654bc..3d5e2a2b 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -24,8 +24,7 @@ #include "ringct/rctOps.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "multisig" + using namespace std; @@ -33,6 +32,7 @@ static const rct::key multisig_salt = {{'M', 'u', 'l', 't', 'i', 's', 'i', 'g', namespace cryptonote { +GULPS_CAT_MAJOR("multisig"); //----------------------------------------------------------------- crypto::secret_key get_multisig_blinded_secret_key(const crypto::secret_key &key) { @@ -47,7 +47,7 @@ void generate_multisig_N_N(const account_keys &keys, const std::vector, public epee::net_utils::i_connection_filter { + GULPS_CAT_MAJOR("net_node"); struct by_conn_id { }; @@ -255,11 +258,11 @@ class node_server : public epee::levin::levin_commands_handlerjoin(); // make sure the thread finishes - _info("Joined extra background net_node threads"); + GULPS_INFO("Joined extra background net_node threads"); } //debug functions @@ -273,7 +276,7 @@ class node_server : public epee::levin::levin_commands_handler #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.p2p" +#include "common/gulps.hpp" + +#define contextx_str(x) std::string("[" + epee::net_utils::print_connection_context_short(x) + "]") + + #define NET_MAKE_IP(b1, b2, b3, b4) ((LPARAM)(((DWORD)(b1) << 24) + ((DWORD)(b2) << 16) + ((DWORD)(b3) << 8) + ((DWORD)(b4)))) @@ -78,7 +81,7 @@ template bool node_server::init_config() { // - TRY_ENTRY(); + GULPS_TRY_ENTRY(); std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME; std::ifstream p2p_data; p2p_data.open(state_file_path, std::ios_base::binary | std::ios_base::in); @@ -105,7 +108,7 @@ bool node_server::init_config() } catch(const std::exception &e) { - MWARNING("Failed to load p2p config file, falling back to default config"); + GULPS_WARN("Failed to load p2p config file, falling back to default config"); m_peerlist = peerlist_manager(); // it was probably half clobbered by the failed load make_default_config(); } @@ -134,7 +137,7 @@ bool node_server::init_config() m_config.m_support_flags = P2P_SUPPORT_FLAGS; m_first_connection_maker_call = true; - CATCH_ENTRY_L0("node_server::init_config", false); + GULPS_CATCH_ENTRY_L0("node_server::init_config", false); return true; } //----------------------------------------------------------------------------------- @@ -164,7 +167,7 @@ bool node_server::is_remote_host_allowed(const epee::net_ if(time(nullptr) >= it->second) { m_blocked_hosts.erase(it); - MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_CYAN, "Host {} unblocked.", address.host_str()); return true; } return false; @@ -201,7 +204,7 @@ bool node_server::block_host(const epee::net_utils::netwo for(const auto &c : conns) m_net_server.get_config_object().close(c); - MCLOG_CYAN(el::Level::Info, "global", "Host " << addr.host_str() << " blocked."); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_CYAN, "Host {} blocked.", addr.host_str()); return true; } //----------------------------------------------------------------------------------- @@ -213,7 +216,7 @@ bool node_server::unblock_host(const epee::net_utils::net if(i == m_blocked_hosts.end()) return false; m_blocked_hosts.erase(i); - MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); + GULPSF_GLOBAL_PRINT_CLR(gulps::COLOR_CYAN, "Host {} unblocked", address.host_str()); return true; } //----------------------------------------------------------------------------------- @@ -222,11 +225,11 @@ bool node_server::add_host_fail(const epee::net_utils::ne { CRITICAL_REGION_LOCAL(m_host_fails_score_lock); uint64_t fails = ++m_host_fails_score[address.host_str()]; - MDEBUG("Host " << address.host_str() << " fail score=" << fails); + GULPSF_LOG_L1("Host {} fail score={}", address.host_str() , fails); if(fails > P2P_IP_FAILS_BEFORE_BLOCK) { auto it = m_host_fails_score.find(address.host_str()); - CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); + GULPS_CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); it->second = P2P_IP_FAILS_BEFORE_BLOCK / 2; block_host(address); } @@ -263,7 +266,7 @@ bool node_server::handle_command_line( pe.id = crypto::rand(); const uint16_t default_port = config_get_p2p_port(m_nettype); bool r = parse_peer_from_string(pe.adr, pr_str, default_port); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " , pr_str); m_command_line_peers.push_back(pe); } } @@ -316,7 +319,7 @@ inline void append_net_address( using namespace boost::asio; size_t pos = addr.find_last_of(':'); - CHECK_AND_ASSERT_MES_NO_RET(std::string::npos != pos && addr.length() - 1 != pos && 0 != pos, "Failed to parse seed address from string: '" << addr << '\''); + GULPS_CHECK_AND_ASSERT_MES_NO_RET(std::string::npos != pos && addr.length() - 1 != pos && 0 != pos, "Failed to parse seed address from string: '" , addr , '\''); std::string host = addr.substr(0, pos); std::string port = addr.substr(pos + 1); @@ -325,7 +328,7 @@ inline void append_net_address( ip::tcp::resolver::query query(host, port, boost::asio::ip::tcp::resolver::query::canonical_name); boost::system::error_code ec; ip::tcp::resolver::iterator i = resolver.resolve(query, ec); - CHECK_AND_ASSERT_MES_NO_RET(!ec, "Failed to resolve host name '" << host << "': " << ec.message() << ':' << ec.value()); + GULPS_CHECK_AND_ASSERT_MES_NO_RET(!ec, "Failed to resolve host name '" , host , "': " , ec.message() , ':' , ec.value()); ip::tcp::resolver::iterator iend; for(; i != iend; ++i) @@ -335,11 +338,11 @@ inline void append_net_address( { epee::net_utils::network_address na{epee::net_utils::ipv4_network_address{boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()), endpoint.port()}}; seed_nodes.push_back(na); - MINFO("Added seed node: " << na.str()); + GULPSF_INFO("Added seed node: {}", na.str()); } else { - MWARNING("IPv6 unsupported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + GULPSF_WARN("IPv6 unsupported, skip '{}' -> {}", host , endpoint.address().to_v6().to_string(ec) ); throw std::runtime_error("IPv6 unsupported"); } } @@ -375,7 +378,7 @@ bool node_server::init(const boost::program_options::vari std::set full_addrs; bool res = handle_command_line(vm); - CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line"); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line"); if(m_nettype == cryptonote::TESTNET) { @@ -405,7 +408,7 @@ bool node_server::init(const boost::program_options::vari for(const std::string &addr_str : m_seed_nodes_list) { boost::thread th = boost::thread([=, &dns_results, &addr_str] { - MDEBUG("dns_threads[" << result_index << "] created for: " << addr_str); + GULPSF_LOG_L1("dns_threads[{}] created for: {}", result_index , addr_str); // TODO: care about dnssec avail/valid bool avail, valid; std::vector addr_list; @@ -413,7 +416,7 @@ bool node_server::init(const boost::program_options::vari try { addr_list = tools::DNSResolver::instance().get_ipv4(addr_str, avail, valid); - MDEBUG("dns_threads[" << result_index << "] DNS resolve done"); + GULPSF_LOG_L1("dns_threads[{}] DNS resolve done", result_index ); boost::this_thread::interruption_point(); } catch(const boost::thread_interrupted &) @@ -421,11 +424,11 @@ bool node_server::init(const boost::program_options::vari // thread interruption request // even if we now have results, finish thread without setting // result variables, which are now out of scope in main thread - MWARNING("dns_threads[" << result_index << "] interrupted"); + GULPSF_WARN("dns_threads[{}] interrupted", result_index ); return; } - MINFO("dns_threads[" << result_index << "] addr_str: " << addr_str << " number of results: " << addr_list.size()); + GULPSF_INFO("dns_threads[{}] addr_str: {}", result_index , addr_str ); dns_results[result_index] = addr_list; }); @@ -433,14 +436,14 @@ bool node_server::init(const boost::program_options::vari ++result_index; } - MDEBUG("dns_threads created, now waiting for completion or timeout of " << CRYPTONOTE_DNS_TIMEOUT_MS << "ms"); + GULPSF_LOG_L1("dns_threads created, now waiting for completion or timeout of {}ms", CRYPTONOTE_DNS_TIMEOUT_MS ); boost::chrono::system_clock::time_point deadline = boost::chrono::system_clock::now() + boost::chrono::milliseconds(CRYPTONOTE_DNS_TIMEOUT_MS); uint64_t i = 0; for(boost::thread &th : dns_threads) { if(!th.try_join_until(deadline)) { - MWARNING("dns_threads[" << i << "] timed out, sending interrupt"); + GULPSF_WARN("dns_threads[{}] timed out, sending interrupt", i ); th.interrupt(); } ++i; @@ -449,7 +452,7 @@ bool node_server::init(const boost::program_options::vari i = 0; for(const auto &result : dns_results) { - MDEBUG("DNS lookup for " << m_seed_nodes_list[i] << ": " << result.size() << " results"); + GULPSF_LOG_L1("DNS lookup for {}: {} results", m_seed_nodes_list[i] , result.size() ); // if no results for node, thread's lookup likely timed out if(result.size()) { @@ -463,9 +466,9 @@ bool node_server::init(const boost::program_options::vari if(full_addrs.size() < MIN_WANTED_SEED_NODES) { if(full_addrs.empty()) - MINFO("DNS seed node lookup either timed out or failed, falling back to defaults"); + GULPS_INFO("DNS seed node lookup either timed out or failed, falling back to defaults"); else - MINFO("Not enough DNS seed nodes found, using fallback defaults too"); + GULPS_INFO("Not enough DNS seed nodes found, using fallback defaults too"); for(const auto &peer : get_seed_nodes(cryptonote::MAINNET)) full_addrs.insert(peer); @@ -475,10 +478,10 @@ bool node_server::init(const boost::program_options::vari for(const auto &full_addr : full_addrs) { - MDEBUG("Seed node: " << full_addr); + GULPSF_LOG_L1("Seed node: {}", full_addr); append_net_address(m_seed_nodes, full_addr); } - MDEBUG("Number of seed nodes: " << m_seed_nodes.size()); + GULPSF_LOG_L1("Number of seed nodes: {}", m_seed_nodes.size()); m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); @@ -488,10 +491,10 @@ bool node_server::init(const boost::program_options::vari } res = init_config(); - CHECK_AND_ASSERT_MES(res, false, "Failed to init config."); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to init config."); res = m_peerlist.init(m_allow_local_ip); - CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist."); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist."); for(auto &p : m_command_line_peers) m_peerlist.append_with_peer_white(p); @@ -512,14 +515,14 @@ bool node_server::init(const boost::program_options::vari return res; //try to bind - MINFO("Binding on " << m_bind_ip << ":" << m_port); + GULPSF_INFO("Binding on {}:{}", m_bind_ip , m_port); res = m_net_server.init_server(m_port, m_bind_ip); - CHECK_AND_ASSERT_MES(res, false, "Failed to bind server"); + GULPS_CHECK_AND_ASSERT_MES(res, false, "Failed to bind server"); m_listening_port = m_net_server.get_binded_port(); - MLOG_GREEN(el::Level::Info, "Net service bound to " << m_bind_ip << ":" << m_listening_port); + GULPSF_INFO_CLR(gulps::COLOR_GREEN, "Net service bound to {}:{}", m_bind_ip, m_listening_port); if(m_external_port) - MDEBUG("External port defined as " << m_external_port); + GULPSF_LOG_L1("External port defined as {}", m_external_port); // add UPnP port mapping if(!m_no_igd) @@ -539,7 +542,7 @@ bool node_server::run() { // creating thread to log number of connections mPeersLoggerThread.reset(new boost::thread([&]() { - _note("Thread monitor number of peers - start"); + GULPS_LOG_L1("Thread monitor number of peers - start"); while(!is_closing && !m_net_server.is_stop_signal_sent()) { // main loop of thread //number_of_peers = m_net_server.get_config_object().get_connections_count(); @@ -562,7 +565,7 @@ bool node_server::run() boost::this_thread::sleep_for(boost::chrono::seconds(1)); } // main loop of thread - _note("Thread monitor number of peers - done"); + GULPS_LOG_L1("Thread monitor number of peers - done"); })); // lambda //here you can set worker threads count @@ -575,13 +578,13 @@ bool node_server::run() attrs.set_stack_size(THREAD_STACK_SIZE); //go to loop - MINFO("Run net_service loop( " << thrds_count << " threads)..."); + GULPSF_INFO("Run net_service loop( {} threads)...", thrds_count ); if(!m_net_server.run_server(thrds_count, true, attrs)) { - LOG_ERROR("Failed to run net tcp server!"); + GULPS_LOG_ERROR("Failed to run net tcp server!"); } - MINFO("net_service loop stopped."); + GULPS_INFO("net_service loop stopped."); return true; } @@ -608,10 +611,10 @@ template bool node_server::store_config() { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!tools::create_directories_if_necessary(m_config_folder)) { - MWARNING("Failed to create data directory: " << m_config_folder); + GULPSF_WARN("Failed to create data directory: {}", m_config_folder); return false; } @@ -620,14 +623,14 @@ bool node_server::store_config() p2p_data.open(state_file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc); if(p2p_data.fail()) { - MWARNING("Failed to save config to file " << state_file_path); + GULPSF_WARN("Failed to save config to file {}", state_file_path); return false; }; boost::archive::portable_binary_oarchive a(p2p_data); a << *this; return true; - CATCH_ENTRY_L0("blockchain_storage::save", false); + GULPS_CATCH_ENTRY_L0("blockchain_storage::save", false); return true; } @@ -635,9 +638,9 @@ bool node_server::store_config() template bool node_server::send_stop_signal() { - MDEBUG("[node] sending stop signal"); + GULPS_LOG_L1("[node] sending stop signal"); m_net_server.send_stop_signal(); - MDEBUG("[node] Stop signal sent"); + GULPS_LOG_L1("[node] Stop signal sent"); std::list connection_ids; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context &cntxt) { @@ -670,19 +673,19 @@ bool node_server::do_handshake_with_peer(peerid_type &pi, if(code < 0) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE invoke failed. ({}, {})", contextx_str(context), code , epee::levin::get_err_descr(code) ); return; } if(rsp.node_data.network_id != m_network_id) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE Failed, wrong network! (" << epee::string_tools::get_str_from_guid_a(rsp.node_data.network_id) << "), closing connection."); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE Failed, wrong network! ({}), closing connection.", contextx_str(context), epee::string_tools::get_str_from_guid_a(rsp.node_data.network_id)); return; } if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.node_data.local_time, context)) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection."); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection.", contextx_str(context)); add_host_fail(context.m_remote_address); return; } @@ -691,7 +694,7 @@ bool node_server::do_handshake_with_peer(peerid_type &pi, { if(!m_payload_handler.process_payload_sync_data(rsp.payload_data, context, true)) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE invoked, but process_payload_sync_data returned false, dropping connection."); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE invoked, but process_payload_sync_data returned false, dropping connection.", contextx_str(context)); hsh_result = false; return; } @@ -701,15 +704,15 @@ bool node_server::do_handshake_with_peer(peerid_type &pi, if(rsp.node_data.peer_id == m_config.m_peer_id) { - LOG_DEBUG_CC(context, "Connection to self detected, dropping connection"); + GULPSF_LOG_L1("{} Connection to self detected, dropping connection", contextx_str(context)); hsh_result = false; return; } - LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE INVOKED OK"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE INVOKED OK", contextx_str(context)); } else { - LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK", contextx_str(context)); } }, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT); @@ -721,7 +724,7 @@ bool node_server::do_handshake_with_peer(peerid_type &pi, if(!hsh_result) { - LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE Failed", contextx_str(context_)); m_net_server.get_config_object().close(context_.m_connection_id); } else @@ -745,13 +748,13 @@ bool node_server::do_peer_timed_sync(const epee::net_util context.m_in_timedsync = false; if(code < 0) { - LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")"); + GULPSF_LOG_L1("{} COMMAND_TIMED_SYNC invoke failed. ({}, {})", contextx_str(context), code , epee::levin::get_err_descr(code) ); return; } if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.local_time, context)) { - LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection."); + GULPSF_LOG_L1("{} COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.", contextx_str(context)); m_net_server.get_config_object().close(context.m_connection_id); add_host_fail(context.m_remote_address); } @@ -762,7 +765,7 @@ bool node_server::do_peer_timed_sync(const epee::net_util if(!r) { - LOG_WARNING_CC(context_, "COMMAND_TIMED_SYNC Failed"); + GULPSF_LOG_L1("{} COMMAND_TIMED_SYNC Failed", contextx_str(context_)); return false; } return true; @@ -777,7 +780,7 @@ size_t node_server::get_random_index_with_fixed_probabili size_t x = crypto::rand() % (max_index + 1); size_t res = (x * x * x) / (max_index * max_index); //parabola \/ - MDEBUG("Random connection index=" << res << "(x=" << x << ", max_index=" << max_index << ")"); + GULPSF_LOG_L1("Random connection index={}(x={}, max_index={})", res , x , max_index ); return res; } //----------------------------------------------------------------------------------- @@ -841,18 +844,7 @@ bool node_server::is_addr_connected(const epee::net_utils return connected; } -#define LOG_PRINT_CC_PRIORITY_NODE(priority, con, msg) \ - do \ - { \ - if(priority) \ - { \ - LOG_INFO_CC(con, "[priority]" << msg); \ - } \ - else \ - { \ - LOG_INFO_CC(con, msg); \ - } \ - } while(0) +#define priority_str(x) x ? "[priority]" : "" template bool node_server::try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address &na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp) @@ -867,11 +859,10 @@ bool node_server::try_to_connect_and_handshake_with_new_p m_current_number_of_out_peers--; // atomic variable, update time = 1s return false; } - MDEBUG("Connecting to " << na.str() << "(peer_type=" << peer_type << ", last_seen: " - << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp) : "never") - << ")..."); + GULPSF_LOG_L1("Connecting to {}(peer_type={}, last_seen: {})...", na.str() , peer_type , (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp) : "never") + ); - CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, + GULPS_CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, "Only IPv4 addresses are supported here"); const epee::net_utils::ipv4_network_address &ipv4 = na.as(); @@ -884,7 +875,7 @@ bool node_server::try_to_connect_and_handshake_with_new_p if(!res) { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str() + GULPS_INFO( "{} {} Connect failed to {}", contextx_str(con), priority_str(is_priority), na.str() /*<< ", try " << try_count*/); //m_peerlist.set_peer_unreachable(pe); return false; @@ -896,8 +887,7 @@ bool node_server::try_to_connect_and_handshake_with_new_p if(!res) { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " - << na.str() + GULPS_INFO("{} {} Failed to HANDSHAKE with peer {}", contextx_str(con), priority_str(is_priority), na.str() /*<< ", try " << try_count*/); return false; } @@ -905,7 +895,7 @@ bool node_server::try_to_connect_and_handshake_with_new_p if(just_take_peerlist) { m_net_server.get_config_object().close(con.m_connection_id); - LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK AND CLOSED."); + GULPSF_LOG_L1("{} CONNECTION HANDSHAKED OK AND CLOSED.", contextx_str(con)); return true; } @@ -925,18 +915,17 @@ bool node_server::try_to_connect_and_handshake_with_new_p m_peerlist.append_with_peer_anchor(ape); - LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK."); + GULPSF_LOG_L1("{} CONNECTION HANDSHAKED OK.", contextx_str(con)); return true; } template bool node_server::check_connection_and_handshake_with_peer(const epee::net_utils::network_address &na, uint64_t last_seen_stamp) { - LOG_PRINT_L1("Connecting to " << na.str() << "(last_seen: " - << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp) : "never") - << ")..."); + GULPSF_LOG_L1("Connecting to {}(last_seen: {})...", na.str() , (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp) : "never") + ); - CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, + GULPS_CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, "Only IPv4 addresses are supported here"); const epee::net_utils::ipv4_network_address &ipv4 = na.as(); @@ -949,9 +938,7 @@ bool node_server::check_connection_and_handshake_with_pee if(!res) { bool is_priority = is_priority_node(na); - - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str()); - + GULPSF_INFO("{} {} Connect failed to {}", contextx_str(con), priority_str(is_priority), na.str()); return false; } @@ -962,19 +949,18 @@ bool node_server::check_connection_and_handshake_with_pee { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " << na.str()); - + GULPSF_INFO("{} {} Failed to HANDSHAKE with peer {}", contextx_str(con), priority_str(is_priority), na.str()); return false; } m_net_server.get_config_object().close(con.m_connection_id); - LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK AND CLOSED."); + GULPSF_LOG_L1("{} CONNECTION HANDSHAKED OK AND CLOSED.", contextx_str(con)); return true; } -#undef LOG_PRINT_CC_PRIORITY_NODE +#undef priority_str //----------------------------------------------------------------------------------- template @@ -996,11 +982,11 @@ bool node_server::make_new_connection_from_anchor_peerlis { for(const auto &pe : anchor_peerlist) { - _note("Considering connecting (out) to peer: " << peerid_type(pe.id) << " " << pe.adr.str()); + GULPSF_LOG_L1("Considering connecting (out) to peer: {} {}", peerid_type(pe.id) , pe.adr.str()); if(is_peer_used(pe)) { - _note("Peer is used"); + GULPS_LOG_L1("Peer is used"); continue; } @@ -1014,13 +1000,13 @@ bool node_server::make_new_connection_from_anchor_peerlis continue; } - MDEBUG("Selected peer: " << peerid_to_string(pe.id) << " " << pe.adr.str() - << "[peer_type=" << anchor - << "] first_seen: " << epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen)); + GULPSF_LOG_L1("Selected peer: {} {}[peer_type={}] first_seen: {}", peerid_to_string(pe.id) , pe.adr.str() + , anchor + , epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen)); if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, 0, anchor, pe.first_seen)) { - _note("Handshake failed"); + GULPS_LOG_L1("Handshake failed"); continue; } @@ -1064,7 +1050,7 @@ bool node_server::make_new_connection_from_peerlist(bool random_index = crypto::rand() % local_peers_count; } - CHECK_AND_ASSERT_MES(random_index < local_peers_count, false, "random_starter_index < peers_local.size() failed!!"); + GULPS_CHECK_AND_ASSERT_MES(random_index < local_peers_count, false, "random_starter_index < peers_local.size() failed!!"); if(tried_peers.count(random_index)) continue; @@ -1072,15 +1058,15 @@ bool node_server::make_new_connection_from_peerlist(bool tried_peers.insert(random_index); peerlist_entry pe = AUTO_VAL_INIT(pe); bool r = use_white_list ? m_peerlist.get_white_peer_by_index(pe, random_index) : m_peerlist.get_gray_peer_by_index(pe, random_index); - CHECK_AND_ASSERT_MES(r, false, "Failed to get random peer from peerlist(white:" << use_white_list << ")"); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to get random peer from peerlist(white:" , use_white_list , ")"); ++try_count; - _note("Considering connecting (out) to peer: " << peerid_to_string(pe.id) << " " << pe.adr.str()); + GULPSF_LOG_L1("Considering connecting (out) to peer: {} {}", peerid_to_string(pe.id) , pe.adr.str()); if(is_peer_used(pe)) { - _note("Peer is used"); + GULPS_LOG_L1("Peer is used"); continue; } @@ -1090,13 +1076,13 @@ bool node_server::make_new_connection_from_peerlist(bool if(is_addr_recently_failed(pe.adr)) continue; - MDEBUG("Selected peer: " << peerid_to_string(pe.id) << " " << pe.adr.str() - << "[peer_list=" << (use_white_list ? white : gray) - << "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); + GULPSF_LOG_L1("Selected peer: {} {}[peer_list={}] last_seen: {}", peerid_to_string(pe.id) , pe.adr.str() + , (use_white_list ? white : gray) + , (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list ? white : gray)) { - _note("Handshake failed"); + GULPS_LOG_L1("Handshake failed"); continue; } @@ -1125,10 +1111,10 @@ bool node_server::connect_to_seed() { if(!fallback_nodes_added) { - MWARNING("Failed to connect to any of seed peers, trying fallback seeds"); + GULPS_WARN("Failed to connect to any of seed peers, trying fallback seeds"); for(const auto &peer : get_seed_nodes(m_nettype)) { - MDEBUG("Fallback seed node: " << peer); + GULPSF_LOG_L1("Fallback seed node: {}", peer); append_net_address(m_seed_nodes, peer); } fallback_nodes_added = true; @@ -1136,7 +1122,7 @@ bool node_server::connect_to_seed() } else { - MWARNING("Failed to connect to any of seed peers, continuing without seeds"); + GULPS_WARN("Failed to connect to any of seed peers, continuing without seeds"); break; } } @@ -1197,7 +1183,7 @@ bool node_server::connections_maker() if(start_conn_count == get_outgoing_connections_count() && start_conn_count < m_config.m_net_config.max_out_connection_count) { - MINFO("Failed to connect to any, trying seeds"); + GULPS_INFO("Failed to connect to any, trying seeds"); if(!connect_to_seed()) return false; } @@ -1285,7 +1271,7 @@ bool node_server::idle_worker() template bool node_server::peer_sync_idle_maker() { - MDEBUG("STARTED PEERLIST IDLE HANDSHAKE"); + GULPS_LOG_L1("STARTED PEERLIST IDLE HANDSHAKE"); typedef std::list> local_connects_type; local_connects_type cncts; m_net_server.get_config_object().foreach_connection([&](p2p_connection_context &cntxt) { @@ -1299,7 +1285,7 @@ bool node_server::peer_sync_idle_maker() std::for_each(cncts.begin(), cncts.end(), [&](const typename local_connects_type::value_type &vl) { do_peer_timed_sync(vl.first, vl.second); }); - MDEBUG("FINISHED PEERLIST IDLE HANDSHAKE"); + GULPS_LOG_L1("FINISHED PEERLIST IDLE HANDSHAKE"); return true; } //----------------------------------------------------------------------------------- @@ -1315,7 +1301,7 @@ bool node_server::fix_time_delta(std::list local_time) { - MWARNING("FOUND FUTURE peerlist for entry " << be.adr.str() << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); + GULPSF_WARN("FOUND FUTURE peerlist for entry {} last_seen: {}, local_time(on remote node):{}", be.adr.str() , be.last_seen , local_time); return false; } be.last_seen += delta; @@ -1330,8 +1316,8 @@ bool node_server::handle_remote_peerlist(const std::list< std::list peerlist_ = peerlist; if(!fix_time_delta(peerlist_, local_time, delta)) return false; - LOG_DEBUG_CC(context, "REMOTE PEERLIST: TIME_DELTA: " << delta << ", remote peerlist size=" << peerlist_.size()); - LOG_DEBUG_CC(context, "REMOTE PEERLIST: " << print_peerlist_to_string(peerlist_)); + GULPSF_LOG_L1("{} REMOTE PEERLIST: TIME_DELTA: {}, remote peerlist size={}",contextx_str(context), delta , peerlist_.size()); + GULPSF_LOG_L1("{} REMOTE PEERLIST: {}",contextx_str(context), print_peerlist_to_string(peerlist_)); return m_peerlist.merge_peerlist(peerlist_); } //----------------------------------------------------------------------------------- @@ -1358,17 +1344,17 @@ bool node_server::check_trust(const proof_of_trust &tr) uint64_t time_delata = local_time > tr.time ? local_time - tr.time : tr.time - local_time; if(time_delata > 24 * 60 * 60) { - MWARNING("check_trust failed to check time conditions, local_time=" << local_time << ", proof_time=" << tr.time); + GULPSF_WARN("check_trust failed to check time conditions, local_time={}, proof_time={}", local_time , tr.time); return false; } if(m_last_stat_request_time >= tr.time) { - MWARNING("check_trust failed to check time conditions, last_stat_request_time=" << m_last_stat_request_time << ", proof_time=" << tr.time); + GULPSF_WARN("check_trust failed to check time conditions, last_stat_request_time={}, proof_time={}", m_last_stat_request_time , tr.time); return false; } if(m_config.m_peer_id != tr.peer_id) { - MWARNING("check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << m_config.m_peer_id << ")"); + GULPSF_WARN("check_trust failed: peer_id mismatch (passed {}, expected {})", tr.peer_id , m_config.m_peer_id ); return false; } crypto::public_key pk = AUTO_VAL_INIT(pk); @@ -1376,7 +1362,7 @@ bool node_server::check_trust(const proof_of_trust &tr) crypto::hash h = get_proof_of_trust_hash(tr); if(!crypto::check_signature(h, pk, tr.sign)) { - MWARNING("check_trust failed: sign check failed"); + GULPS_WARN("check_trust failed: sign check failed"); return false; } //update last request time @@ -1500,7 +1486,7 @@ bool node_server::try_ping(basic_node_data &node_data, p2 if(!node_data.my_port) return false; - CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, + GULPS_CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, false, "Only IPv4 addresses are supported here"); const epee::net_utils::network_address na = context.m_remote_address; @@ -1516,7 +1502,7 @@ bool node_server::try_ping(basic_node_data &node_data, p2 const boost::system::error_code &ec) -> bool { if(ec) { - LOG_WARNING_CC(ping_context, "back ping connect failed to " << address.str()); + GULPSF_LOG_L1("{} back ping connect failed to {}",contextx_str(ping_context), address.str()); return false; } COMMAND_PING::request req; @@ -1534,13 +1520,13 @@ bool node_server::try_ping(basic_node_data &node_data, p2 [=](int code, const COMMAND_PING::response &rsp, p2p_connection_context &context) { if(code <= 0) { - LOG_WARNING_CC(ping_context, "Failed to invoke COMMAND_PING to " << address.str() << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); + GULPSF_LOG_L1("{} Failed to invoke COMMAND_PING to {}({}, {})", contextx_str(ping_context), address.str() , code , epee::levin::get_err_descr(code) ); return; } if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id) { - LOG_WARNING_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << address.str() << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << rsp.peer_id); + GULPSF_LOG_L1("{} back ping invoke wrong response \"{}\" from {}, hsh_peer_id={}, rsp.peer_id={}", contextx_str(ping_context), rsp.status, address.str(), pr_ , rsp.peer_id); m_net_server.get_config_object().close(ping_context.m_connection_id); return; } @@ -1550,7 +1536,7 @@ bool node_server::try_ping(basic_node_data &node_data, p2 if(!inv_call_res) { - LOG_WARNING_CC(ping_context, "back ping invoke failed to " << address.str()); + GULPSF_LOG_L1("{} back ping invoke failed to {}",contextx_str(ping_context), address.str()); m_net_server.get_config_object().close(ping_context.m_connection_id); return false; } @@ -1558,7 +1544,7 @@ bool node_server::try_ping(basic_node_data &node_data, p2 }); if(!r) { - LOG_WARNING_CC(context, "Failed to call connect_async, network error."); + GULPSF_LOG_L1("{} Failed to call connect_async, network error.", contextx_str(context)); } return r; } @@ -1575,7 +1561,7 @@ bool node_server::try_get_support_flags(const p2p_connect [=](int code, const typename COMMAND_REQUEST_SUPPORT_FLAGS::response &rsp, p2p_connection_context &context_) { if(code < 0) { - LOG_WARNING_CC(context_, "COMMAND_REQUEST_SUPPORT_FLAGS invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")"); + GULPSF_LOG_L1("{} COMMAND_REQUEST_SUPPORT_FLAGS invoke failed. ({}, {})", contextx_str(context_), code , epee::levin::get_err_descr(code) ); return; } @@ -1591,7 +1577,7 @@ int node_server::handle_timed_sync(int command, typename { if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, false)) { - LOG_WARNING_CC(context, "Failed to process_payload_sync_data(), dropping connection"); + GULPSF_LOG_L1("{} Failed to process_payload_sync_data(), dropping connection", contextx_str(context)); drop_connection(context); return 1; } @@ -1600,7 +1586,7 @@ int node_server::handle_timed_sync(int command, typename rsp.local_time = time(NULL); m_peerlist.get_peerlist_head(rsp.local_peerlist_new); m_payload_handler.get_payload_sync_data(rsp.payload_data); - LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC"); + GULPSF_LOG_L1("{} COMMAND_TIMED_SYNC", contextx_str(context)); return 1; } //----------------------------------------------------------------------------------- @@ -1610,7 +1596,7 @@ int node_server::handle_handshake(int command, typename C if(arg.node_data.network_id != m_network_id) { - LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id)); + GULPSF_LOG_L0("{} WRONG NETWORK AGENT CONNECTED! id={}", contextx_str(context), epee::string_tools::get_str_from_guid_a(arg.node_data.network_id)); drop_connection(context); add_host_fail(context.m_remote_address); return 1; @@ -1618,7 +1604,7 @@ int node_server::handle_handshake(int command, typename C if(!context.m_is_income) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came not from incoming connection"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE came not from incoming connection", contextx_str(context)); drop_connection(context); add_host_fail(context.m_remote_address); return 1; @@ -1626,28 +1612,28 @@ int node_server::handle_handshake(int command, typename C if(context.peer_id) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but seems that connection already have associated peer_id (double COMMAND_HANDSHAKE?)"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE came, but seems that connection already have associated peer_id (double COMMAND_HANDSHAKE?)", contextx_str(context)); drop_connection(context); return 1; } if(m_current_number_of_in_peers >= m_config.m_net_config.max_in_connection_count) // in peers limit { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but already have max incoming connections, so dropping this one."); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE came, but already have max incoming connections, so dropping this one.", contextx_str(context)); drop_connection(context); return 1; } if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, true)) { - LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but process_payload_sync_data returned false, dropping connection."); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE came, but process_payload_sync_data returned false, dropping connection.", contextx_str(context)); drop_connection(context); return 1; } if(has_too_many_connections(context.m_remote_address)) { - LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << context.m_remote_address.host_str() << " REFUSED, too many connections from the same address"); + GULPSF_LOG_L1("{} CONNECTION FROM {} REFUSED, too many connections from the same address", contextx_str(context), context.m_remote_address.host_str()); drop_connection(context); return 1; } @@ -1662,7 +1648,7 @@ int node_server::handle_handshake(int command, typename C uint32_t port_l = arg.node_data.my_port; //try ping to be sure that we can add this peer to peer_list try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]() { - CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, void(), + GULPS_CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, void(), "Only IPv4 addresses are supported here"); //called only(!) if success pinged, update local peerlist peerlist_entry pe; @@ -1673,7 +1659,7 @@ int node_server::handle_handshake(int command, typename C pe.last_seen = static_cast(last_seen); pe.id = peer_id_l; this->m_peerlist.append_with_peer_white(pe); - LOG_DEBUG_CC(context, "PING SUCCESS " << context.m_remote_address.host_str() << ":" << port_l); + GULPSF_LOG_L1("{} PING SUCCESS {}:{}",contextx_str(context), context.m_remote_address.host_str() , port_l); }); } @@ -1685,14 +1671,14 @@ int node_server::handle_handshake(int command, typename C m_peerlist.get_peerlist_head(rsp.local_peerlist_new); get_local_node_data(rsp.node_data); m_payload_handler.get_payload_sync_data(rsp.payload_data); - LOG_DEBUG_CC(context, "COMMAND_HANDSHAKE"); + GULPSF_LOG_L1("{} COMMAND_HANDSHAKE", contextx_str(context)); return 1; } //----------------------------------------------------------------------------------- template int node_server::handle_ping(int command, COMMAND_PING::request &arg, COMMAND_PING::response &rsp, p2p_connection_context &context) { - LOG_DEBUG_CC(context, "COMMAND_PING"); + GULPSF_LOG_L1("{} COMMAND_PING", contextx_str(context)); rsp.status = PING_OK_RESPONSE_STATUS_TEXT; rsp.peer_id = m_config.m_peer_id; return 1; @@ -1704,15 +1690,14 @@ bool node_server::log_peerlist() std::list pl_white; std::list pl_gray; m_peerlist.get_peerlist_full(pl_gray, pl_white); - MINFO(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray)); + GULPSF_INFO("\nPeerlist white:\n{}\nPeerlist gray:\n{}", print_peerlist_to_string(pl_white), print_peerlist_to_string(pl_gray)); return true; } //----------------------------------------------------------------------------------- template bool node_server::log_connections() { - MINFO("Connections: \r\n" - << print_connections_container()); + GULPSF_INFO("Connections: \r\n{}", print_connections_container()); return true; } //----------------------------------------------------------------------------------- @@ -1735,7 +1720,7 @@ std::string node_server::print_connections_container() template void node_server::on_connection_new(p2p_connection_context &context) { - MINFO("[" << epee::net_utils::print_connection_context(context) << "] NEW CONNECTION"); + GULPSF_INFO("[{}] NEW CONNECTION", epee::net_utils::print_connection_context(context) ); } //----------------------------------------------------------------------------------- template @@ -1751,7 +1736,7 @@ void node_server::on_connection_close(p2p_connection_cont m_payload_handler.on_connection_close(context); - MINFO("[" << epee::net_utils::print_connection_context(context) << "] CLOSE CONNECTION"); + GULPSF_INFO("[{}] CLOSE CONNECTION", epee::net_utils::print_connection_context(context) ); } template @@ -1789,7 +1774,7 @@ bool node_server::parse_peers_and_add_to_container(const epee::net_utils::network_address na = AUTO_VAL_INIT(na); const uint16_t default_port = config_get_p2p_port(m_nettype); bool r = parse_peer_from_string(na, pr_str, default_port); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); + GULPS_CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " , pr_str); container.push_back(na); } @@ -1840,7 +1825,7 @@ bool node_server::set_tos_flag(const boost::program_optio return true; } epee::net_utils::connection>::set_tos_flag(flag); - _dbg1("Set ToS flag " << flag); + GULPS_LOG_L1("Set ToS flag ", flag); return true; } @@ -1856,7 +1841,7 @@ bool node_server::set_rate_up_limit(const boost::program_ } epee::net_utils::connection>::set_rate_up_limit(limit); - MINFO("Set limit-up to " << limit << " kB/s"); + GULPSF_INFO("Set limit-up to {} kB/s", limit ); return true; } @@ -1870,7 +1855,7 @@ bool node_server::set_rate_down_limit(const boost::progra this->islimitdown = false; } epee::net_utils::connection>::set_rate_down_limit(limit); - MINFO("Set limit-down to " << limit << " kB/s"); + GULPSF_INFO("Set limit-down to {} kB/s", limit ); return true; } @@ -1893,12 +1878,12 @@ bool node_server::set_rate_limit(const boost::program_opt if(!this->islimitup) { epee::net_utils::connection>::set_rate_up_limit(limit_up); - MINFO("Set limit-up to " << limit_up << " kB/s"); + GULPSF_INFO("Set limit-up to {} kB/s", limit_up ); } if(!this->islimitdown) { epee::net_utils::connection>::set_rate_down_limit(limit_down); - MINFO("Set limit-down to " << limit_down << " kB/s"); + GULPSF_INFO("Set limit-down to {} kB/s", limit_down ); } return true; @@ -1951,14 +1936,14 @@ bool node_server::gray_peerlist_housekeeping() { m_peerlist.remove_from_peer_gray(pe); - LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id)); + GULPSF_LOG_L2("PEER EVICTED FROM GRAY PEER LIST IP address: {} Peer ID: {}", pe.adr.host_str() , peerid_type(pe.id)); return true; } m_peerlist.set_peer_just_seen(pe.id, pe.adr); - LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id)); + GULPSF_LOG_L2("PEER PROMOTED TO WHITE PEER LIST IP address: {} Peer ID: {}", pe.adr.host_str() , peerid_type(pe.id)); return true; } @@ -1966,7 +1951,7 @@ bool node_server::gray_peerlist_housekeeping() template void node_server::add_upnp_port_mapping(uint32_t port) { - MDEBUG("Attempting to add IGD port mapping."); + GULPS_LOG_L1("Attempting to add IGD port mapping."); int result; #if MINIUPNPC_API_VERSION > 13 // default according to miniupnpc.h @@ -1994,38 +1979,38 @@ void node_server::add_upnp_port_mapping(uint32_t port) portMappingResult = UPNP_AddPortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), portString.str().c_str(), lanAddress, CRYPTONOTE_NAME, "TCP", 0, "0"); if(portMappingResult != 0) { - LOG_ERROR("UPNP_AddPortMapping failed, error: " << strupnperror(portMappingResult)); + GULPSF_LOG_ERROR("UPNP_AddPortMapping failed, error: {}", strupnperror(portMappingResult)); } else { - MLOG_GREEN(el::Level::Info, "Added IGD port mapping."); + GULPS_INFO_CLR(gulps::COLOR_GREEN, "Added IGD port mapping."); } } else if(result == 2) { - MWARNING("IGD was found but reported as not connected."); + GULPS_WARN("IGD was found but reported as not connected."); } else if(result == 3) { - MWARNING("UPnP device was found but not recognized as IGD."); + GULPS_WARN("UPnP device was found but not recognized as IGD."); } else { - MWARNING("UPNP_GetValidIGD returned an unknown result code."); + GULPS_WARN("UPNP_GetValidIGD returned an unknown result code."); } FreeUPNPUrls(&urls); } else { - MINFO("No IGD was found."); + GULPS_INFO("No IGD was found."); } } template void node_server::delete_upnp_port_mapping(uint32_t port) { - MDEBUG("Attempting to delete IGD port mapping."); + GULPS_LOG_L1("Attempting to delete IGD port mapping."); int result; #if MINIUPNPC_API_VERSION > 13 // default according to miniupnpc.h @@ -2050,31 +2035,31 @@ void node_server::delete_upnp_port_mapping(uint32_t port) portMappingResult = UPNP_DeletePortMapping(urls.controlURL, igdData.first.servicetype, portString.str().c_str(), "TCP", 0); if(portMappingResult != 0) { - LOG_ERROR("UPNP_DeletePortMapping failed, error: " << strupnperror(portMappingResult)); + GULPSF_LOG_ERROR("UPNP_DeletePortMapping failed, error: {}", strupnperror(portMappingResult)); } else { - MLOG_GREEN(el::Level::Info, "Deleted IGD port mapping."); + GULPS_INFO_CLR(gulps::COLOR_GREEN, "Deleted IGD port mapping."); } } else if(result == 2) { - MWARNING("IGD was found but reported as not connected."); + GULPS_WARN("IGD was found but reported as not connected."); } else if(result == 3) { - MWARNING("UPnP device was found but not recognized as IGD."); + GULPS_WARN("UPnP device was found but not recognized as IGD."); } else { - MWARNING("UPNP_GetValidIGD returned an unknown result code."); + GULPS_WARN("UPNP_GetValidIGD returned an unknown result code."); } FreeUPNPUrls(&urls); } else { - MINFO("No IGD was found."); + GULPS_INFO("No IGD was found."); } } } diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index ecfc1a74..f58e4cd2 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index ded93c31..e828e4ef 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -345,7 +345,7 @@ inline bool peerlist_manager::get_peerlist_full(std::list &pl_gr //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address &addr) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); //find in white list peerlist_entry ple; @@ -353,12 +353,12 @@ inline bool peerlist_manager::set_peer_just_seen(peerid_type peer, const epee::n ple.id = peer; ple.last_seen = time(NULL); return append_with_peer_white(ple); - CATCH_ENTRY_L0("peerlist_manager::set_peer_just_seen()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::set_peer_just_seen()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::append_with_peer_white(const peerlist_entry &ple) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!is_host_allowed(ple.adr)) return true; @@ -383,12 +383,12 @@ inline bool peerlist_manager::append_with_peer_white(const peerlist_entry &ple) m_peers_gray.erase(by_addr_it_gr); } return true; - CATCH_ENTRY_L0("peerlist_manager::append_with_peer_white()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::append_with_peer_white()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::append_with_peer_gray(const peerlist_entry &ple) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); if(!is_host_allowed(ple.adr)) return true; @@ -412,12 +412,12 @@ inline bool peerlist_manager::append_with_peer_gray(const peerlist_entry &ple) m_peers_gray.replace(by_addr_it_gr, ple); } return true; - CATCH_ENTRY_L0("peerlist_manager::append_with_peer_gray()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::append_with_peer_gray()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::append_with_peer_anchor(const anchor_peerlist_entry &ple) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -430,12 +430,12 @@ inline bool peerlist_manager::append_with_peer_anchor(const anchor_peerlist_entr return true; - CATCH_ENTRY_L0("peerlist_manager::append_with_peer_anchor()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::append_with_peer_anchor()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::get_random_gray_peer(peerlist_entry &pe) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -451,12 +451,12 @@ inline bool peerlist_manager::get_random_gray_peer(peerlist_entry &pe) return true; - CATCH_ENTRY_L0("peerlist_manager::get_random_gray_peer()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::get_random_gray_peer()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::remove_from_peer_gray(const peerlist_entry &pe) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -469,12 +469,12 @@ inline bool peerlist_manager::remove_from_peer_gray(const peerlist_entry &pe) return true; - CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_gray()", false); + GULPS_CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_gray()", false); } //-------------------------------------------------------------------------------------------------- inline bool peerlist_manager::get_and_empty_anchor_peerlist(std::vector &apl) { - TRY_ENTRY(); + GULPS_TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -489,12 +489,12 @@ inline bool peerlist_manager::get_and_empty_anchor_peerlist(std::vector struct peerlist_entry_base { + peerlist_entry_base(AddressType adr, const peerid_type id, const int64_t last_seen) : adr(adr), id(id), last_seen(last_seen) {} + AddressType adr; peerid_type id; int64_t last_seen; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(peerlist_entry_base) KV_SERIALIZE(adr) KV_SERIALIZE(id) KV_SERIALIZE(last_seen) @@ -78,7 +86,7 @@ struct anchor_peerlist_entry_base peerid_type id; int64_t first_seen; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(anchor_peerlist_entry_base) KV_SERIALIZE(adr) KV_SERIALIZE(id) KV_SERIALIZE(first_seen) @@ -93,7 +101,7 @@ struct connection_entry_base peerid_type id; bool is_income; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(connection_entry_base) KV_SERIALIZE(adr) KV_SERIALIZE(id) KV_SERIALIZE(is_income) @@ -118,7 +126,7 @@ inline std::string print_peerlist_to_string(const std::list &pl) struct network_config { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(network_config) KV_SERIALIZE(max_out_connection_count) KV_SERIALIZE(max_in_connection_count) KV_SERIALIZE(handshake_interval) @@ -143,7 +151,7 @@ struct basic_node_data uint32_t my_port; peerid_type peer_id; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(basic_node_data) KV_SERIALIZE_VAL_POD_AS_BLOB(network_id) KV_SERIALIZE(peer_id) KV_SERIALIZE(local_time) @@ -166,7 +174,7 @@ struct COMMAND_HANDSHAKE_T basic_node_data node_data; t_playload_type payload_data; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(node_data) KV_SERIALIZE(payload_data) END_KV_SERIALIZE_MAP() @@ -178,7 +186,7 @@ struct COMMAND_HANDSHAKE_T t_playload_type payload_data; std::list local_peerlist_new; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(node_data) KV_SERIALIZE(payload_data) if(is_store) @@ -195,7 +203,7 @@ struct COMMAND_HANDSHAKE_T local_peerlist.push_back(peerlist_entry_base({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); } else - MDEBUG("Not including in legacy peer list: " << p.adr.str()); + GULPS_LOG_L1("Not including in legacy peer list: ", p.adr.str()); } epee::serialization::selector::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); } @@ -225,7 +233,7 @@ struct COMMAND_TIMED_SYNC_T struct request { t_playload_type payload_data; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(payload_data) END_KV_SERIALIZE_MAP() }; @@ -236,7 +244,7 @@ struct COMMAND_TIMED_SYNC_T t_playload_type payload_data; std::list local_peerlist_new; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(local_time) KV_SERIALIZE(payload_data) if(is_store) @@ -253,7 +261,7 @@ struct COMMAND_TIMED_SYNC_T local_peerlist.push_back(peerlist_entry_base({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); } else - MDEBUG("Not including in legacy peer list: " << p.adr.str()); + GULPS_LOG_L1("Not including in legacy peer list: ", p.adr.str()); } epee::serialization::selector::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); } @@ -265,7 +273,7 @@ struct COMMAND_TIMED_SYNC_T std::list> local_peerlist; epee::serialization::selector::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); for(const auto &p : local_peerlist) - ((response &)this_ref).local_peerlist_new.push_back(peerlist_entry({epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); + ((response &)this_ref).local_peerlist_new.emplace_back(peerlist_entry{epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen}); } } END_KV_SERIALIZE_MAP() @@ -279,7 +287,7 @@ struct COMMAND_TIMED_SYNC_T struct COMMAND_PING { /* - Used to make "callback" connection, to be sure that opponent node + Used to make "callback" connection, to be sure that opponent node have accessible connection point. Only other nodes can add peer to peerlist, and ONLY in case when peer has accepted connection and answered to ping. */ @@ -291,7 +299,7 @@ struct COMMAND_PING { /*actually we don't need to send any real data*/ - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -300,7 +308,7 @@ struct COMMAND_PING std::string status; peerid_type peer_id; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(peer_id) END_KV_SERIALIZE_MAP() @@ -317,7 +325,7 @@ struct proof_of_trust uint64_t time; crypto::signature sign; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(proof_of_trust) KV_SERIALIZE(peer_id) KV_SERIALIZE(time) KV_SERIALIZE_VAL_POD_AS_BLOB(sign) @@ -332,7 +340,7 @@ struct COMMAND_REQUEST_STAT_INFO_T struct request { proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(tr) END_KV_SERIALIZE_MAP() }; @@ -345,7 +353,7 @@ struct COMMAND_REQUEST_STAT_INFO_T uint64_t incoming_connections_count; payload_stat_info payload_info; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(version) KV_SERIALIZE(os_version) KV_SERIALIZE(connections_count) @@ -365,7 +373,7 @@ struct COMMAND_REQUEST_NETWORK_STATE struct request { proof_of_trust tr; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(tr) END_KV_SERIALIZE_MAP() }; @@ -377,7 +385,7 @@ struct COMMAND_REQUEST_NETWORK_STATE std::list connections_list; peerid_type my_id; uint64_t local_time; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_white) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist_gray) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(connections_list) @@ -396,7 +404,7 @@ struct COMMAND_REQUEST_PEER_ID struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -404,7 +412,7 @@ struct COMMAND_REQUEST_PEER_ID { peerid_type my_id; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(my_id) END_KV_SERIALIZE_MAP() }; @@ -419,7 +427,7 @@ struct COMMAND_REQUEST_SUPPORT_FLAGS struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -427,7 +435,7 @@ struct COMMAND_REQUEST_SUPPORT_FLAGS { uint32_t support_flags; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(support_flags) END_KV_SERIALIZE_MAP() }; diff --git a/src/p2p/stdafx.h b/src/p2p/stdafx.h index 439825f4..9b3f3796 100644 --- a/src/p2p/stdafx.h +++ b/src/p2p/stdafx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -33,4 +33,4 @@ #define BOOST_FILESYSTEM_VERSION 3 #define ENABLE_RELEASE_LOGGING #include "log_opt_defs.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" diff --git a/src/platform/mingw/alloca.h b/src/platform/mingw/alloca.h index 1f8b8bd3..364e8b0f 100644 --- a/src/platform/mingw/alloca.h +++ b/src/platform/mingw/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/platform/msc/alloca.h b/src/platform/msc/alloca.h index cc022671..163c18d5 100644 --- a/src/platform/msc/alloca.h +++ b/src/platform/msc/alloca.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/platform/msc/inline_c.h b/src/platform/msc/inline_c.h index 5b05f35d..55251f40 100644 --- a/src/platform/msc/inline_c.h +++ b/src/platform/msc/inline_c.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/platform/msc/stdbool.h b/src/platform/msc/stdbool.h index 73ddfbe2..cc1c299a 100644 --- a/src/platform/msc/stdbool.h +++ b/src/platform/msc/stdbool.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/platform/msc/sys/param.h b/src/platform/msc/sys/param.h index 67ef6199..225a72b3 100644 --- a/src/platform/msc/sys/param.h +++ b/src/platform/msc/sys/param.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 3b6f8096..9f7a8e31 100644 --- a/src/ringct/CMakeLists.txt +++ b/src/ringct/CMakeLists.txt @@ -29,7 +29,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -62,6 +62,7 @@ target_link_libraries(ringct_basic PUBLIC common cncrypto + fmt::fmt-header-only PRIVATE ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) @@ -88,6 +89,7 @@ target_link_libraries(ringct cncrypto cryptonote_basic device + fmt::fmt-header-only PRIVATE ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index ae84ab77..2d206dc5 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -19,7 +19,7 @@ // Adapted from Java code by Sarang Noether #include "common/perf_timer.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include extern "C" { #include "crypto/crypto-ops.h" @@ -28,8 +28,6 @@ extern "C" { #include "multiexp.h" #include "rctOps.h" -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "bulletproofs" #define DEBUG_BP @@ -37,6 +35,7 @@ extern "C" { namespace rct { +GULPS_CAT_MAJOR("bulletproofs"); static rct::keyV vector_powers(const rct::key &x, size_t n); static rct::keyV vector_dup(const rct::key &x, size_t n); static rct::key inner_product(const rct::keyV &a, const rct::keyV &b); @@ -58,7 +57,7 @@ static bool is_reduced(const rct::key &scalar) static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point) { ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); ge_scalarmult_p3(&p3, a.bytes, &p3); ge_cached cached; ge_p3_to_cached(&cached, acc_p3); @@ -70,7 +69,7 @@ static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &poi static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) { ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); ge_cached cached; ge_p3_to_cached(&cached, &p3); ge_p1p1 p1; @@ -81,7 +80,7 @@ static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) static void sub_acc_p3(ge_p3 *acc_p3, const rct::key &point) { ge_p3 p3; - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); ge_cached cached; ge_p3_to_cached(&cached, &p3); ge_p1p1 p1; @@ -136,7 +135,7 @@ static rct::key vector_power_sum(const rct::key &x, size_t n) /* Given two scalar arrays, construct the inner product */ static rct::key inner_product(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::key res = rct::zero(); for(size_t i = 0; i < a.size(); ++i) { @@ -148,7 +147,7 @@ static rct::key inner_product(const rct::keyV &a, const rct::keyV &b) /* Given two scalar arrays, construct the Hadamard product */ static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::keyV res(a.size()); for(size_t i = 0; i < a.size(); ++i) { @@ -160,7 +159,7 @@ static rct::keyV hadamard(const rct::keyV &a, const rct::keyV &b) /* Given two curvepoint arrays, construct the Hadamard product */ static rct::keyV hadamard2(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::keyV res(a.size()); for(size_t i = 0; i < a.size(); ++i) { @@ -172,7 +171,7 @@ static rct::keyV hadamard2(const rct::keyV &a, const rct::keyV &b) /* Add two vectors */ static rct::keyV vector_add(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::keyV res(a.size()); for(size_t i = 0; i < a.size(); ++i) { @@ -184,7 +183,7 @@ static rct::keyV vector_add(const rct::keyV &a, const rct::keyV &b) /* Subtract two vectors */ static rct::keyV vector_subtract(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); rct::keyV res(a.size()); for(size_t i = 0; i < a.size(); ++i) { @@ -289,7 +288,7 @@ static rct::key invert(const rct::key &x) #ifndef NDEBUG rct::key tmp; sc_mul(tmp.bytes, inv.bytes, x.bytes); - CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(tmp == rct::identity(), "invert failed"); #endif return inv; } @@ -297,9 +296,9 @@ static rct::key invert(const rct::key &x) /* Compute the slice of a vector */ static rct::keyV slice(const rct::keyV &a, size_t start, size_t stop) { - CHECK_AND_ASSERT_THROW_MES(start < a.size(), "Invalid start index"); - CHECK_AND_ASSERT_THROW_MES(stop <= a.size(), "Invalid stop index"); - CHECK_AND_ASSERT_THROW_MES(start < stop, "Invalid start/stop indices"); + GULPS_CHECK_AND_ASSERT_THROW_MES(start < a.size(), "Invalid start index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(stop <= a.size(), "Invalid stop index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(start < stop, "Invalid start/stop indices"); rct::keyV res(stop - start); for(size_t i = start; i < stop; ++i) { @@ -388,8 +387,8 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) uint64_t v_test = 0; for(int n = 0; n < 8; ++n) v_test |= (((uint64_t)sv[n]) << (8 * n)); - CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed"); - CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed"); #endif try_again: @@ -414,14 +413,14 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) if(y == rct::zero()) { PERF_TIMER_STOP(PROVE_step1); - MINFO("y is 0, trying again"); + GULPS_INFO("y is 0, trying again"); goto try_again; } rct::key z = hash_cache = rct::hash_to_scalar(y); if(z == rct::zero()) { PERF_TIMER_STOP(PROVE_step1); - MINFO("z is 0, trying again"); + GULPS_INFO("z is 0, trying again"); goto try_again; } @@ -458,7 +457,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) rct::key ipt = inner_product(twoN, aL); sc_muladd(test_t0.bytes, zsq.bytes, ipt.bytes, test_t0.bytes); sc_add(test_t0.bytes, test_t0.bytes, k.bytes); - CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed"); #endif PERF_TIMER_STOP(PROVE_step1); @@ -491,7 +490,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) if(x == rct::zero()) { PERF_TIMER_STOP(PROVE_step2); - MINFO("x is 0, trying again"); + GULPS_INFO("x is 0, trying again"); goto try_again; } @@ -518,7 +517,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) rct::key test_t; sc_muladd(test_t.bytes, t1.bytes, x.bytes, t0.bytes); sc_muladd(test_t.bytes, t2.bytes, xsq.bytes, test_t.bytes); - CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed"); #endif // PAPER LINES 32-33 @@ -572,7 +571,7 @@ Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma) if(w[round] == rct::zero()) { PERF_TIMER_STOP(PROVE_step4); - MINFO("w[round] is 0, trying again"); + GULPS_INFO("w[round] is 0, trying again"); goto try_again; } @@ -613,12 +612,12 @@ Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma) /* Given a set of values v (0..2^N-1) and masks gamma, construct a range proof */ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) { - CHECK_AND_ASSERT_THROW_MES(sv.size() == gamma.size(), "Incompatible sizes of sv and gamma"); - CHECK_AND_ASSERT_THROW_MES(!sv.empty(), "sv is empty"); + GULPS_CHECK_AND_ASSERT_THROW_MES(sv.size() == gamma.size(), "Incompatible sizes of sv and gamma"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!sv.empty(), "sv is empty"); for(const rct::key &sve : sv) - CHECK_AND_ASSERT_THROW_MES(is_reduced(sve), "Invalid sv input"); + GULPS_CHECK_AND_ASSERT_THROW_MES(is_reduced(sve), "Invalid sv input"); for(const rct::key &g : gamma) - CHECK_AND_ASSERT_THROW_MES(is_reduced(g), "Invalid gamma input"); + GULPS_CHECK_AND_ASSERT_THROW_MES(is_reduced(g), "Invalid gamma input"); PERF_TIMER_UNIT(PROVE, 1000000); @@ -628,7 +627,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) size_t M, logM; for(logM = 0; (M = 1 << logM) <= maxM && M < sv.size(); ++logM) ; - CHECK_AND_ASSERT_THROW_MES(M <= maxM, "sv/gamma are too large"); + GULPS_CHECK_AND_ASSERT_THROW_MES(M <= maxM, "sv/gamma are too large"); const size_t logMN = logM + logN; const size_t MN = M * N; @@ -682,8 +681,8 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if(j < sv.size()) for(int n = 0; n < 8; ++n) v_test |= (((uint64_t)sv[j][n]) << (8 * n)); - CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed"); - CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed"); } #endif @@ -711,14 +710,14 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if(y == rct::zero()) { PERF_TIMER_STOP(PROVE_step1); - MINFO("y is 0, trying again"); + GULPS_INFO("y is 0, trying again"); goto try_again; } rct::key z = hash_cache = rct::hash_to_scalar(y); if(z == rct::zero()) { PERF_TIMER_STOP(PROVE_step1); - MINFO("z is 0, trying again"); + GULPS_INFO("z is 0, trying again"); goto try_again; } @@ -737,8 +736,8 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) { if(i >= (j - 1) * N && i < j * N) { - CHECK_AND_ASSERT_THROW_MES(1 + j < zpow.size(), "invalid zpow index"); - CHECK_AND_ASSERT_THROW_MES(i - (j - 1) * N < twoN.size(), "invalid twoN index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(1 + j < zpow.size(), "invalid zpow index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(i - (j - 1) * N < twoN.size(), "invalid twoN index"); sc_muladd(zero_twos[i].bytes, zpow[1 + j].bytes, twoN[i - (j - 1) * N].bytes, zero_twos[i].bytes); } } @@ -773,7 +772,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if(x == rct::zero()) { PERF_TIMER_STOP(PROVE_step2); - MINFO("x is 0, trying again"); + GULPS_INFO("x is 0, trying again"); goto try_again; } @@ -785,7 +784,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) sc_muladd(taux.bytes, tau2.bytes, xsq.bytes, taux.bytes); for(size_t j = 1; j <= sv.size(); ++j) { - CHECK_AND_ASSERT_THROW_MES(j + 1 < zpow.size(), "invalid zpow index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(j + 1 < zpow.size(), "invalid zpow index"); sc_muladd(taux.bytes, zpow[j + 1].bytes, gamma[j - 1].bytes, taux.bytes); } rct::key mu; @@ -807,7 +806,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) const rct::key t0 = inner_product(l0, r0); sc_muladd(test_t.bytes, t1.bytes, x.bytes, t0.bytes); sc_muladd(test_t.bytes, t2.bytes, xsq.bytes, test_t.bytes); - CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed"); #endif // PAPER LINES 32-33 @@ -815,7 +814,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if(x_ip == rct::zero()) { PERF_TIMER_STOP(PROVE_step3); - MINFO("x_ip is 0, trying again"); + GULPS_INFO("x_ip is 0, trying again"); goto try_again; } @@ -867,7 +866,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) if(w[round] == rct::zero()) { PERF_TIMER_STOP(PROVE_step4); - MINFO("w[round] is 0, trying again"); + GULPS_INFO("w[round] is 0, trying again"); goto try_again; } @@ -890,7 +889,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma) Bulletproof bulletproof_PROVE(const std::vector &v, const rct::keyV &gamma) { - CHECK_AND_ASSERT_THROW_MES(v.size() == gamma.size(), "Incompatible sizes of v and gamma"); + GULPS_CHECK_AND_ASSERT_THROW_MES(v.size() == gamma.size(), "Incompatible sizes of v and gamma"); // vG + gammaH PERF_TIMER_START_BP(PROVE_v); @@ -923,19 +922,19 @@ bool bulletproof_VERIFY(const std::vector &proofs) const Bulletproof &proof = *p; // check scalar range - CHECK_AND_ASSERT_MES(is_reduced(proof.taux), false, "Input scalar not in range"); - CHECK_AND_ASSERT_MES(is_reduced(proof.mu), false, "Input scalar not in range"); - CHECK_AND_ASSERT_MES(is_reduced(proof.a), false, "Input scalar not in range"); - CHECK_AND_ASSERT_MES(is_reduced(proof.b), false, "Input scalar not in range"); - CHECK_AND_ASSERT_MES(is_reduced(proof.t), false, "Input scalar not in range"); + GULPS_CHECK_AND_ASSERT_MES(is_reduced(proof.taux), false, "Input scalar not in range"); + GULPS_CHECK_AND_ASSERT_MES(is_reduced(proof.mu), false, "Input scalar not in range"); + GULPS_CHECK_AND_ASSERT_MES(is_reduced(proof.a), false, "Input scalar not in range"); + GULPS_CHECK_AND_ASSERT_MES(is_reduced(proof.b), false, "Input scalar not in range"); + GULPS_CHECK_AND_ASSERT_MES(is_reduced(proof.t), false, "Input scalar not in range"); - CHECK_AND_ASSERT_MES(proof.V.size() >= 1, false, "V does not have at least one element"); - CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), false, "Mismatched L and R sizes"); - CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof"); + GULPS_CHECK_AND_ASSERT_MES(proof.V.size() >= 1, false, "V does not have at least one element"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), false, "Mismatched L and R sizes"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() > 0, false, "Empty proof"); max_length = std::max(max_length, proof.L.size()); } - CHECK_AND_ASSERT_MES(max_length < 32, false, "At least one proof is too large"); + GULPS_CHECK_AND_ASSERT_MES(max_length < 32, false, "At least one proof is too large"); size_t maxMN = 1u << max_length; bp_cache exp_cache; @@ -958,7 +957,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) size_t M, logM; for(logM = 0; (M = 1 << logM) <= maxM && M < proof.V.size(); ++logM) ; - CHECK_AND_ASSERT_MES(proof.L.size() == 6 + logM, false, "Proof is not the expected size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() == 6 + logM, false, "Proof is not the expected size"); const size_t MN = M * N; rct::key weight = rct::skGen(); @@ -966,13 +965,13 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_start); rct::key hash_cache = rct::hash_to_scalar(proof.V); rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S); - CHECK_AND_ASSERT_MES(!(y == rct::zero()), false, "y == 0"); + GULPS_CHECK_AND_ASSERT_MES(!(y == rct::zero()), false, "y == 0"); rct::key z = hash_cache = rct::hash_to_scalar(y); - CHECK_AND_ASSERT_MES(!(z == rct::zero()), false, "z == 0"); + GULPS_CHECK_AND_ASSERT_MES(!(z == rct::zero()), false, "z == 0"); rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2); - CHECK_AND_ASSERT_MES(!(x == rct::zero()), false, "x == 0"); + GULPS_CHECK_AND_ASSERT_MES(!(x == rct::zero()), false, "x == 0"); rct::key x_ip = hash_cache_mash(hash_cache, x, proof.taux, proof.mu, proof.t); - CHECK_AND_ASSERT_MES(!(x_ip == rct::zero()), false, "x_ip == 0"); + GULPS_CHECK_AND_ASSERT_MES(!(x_ip == rct::zero()), false, "x_ip == 0"); PERF_TIMER_STOP(VERIFY_start); // pre-multiply some points by 8 @@ -1000,7 +999,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mulsub(k.bytes, zpow[2].bytes, ip1y.bytes, rct::zero().bytes); for(size_t j = 1; j <= M; ++j) { - CHECK_AND_ASSERT_MES(j + 2 < zpow.size(), false, "invalid zpow index"); + GULPS_CHECK_AND_ASSERT_MES(j + 2 < zpow.size(), false, "invalid zpow index"); sc_mulsub(k.bytes, zpow[j + 2].bytes, ip12.bytes, k.bytes); } PERF_TIMER_STOP(VERIFY_line_61); @@ -1032,7 +1031,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) // Compute the number of rounds for the inner product const size_t rounds = logM + logN; - CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); + GULPS_CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); PERF_TIMER_START_BP(VERIFY_line_21_22); // PAPER LINES 21-22 @@ -1041,7 +1040,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) for(size_t i = 0; i < rounds; ++i) { w[i] = hash_cache_mash(hash_cache, proof.L[i], proof.R[i]); - CHECK_AND_ASSERT_MES(!(w[i] == rct::zero()), false, "w[i] == 0"); + GULPS_CHECK_AND_ASSERT_MES(!(w[i] == rct::zero()), false, "w[i] == 0"); } PERF_TIMER_STOP(VERIFY_line_21_22); @@ -1083,8 +1082,8 @@ bool bulletproof_VERIFY(const std::vector &proofs) // Adjust the scalars using the exponents from PAPER LINE 62 sc_add(g_scalar.bytes, g_scalar.bytes, z.bytes); - CHECK_AND_ASSERT_MES(2 + i / N < zpow.size(), false, "invalid zpow index"); - CHECK_AND_ASSERT_MES(i % N < twoN.size(), false, "invalid twoN index"); + GULPS_CHECK_AND_ASSERT_MES(2 + i / N < zpow.size(), false, "invalid zpow index"); + GULPS_CHECK_AND_ASSERT_MES(i % N < twoN.size(), false, "invalid twoN index"); sc_mul(tmp.bytes, zpow[2 + i / N].bytes, twoN[i % N].bytes); sc_muladd(tmp.bytes, z.bytes, ypow.bytes, tmp.bytes); sc_mulsub(h_scalar.bytes, tmp.bytes, yinvpow.bytes, h_scalar.bytes); @@ -1132,7 +1131,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sub_acc_p3(&check1, Y4); if(!ge_p3_is_point_at_infinity(&check1)) { - MERROR("Verification failure at step 1"); + GULPS_ERROR("Verification failure at step 1"); return false; } ge_p3 check2; @@ -1154,7 +1153,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) if(!ge_p3_is_point_at_infinity(&check2)) { - MERROR("Verification failure at step 2"); + GULPS_ERROR("Verification failure at step 2"); return false; } diff --git a/src/ringct/bulletproofs.h b/src/ringct/bulletproofs.h index 8233e925..89377e4a 100644 --- a/src/ringct/bulletproofs.h +++ b/src/ringct/bulletproofs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/ringct/multiexp.cc b/src/ringct/multiexp.cc index 2a71244d..9b803e32 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -19,16 +19,13 @@ // Adapted from Python code by Sarang Noether #include "common/perf_timer.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" extern "C" { #include "crypto/crypto-ops.h" } #include "multiexp.h" #include "rctOps.h" -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "multiexp" - //#define MULTIEXP_PERF(x) x #define MULTIEXP_PERF(x) @@ -65,7 +62,7 @@ extern "C" { namespace rct { - + GULPS_CAT_MAJOR("multiexp"); static inline bool operator<(const rct::key &k0, const rct::key &k1) { for(int n = 31; n >= 0; --n) @@ -93,7 +90,7 @@ static inline rct::key div2(const rct::key &k) static inline rct::key pow2(size_t n) { - CHECK_AND_ASSERT_THROW_MES(n < 256, "Invalid pow2 argument"); + GULPS_CHECK_AND_ASSERT_THROW_MES(n < 256, "Invalid pow2 argument"); rct::key res = rct::zero(); res[n >> 3] |= 1 << (n & 7); return res; @@ -125,7 +122,7 @@ rct::key bos_coster_heap_conv(std::vector data) MULTIEXP_PERF(PERF_TIMER_START_UNIT(bos_coster, 1000000)); MULTIEXP_PERF(PERF_TIMER_START_UNIT(setup, 1000000)); size_t points = data.size(); - CHECK_AND_ASSERT_THROW_MES(points > 1, "Not enough points"); + GULPS_CHECK_AND_ASSERT_THROW_MES(points > 1, "Not enough points"); std::vector heap(points); for(size_t n = 0; n < points; ++n) heap[n] = n; @@ -200,7 +197,7 @@ rct::key bos_coster_heap_conv_robust(std::vector data) MULTIEXP_PERF(PERF_TIMER_START_UNIT(bos_coster, 1000000)); MULTIEXP_PERF(PERF_TIMER_START_UNIT(setup, 1000000)); size_t points = data.size(); - CHECK_AND_ASSERT_THROW_MES(points > 0, "Not enough points"); + GULPS_CHECK_AND_ASSERT_THROW_MES(points > 0, "Not enough points"); std::vector heap; heap.reserve(points); for(size_t n = 0; n < points; ++n) @@ -319,7 +316,7 @@ static rct::key get_exponent(const rct::key &base, size_t idx) static const std::string salt("bulletproof"); std::string hashed = std::string((const char *)base.bytes, sizeof(base)) + salt + tools::get_varint_data(idx); const rct::key e = rct::hashToPoint(rct::hash2rct(crypto::cn_fast_hash(hashed.data(), hashed.size()))); - CHECK_AND_ASSERT_THROW_MES(!(e == rct::identity()), "Exponent is point at infinity"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!(e == rct::identity()), "Exponent is point at infinity"); return e; } @@ -329,9 +326,9 @@ multiexp_cache::multiexp_cache() for(size_t i = 0; i < maxN * maxM; ++i) { Hi_cache[i] = get_exponent(rct::H, i * 2); - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3_cache[i], Hi_cache[i].bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Hi_p3_cache[i], Hi_cache[i].bytes) == 0, "ge_frombytes_vartime failed"); Gi_cache[i] = get_exponent(rct::H, i * 2 + 1); - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3_cache[i], Gi_cache[i].bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&Gi_p3_cache[i], Gi_cache[i].bytes) == 0, "ge_frombytes_vartime failed"); data.push_back({rct::zero(), Gi_cache[i]}); data.push_back({rct::zero(), Hi_cache[i]}); @@ -340,12 +337,12 @@ multiexp_cache::multiexp_cache() s_cache.init_cache(data, STRAUS_SIZE_LIMIT); p_cache.init_cache(data, 0, false); - MINFO("Hi/Gi cache size: " << (sizeof(Hi_cache) + sizeof(Gi_cache)) / 1024 << " kB"); - MINFO("Hi_p3/Gi_p3 cache size: " << (sizeof(Hi_p3_cache) + sizeof(Gi_p3_cache)) / 1024 << " kB"); - MINFO("Straus cache size: " << sizeof(straus_cache) / 1024 << " kB"); - MINFO("Pippenger cache size: " << sizeof(pippenger_cache) / 1024 << " kB"); + GULPSF_INFO("Hi/Gi cache size: {} kB", (sizeof(Hi_cache) + sizeof(Gi_cache)) / 1024 ); + GULPSF_INFO("Hi_p3/Gi_p3 cache size: {} kB", (sizeof(Hi_p3_cache) + sizeof(Gi_p3_cache)) / 1024 ); + GULPSF_INFO("Straus cache size: {} kB", sizeof(straus_cache) / 1024 ); + GULPSF_INFO("Pippenger cache size: {} kB", sizeof(pippenger_cache) / 1024 ); size_t cache_size = (sizeof(Hi_cache) + sizeof(Hi_p3_cache)) * 2 + sizeof(straus_cache) + sizeof(pippenger_cache); - MINFO("Total cache size: " << cache_size / 1024 << "kB"); + GULPSF_INFO("Total cache size: {}kB", cache_size / 1024 ); } void straus_cache::init_cache(const std::vector &data, size_t N) @@ -353,7 +350,7 @@ void straus_cache::init_cache(const std::vector &data, size_t N) MULTIEXP_PERF(PERF_TIMER_START_UNIT(multiples, 1000000)); if (N == 0) N = data.size(); - CHECK_AND_ASSERT_THROW_MES(N <= data.size(), "Bad cache base data"); + GULPS_CHECK_AND_ASSERT_THROW_MES(N <= data.size(), "Bad cache base data"); ge_p1p1 p1; ge_p3 p3; @@ -379,14 +376,14 @@ void straus_cache::init_cache(const std::vector &data, size_t N) rct::key straus_cache::straus(const std::vector &data, size_t STEP) const { - CHECK_AND_ASSERT_THROW_MES(cache != nullptr, "null cache"); - CHECK_AND_ASSERT_THROW_MES(cache == NULL || size >= data.size(), "Cache is too small"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cache != nullptr, "null cache"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cache == NULL || size >= data.size(), "Cache is too small"); MULTIEXP_PERF(PERF_TIMER_UNIT(straus, 1000000)); STEP = STEP ? STEP : 192; MULTIEXP_PERF(PERF_TIMER_START_UNIT(setup, 1000000)); static constexpr unsigned int mask = (1 << STRAUS_C) - 1; - + ge_cached cached; ge_p1p1 p1; ge_p3 p3; @@ -486,7 +483,7 @@ void pippenger_cache::init_cache(const std::vector &data, size_t N MULTIEXP_PERF(PERF_TIMER_START_UNIT(pippenger_init_cache, 1000000)); if(N == 0) N = data.size(); - CHECK_AND_ASSERT_THROW_MES(N <= data.size(), "Bad cache base data"); + GULPS_CHECK_AND_ASSERT_THROW_MES(N <= data.size(), "Bad cache base data"); size = N; if(cache == nullptr || alloc_size < N) @@ -507,13 +504,13 @@ void pippenger_cache::init_cache(const std::vector &data, size_t N rct::key pippenger_cache::pippenger(const std::vector &data, aligned_ptr& buckets, size_t c) const { - CHECK_AND_ASSERT_THROW_MES(cache != nullptr, "null cache"); - CHECK_AND_ASSERT_THROW_MES(size >= data.size(), "Cache is too small"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cache != nullptr, "null cache"); + GULPS_CHECK_AND_ASSERT_THROW_MES(size >= data.size(), "Cache is too small"); if(c == 0) c = get_pippenger_c(data.size()); - CHECK_AND_ASSERT_THROW_MES(c <= 9, "c is too large"); + GULPS_CHECK_AND_ASSERT_THROW_MES(c <= 9, "c is too large"); ge_p3 result = ge_p3_identity; @@ -560,7 +557,7 @@ rct::key pippenger_cache::pippenger(const std::vector &data, align bucket |= 1 << j; if(bucket == 0) continue; - CHECK_AND_ASSERT_THROW_MES(bucket < (1u << c), "bucket overflow"); + GULPS_CHECK_AND_ASSERT_THROW_MES(bucket < (1u << c), "bucket overflow"); if(!ge_p3_is_point_at_infinity(&buckets[bucket])) { add(buckets[bucket], pp_offset(i)); @@ -588,8 +585,8 @@ rct::key pippenger_cache::pippenger(const std::vector &data, align /* Given two scalar arrays, construct a vector commitment */ rct::key bp_cache::vector_exponent(const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); - CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN * maxM, "Incompatible sizes of a and maxN"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN * maxM, "Incompatible sizes of a and maxN"); clear_pad(a.size()*2); for(size_t i = 0; i < a.size(); ++i) @@ -604,10 +601,10 @@ rct::key bp_cache::vector_exponent(const rct::keyV &a, const rct::keyV &b) /* Compute a custom vector-scalar commitment */ rct::key bp_cache::vector_exponent_custom(const rct::keyV &A, const rct::keyV &B, const rct::keyV &a, const rct::keyV &b) { - CHECK_AND_ASSERT_THROW_MES(A.size() == B.size(), "Incompatible sizes of A and B"); - CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); - CHECK_AND_ASSERT_THROW_MES(a.size() == A.size(), "Incompatible sizes of a and A"); - CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN * maxM, "Incompatible sizes of a and maxN"); + GULPS_CHECK_AND_ASSERT_THROW_MES(A.size() == B.size(), "Incompatible sizes of A and B"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == b.size(), "Incompatible sizes of a and b"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() == A.size(), "Incompatible sizes of a and A"); + GULPS_CHECK_AND_ASSERT_THROW_MES(a.size() <= maxN * maxM, "Incompatible sizes of a and maxN"); clear_pad(a.size()*2); for(size_t i = 0; i < a.size(); ++i) diff --git a/src/ringct/multiexp.h b/src/ringct/multiexp.h index a9eb0006..5be8cbca 100644 --- a/src/ringct/multiexp.h +++ b/src/ringct/multiexp.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -22,7 +22,7 @@ #include "cryptonote_config.h" #include "crypto/crypto.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include "rctTypes.h" #include #include @@ -56,6 +56,7 @@ static constexpr size_t maxM = cryptonote::common_config::BULLETPROOF_MAX_OUTPUT struct MultiexpData { + GULPS_CAT_MAJOR("multiexp"); rct::key scalar; ge_p3 point; @@ -63,7 +64,7 @@ struct MultiexpData MultiexpData(const rct::key &s, const ge_p3 &p) : scalar(s), point(p) {} MultiexpData(const rct::key &s, const rct::key &p) : scalar(s) { - CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&point, p.bytes) == 0, "ge_frombytes_vartime failed"); + GULPS_CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&point, p.bytes) == 0, "ge_frombytes_vartime failed"); } }; @@ -79,7 +80,7 @@ struct alignas(8) ge_cached_pad class pippenger_cache { public: - pippenger_cache() : size(0), alloc_size(0) {} + pippenger_cache() : size(0), alloc_size(0) {} inline ge_cached* pp_offset(size_t n) { return &cache[n].gec; }; inline const ge_cached& pp_offset(size_t n) const { return cache[n].gec; }; @@ -122,7 +123,7 @@ class pippenger_cache class straus_cache { public: - straus_cache() : size(0) {} + straus_cache() : size(0) {} static constexpr size_t STRAUS_C = 4; diff --git a/src/ringct/rctCryptoOps.c b/src/ringct/rctCryptoOps.c index da0599f4..e4cef66a 100644 --- a/src/ringct/rctCryptoOps.c +++ b/src/ringct/rctCryptoOps.c @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/ringct/rctCryptoOps.h b/src/ringct/rctCryptoOps.h index 50354d20..ec029647 100644 --- a/src/ringct/rctCryptoOps.h +++ b/src/ringct/rctCryptoOps.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 7efd3155..b99254f6 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // @@ -18,20 +19,22 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "rctOps.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include using namespace crypto; using namespace std; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "ringct" +//undef RYO_DEFAULT_LOG_CATEGORY +//#define RYO_DEFAULT_LOG_CATEGORY -#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) \ +#define CHECK_AND_ASSERT_THROW_MES_L1(expr, ...) \ { \ if(!(expr)) \ { \ - MWARNING(message); \ - throw std::runtime_error(message); \ + std::string str; \ + str = stream_writer::write(__VA_ARGS__); \ + {GULPS_CAT_MAJOR("rctOps"); GULPS_WARN(str);} \ + throw std::runtime_error(str); \ } \ } @@ -74,7 +77,8 @@ key skGen() //Mainly used in testing keyV skvGen(size_t rows) { - CHECK_AND_ASSERT_THROW_MES(rows > 0, "0 keys requested"); + GULPS_CAT_MAJOR("rctOps"); + GULPS_CHECK_AND_ASSERT_THROW_MES(rows > 0, "0 keys requested"); keyV rv(rows); for(size_t i = 0; i < rows; i++) skGen(rv[i]); @@ -249,7 +253,7 @@ rct::key addKeys(const key &A, const key &B) return k; } -rct::key addKeys(const keyV &A) +rct::key addKeys(const keyV &A) { if (A.empty()) return rct::identity(); diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index f7758c92..ff5be4e8 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -1,5 +1,5 @@ -//#define DBG -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 995d0d34..8df95405 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // @@ -23,19 +24,19 @@ #include "common/threadpool.h" #include "common/util.h" #include "cryptonote_basic/cryptonote_format_utils.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" using namespace crypto; using namespace std; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "ringct" +GULPS_CAT_MAJOR("rctSigs"); -#define CHECK_AND_ASSERT_MES_L1(expr, ret, message) \ + +#define CHECK_AND_ASSERT_MES_L1(expr, ret, ...) \ { \ if(!(expr)) \ { \ - MCERROR("verify", message); \ + GULPS_CAT_ERROR("verify", __VA_ARGS__); \ return ret; \ } \ } @@ -46,7 +47,7 @@ Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount) { mask = rct::skGen(); Bulletproof proof = bulletproof_PROVE(amount, mask); - CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element"); + GULPS_CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element"); C = proof.V[0]; return proof; } @@ -55,7 +56,7 @@ Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector= 2, "Error! What is c if cols = 1!"); - CHECK_AND_ASSERT_THROW_MES(index < cols, "Index out of range"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cols >= 2, "Error! What is c if cols = 1!"); + GULPS_CHECK_AND_ASSERT_THROW_MES(index < cols, "Index out of range"); size_t rows = pk[0].size(); - CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pk"); + GULPS_CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pk"); for(size_t i = 1; i < cols; ++i) { - CHECK_AND_ASSERT_THROW_MES(pk[i].size() == rows, "pk is not rectangular"); + GULPS_CHECK_AND_ASSERT_THROW_MES(pk[i].size() == rows, "pk is not rectangular"); } - CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "Bad xx size"); - CHECK_AND_ASSERT_THROW_MES(dsRows <= rows, "Bad dsRows size"); - CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); - CHECK_AND_ASSERT_THROW_MES(!kLRki || dsRows == 1, "Multisig requires exactly 1 dsRows"); + GULPS_CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "Bad xx size"); + GULPS_CHECK_AND_ASSERT_THROW_MES(dsRows <= rows, "Bad dsRows size"); + GULPS_CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!kLRki || dsRows == 1, "Multisig requires exactly 1 dsRows"); size_t i = 0, j = 0, ii = 0; key c, c_old, L, R, Hi; @@ -276,25 +277,25 @@ bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &rv, size_t dsRow { size_t cols = pk.size(); - CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!"); + GULPS_CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!"); size_t rows = pk[0].size(); - CHECK_AND_ASSERT_MES(rows >= 1, false, "Empty pk"); + GULPS_CHECK_AND_ASSERT_MES(rows >= 1, false, "Empty pk"); for(size_t i = 1; i < cols; ++i) { - CHECK_AND_ASSERT_MES(pk[i].size() == rows, false, "pk is not rectangular"); + GULPS_CHECK_AND_ASSERT_MES(pk[i].size() == rows, false, "pk is not rectangular"); } - CHECK_AND_ASSERT_MES(rv.II.size() == dsRows, false, "Bad II size"); - CHECK_AND_ASSERT_MES(rv.ss.size() == cols, false, "Bad rv.ss size"); + GULPS_CHECK_AND_ASSERT_MES(rv.II.size() == dsRows, false, "Bad II size"); + GULPS_CHECK_AND_ASSERT_MES(rv.ss.size() == cols, false, "Bad rv.ss size"); for(size_t i = 0; i < cols; ++i) { - CHECK_AND_ASSERT_MES(rv.ss[i].size() == rows, false, "rv.ss is not rectangular"); + GULPS_CHECK_AND_ASSERT_MES(rv.ss[i].size() == rows, false, "rv.ss is not rectangular"); } - CHECK_AND_ASSERT_MES(dsRows <= rows, false, "Bad dsRows value"); + GULPS_CHECK_AND_ASSERT_MES(dsRows <= rows, false, "Bad dsRows value"); for(size_t i = 0; i < rv.ss.size(); ++i) for(size_t j = 0; j < rv.ss[i].size(); ++j) - CHECK_AND_ASSERT_MES(sc_check(rv.ss[i][j].bytes) == 0, false, "Bad ss slot"); - CHECK_AND_ASSERT_MES(sc_check(rv.cc.bytes) == 0, false, "Bad cc"); + GULPS_CHECK_AND_ASSERT_MES(sc_check(rv.ss[i][j].bytes) == 0, false, "Bad ss slot"); + GULPS_CHECK_AND_ASSERT_MES(sc_check(rv.cc.bytes) == 0, false, "Bad cc"); size_t i = 0, j = 0, ii = 0; key c, L, R, Hi; @@ -315,7 +316,7 @@ bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &rv, size_t dsRow { addKeys2(L, rv.ss[i][j], c_old, pk[i][j]); hashToPoint(Hi, pk[i][j]); - CHECK_AND_ASSERT_MES(!(Hi == rct::identity()), false, "Data hashed to point at infinity"); + GULPS_CHECK_AND_ASSERT_MES(!(Hi == rct::identity()), false, "Data hashed to point at infinity"); addKeys3(R, rv.ss[i][j], Hi, c_old, Ip[j].k); toHash[3 * j + 1] = pk[i][j]; toHash[3 * j + 2] = L; @@ -427,11 +428,11 @@ key get_pre_mlsag_hash(const rctSig &rv, hw::device &hwdev) std::stringstream ss; binary_archive ba(ss); - CHECK_AND_ASSERT_THROW_MES(!rv.mixRing.empty(), "Empty mixRing"); + GULPS_CHECK_AND_ASSERT_THROW_MES(!rv.mixRing.empty(), "Empty mixRing"); const size_t inputs = (rv.type == RCTTypeBulletproof || rv.type == RCTTypeSimple) ? rv.mixRing.size() : rv.mixRing[0].size(); const size_t outputs = rv.ecdhInfo.size(); key prehash; - CHECK_AND_ASSERT_THROW_MES(const_cast(rv).serialize_rctsig_base(ba, inputs, outputs), + GULPS_CHECK_AND_ASSERT_THROW_MES(const_cast(rv).serialize_rctsig_base(ba, inputs, outputs), "Failed to serialize rctSigBase"); cryptonote::get_blob_hash(ss.str(), h); hashes.push_back(hash2rct(h)); @@ -491,16 +492,16 @@ mgSig proveRctMG(const key &message, const ctkeyM &pubs, const ctkeyV &inSk, con mgSig mg; //setup vars size_t cols = pubs.size(); - CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); size_t rows = pubs[0].size(); - CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_THROW_MES(rows >= 1, "Empty pubs"); for(size_t i = 1; i < cols; ++i) { - CHECK_AND_ASSERT_THROW_MES(pubs[i].size() == rows, "pubs is not rectangular"); + GULPS_CHECK_AND_ASSERT_THROW_MES(pubs[i].size() == rows, "pubs is not rectangular"); } - CHECK_AND_ASSERT_THROW_MES(inSk.size() == rows, "Bad inSk size"); - CHECK_AND_ASSERT_THROW_MES(outSk.size() == outPk.size(), "Bad outSk/outPk size"); - CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); + GULPS_CHECK_AND_ASSERT_THROW_MES(inSk.size() == rows, "Bad inSk size"); + GULPS_CHECK_AND_ASSERT_THROW_MES(outSk.size() == outPk.size(), "Bad outSk/outPk size"); + GULPS_CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); keyV sk(rows + 1); keyV tmp(rows + 1); @@ -558,8 +559,8 @@ mgSig proveRctMGSimple(const key &message, const ctkeyV &pubs, const ctkey &inSk //setup vars size_t rows = 1; size_t cols = pubs.size(); - CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); - CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); + GULPS_CHECK_AND_ASSERT_THROW_MES(cols >= 1, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); keyV tmp(rows + 1); keyV sk(rows + 1); size_t i; @@ -590,12 +591,12 @@ bool verRctMG(const mgSig &mg, const ctkeyM &pubs, const ctkeyV &outPk, key txnF PERF_TIMER(verRctMG); //setup vars size_t cols = pubs.size(); - CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); size_t rows = pubs[0].size(); - CHECK_AND_ASSERT_MES(rows >= 1, false, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_MES(rows >= 1, false, "Empty pubs"); for(size_t i = 1; i < cols; ++i) { - CHECK_AND_ASSERT_MES(pubs[i].size() == rows, false, "pubs is not rectangular"); + GULPS_CHECK_AND_ASSERT_MES(pubs[i].size() == rows, false, "pubs is not rectangular"); } keyV tmp(rows + 1); @@ -639,7 +640,7 @@ bool verRctMGSimple(const key &message, const mgSig &mg, const ctkeyV &pubs, con //setup vars size_t rows = 1; size_t cols = pubs.size(); - CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); + GULPS_CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); keyV tmp(rows + 1); size_t i; keyM M(cols, tmp); @@ -730,14 +731,14 @@ ryo_amount populateFromBlockchainSimple(ctkeyV &mixRing, const ctkey &inPk, int // Thus the amounts vector will be "one" longer than the destinations vectort rctSig genRct(const key &message, const ctkeyV &inSk, const keyV &destinations, const vector &amounts, const ctkeyM &mixRing, const keyV &amount_keys, const multisig_kLRki *kLRki, multisig_out *msout, unsigned int index, ctkeyV &outSk, hw::device &hwdev) { - CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations"); - CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations"); - CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing"); + GULPS_CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations"); + GULPS_CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations"); + GULPS_CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing"); for(size_t n = 0; n < mixRing.size(); ++n) { - CHECK_AND_ASSERT_THROW_MES(mixRing[n].size() == inSk.size(), "Bad mixRing size"); + GULPS_CHECK_AND_ASSERT_THROW_MES(mixRing[n].size() == inSk.size(), "Bad mixRing size"); } - CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present"); + GULPS_CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present"); rctSig rv; rv.type = RCTTypeFull; @@ -756,7 +757,7 @@ rctSig genRct(const key &message, const ctkeyV &inSk, const keyV &destinations, //compute range proof rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, amounts[i]); #ifndef NDEBUG - CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof"); + GULPS_CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof"); #endif //mask amount and mask rv.ecdhInfo[i].mask = copy(outSk[i].mask); @@ -795,20 +796,20 @@ rctSig genRct(const key &message, const ctkeyV &inSk, const ctkeyV &inPk, const //for post-rct only rctSig genRctSimple(const key &message, const ctkeyV &inSk, const keyV &destinations, const vector &inamounts, const vector &outamounts, ryo_amount txnFee, const ctkeyM &mixRing, const keyV &amount_keys, const std::vector *kLRki, multisig_out *msout, const std::vector &index, ctkeyV &outSk, bool bulletproof, hw::device &hwdev) { - CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts"); - CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk"); - CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations"); - CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations"); - CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk"); - CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk"); + GULPS_CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts"); + GULPS_CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk"); + GULPS_CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations"); + GULPS_CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations"); + GULPS_CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk"); + GULPS_CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk"); for(size_t n = 0; n < mixRing.size(); ++n) { - CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing"); + GULPS_CHECK_AND_ASSERT_THROW_MES(index[n] < mixRing[n].size(), "Bad index into mixRing"); } - CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present"); + GULPS_CHECK_AND_ASSERT_THROW_MES((kLRki && msout) || (!kLRki && !msout), "Only one of kLRki/msout is present"); if(kLRki && msout) { - CHECK_AND_ASSERT_THROW_MES(kLRki->size() == inamounts.size(), "Mismatched kLRki/inamounts sizes"); + GULPS_CHECK_AND_ASSERT_THROW_MES(kLRki->size() == inamounts.size(), "Mismatched kLRki/inamounts sizes"); } rctSig rv; @@ -832,7 +833,7 @@ rctSig genRctSimple(const key &message, const ctkeyV &inSk, const keyV &destinat rv.p.rangeSigs[i] = proveRange(rv.outPk[i].mask, outSk[i].mask, outamounts[i]); #ifndef NDEBUG if(!bulletproof) - CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof"); + GULPS_CHECK_AND_ASSERT_THROW_MES(verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]), "verRange failed on newly created proof"); #endif } @@ -842,7 +843,7 @@ rctSig genRctSimple(const key &message, const ctkeyV &inSk, const keyV &destinat rct::keyV C, masks; rv.p.bulletproofs.push_back(proveRangeBulletproof(C, masks, outamounts)); #ifndef NDEBUG - CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); + GULPS_CHECK_AND_ASSERT_THROW_MES(verBulletproof(rv.p.bulletproofs.back()), "verBulletproof failed on newly created proof"); #endif for(i = 0; i < outamounts.size(); ++i) { @@ -921,12 +922,12 @@ rctSig genRctSimple(const key &message, const ctkeyV &inSk, const ctkeyV &inPk, bool verRct(const rctSig &rv, bool semantics) { PERF_TIMER(verRct); - CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig"); + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig"); if(semantics) { - CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs"); - CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); - CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "full rctSig has not one MG"); } else { @@ -950,7 +951,7 @@ bool verRct(const rctSig &rv, bool semantics) { if(!results[i]) { - LOG_PRINT_L1("Range proof verified failed for proof " << i); + GULPSF_LOG_L1("Range proof verified failed for proof {}", i); return false; } } @@ -965,7 +966,7 @@ bool verRct(const rctSig &rv, bool semantics) DP(mgVerd); if(!mgVerd) { - LOG_PRINT_L1("MG signature verification failed"); + GULPS_LOG_L1("MG signature verification failed"); return false; } } @@ -974,12 +975,12 @@ bool verRct(const rctSig &rv, bool semantics) } catch(const std::exception &e) { - LOG_PRINT_L1("Error in verRct: " << e.what()); + GULPSF_LOG_L1("Error in verRct: {}", e.what()); return false; } catch(...) { - LOG_PRINT_L1("Error in verRct, but not an actual exception"); + GULPS_LOG_L1("Error in verRct, but not an actual exception"); return false; } } @@ -1000,25 +1001,25 @@ bool verRctSemanticsSimple(const std::vector &rvv) for(const rctSig *rvp : rvv) { - CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL"); + GULPS_CHECK_AND_ASSERT_MES(rvp, false, "rctSig pointer is NULL"); const rctSig &rv = *rvp; - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctSemanticsSimple called on non simple rctSig"); + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctSemanticsSimple called on non simple rctSig"); const bool bulletproof = rv.type == RCTTypeBulletproof; if(bulletproof) { - CHECK_AND_ASSERT_MES(rv.outPk.size() <= cryptonote::common_config::BULLETPROOF_MAX_OUTPUTS, false, "Too many outputs"); - CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_amounts(rv.p.bulletproofs), false, "Mismatched sizes of outPk and bulletproofs"); - CHECK_AND_ASSERT_MES(is_canonical_bulletproof_layout(rv.p.bulletproofs), false, "Non-canonical layout"); - CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.MGs"); - CHECK_AND_ASSERT_MES(rv.pseudoOuts.empty(), false, "rv.pseudoOuts is not empty"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() <= cryptonote::common_config::BULLETPROOF_MAX_OUTPUTS, false, "Too many outputs"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() == n_bulletproof_amounts(rv.p.bulletproofs), false, "Mismatched sizes of outPk and bulletproofs"); + GULPS_CHECK_AND_ASSERT_MES(is_canonical_bulletproof_layout(rv.p.bulletproofs), false, "Non-canonical layout"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.p.pseudoOuts and rv.p.MGs"); + GULPS_CHECK_AND_ASSERT_MES(rv.pseudoOuts.empty(), false, "rv.pseudoOuts is not empty"); } else { - CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs"); - CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs"); - CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.empty(), false, "rv.p.pseudoOuts is not empty"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs"); + GULPS_CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.empty(), false, "rv.p.pseudoOuts is not empty"); } - CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); + GULPS_CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo"); if(!bulletproof) max_non_bp_proofs += rv.p.rangeSigs.size(); @@ -1048,7 +1049,7 @@ bool verRctSemanticsSimple(const std::vector &rvv) //check pseudoOuts vs Outs.. if(!equalKeys(sumPseudoOuts, sumOutpks)) { - LOG_PRINT_L1("Sum check failed"); + GULPS_LOG_L1("Sum check failed"); return false; } @@ -1066,7 +1067,7 @@ bool verRctSemanticsSimple(const std::vector &rvv) } if(!proofs.empty() && !verBulletproof(proofs)) { - LOG_PRINT_L1("Aggregate range proof verified failed"); + GULPS_LOG_L1("Aggregate range proof verified failed"); return false; } @@ -1075,7 +1076,7 @@ bool verRctSemanticsSimple(const std::vector &rvv) { if(!results[i]) { - LOG_PRINT_L1("Range proof verified failed for proof " << i); + GULPSF_LOG_L1("Range proof verified failed for proof {}", i); return false; } } @@ -1085,12 +1086,12 @@ bool verRctSemanticsSimple(const std::vector &rvv) // we can get deep throws from ge_frombytes_vartime if input isn't valid catch(const std::exception &e) { - LOG_PRINT_L1("Error in verRctSemanticsSimple: " << e.what()); + GULPSF_LOG_L1("Error in verRctSemanticsSimple: {}", e.what()); return false; } catch(...) { - LOG_PRINT_L1("Error in verRctSemanticsSimple, but not an actual exception"); + GULPS_LOG_L1("Error in verRctSemanticsSimple, but not an actual exception"); return false; } } @@ -1108,13 +1109,13 @@ bool verRctNonSemanticsSimple(const rctSig &rv) { PERF_TIMER(verRctNonSemanticsSimple); - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctNonSemanticsSimple called on non simple rctSig"); + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "verRctNonSemanticsSimple called on non simple rctSig"); const bool bulletproof = rv.type == RCTTypeBulletproof; // semantics check is early, and mixRing/MGs aren't resolved yet if(bulletproof) - CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.p.pseudoOuts and mixRing"); else - CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); + GULPS_CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing"); const size_t threads = std::max(rv.outPk.size(), rv.mixRing.size()); @@ -1140,7 +1141,7 @@ bool verRctNonSemanticsSimple(const rctSig &rv) { if(!results[i]) { - LOG_PRINT_L1("verRctMGSimple failed for input " << i); + GULPSF_LOG_L1("verRctMGSimple failed for input {}", i); return false; } } @@ -1150,12 +1151,12 @@ bool verRctNonSemanticsSimple(const rctSig &rv) // we can get deep throws from ge_frombytes_vartime if input isn't valid catch(const std::exception &e) { - LOG_PRINT_L1("Error in verRctNonSemanticsSimple: " << e.what()); + GULPSF_LOG_L1("Error in verRctNonSemanticsSimple: {}", e.what()); return false; } catch(...) { - LOG_PRINT_L1("Error in verRctNonSemanticsSimple, but not an actual exception"); + GULPS_LOG_L1("Error in verRctNonSemanticsSimple, but not an actual exception"); return false; } } @@ -1172,9 +1173,9 @@ bool verRctNonSemanticsSimple(const rctSig &rv) // must know the destination private key to find the correct amount, else will return a random number ryo_amount decodeRct(const rctSig &rv, const key &sk, unsigned int i, key &mask, hw::device &hwdev) { - CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig"); - CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); - CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig"); + GULPS_CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; @@ -1185,14 +1186,14 @@ ryo_amount decodeRct(const rctSig &rv, const key &sk, unsigned int i, key &mask, DP("C"); DP(C); key Ctmp; - CHECK_AND_ASSERT_THROW_MES(sc_check(mask.bytes) == 0, "warning, bad ECDH mask"); - CHECK_AND_ASSERT_THROW_MES(sc_check(amount.bytes) == 0, "warning, bad ECDH amount"); + GULPS_CHECK_AND_ASSERT_THROW_MES(sc_check(mask.bytes) == 0, "warning, bad ECDH mask"); + GULPS_CHECK_AND_ASSERT_THROW_MES(sc_check(amount.bytes) == 0, "warning, bad ECDH amount"); addKeys2(Ctmp, mask, amount, H); DP("Ctmp"); DP(Ctmp); if(equalKeys(C, Ctmp) == false) { - CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend"); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend"); } return h2d(amount); } @@ -1205,9 +1206,9 @@ ryo_amount decodeRct(const rctSig &rv, const key &sk, unsigned int i, hw::device ryo_amount decodeRctSimple(const rctSig &rv, const key &sk, unsigned int i, key &mask, hw::device &hwdev) { - CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "decodeRct called on non simple rctSig"); - CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); - CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "decodeRct called on non simple rctSig"); + GULPS_CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index"); + GULPS_CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo"); //mask amount and mask ecdhTuple ecdh_info = rv.ecdhInfo[i]; @@ -1218,14 +1219,14 @@ ryo_amount decodeRctSimple(const rctSig &rv, const key &sk, unsigned int i, key DP("C"); DP(C); key Ctmp; - CHECK_AND_ASSERT_THROW_MES(sc_check(mask.bytes) == 0, "warning, bad ECDH mask"); - CHECK_AND_ASSERT_THROW_MES(sc_check(amount.bytes) == 0, "warning, bad ECDH amount"); + GULPS_CHECK_AND_ASSERT_THROW_MES(sc_check(mask.bytes) == 0, "warning, bad ECDH mask"); + GULPS_CHECK_AND_ASSERT_THROW_MES(sc_check(amount.bytes) == 0, "warning, bad ECDH amount"); addKeys2(Ctmp, mask, amount, H); DP("Ctmp"); DP(Ctmp); if(equalKeys(C, Ctmp) == false) { - CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend"); + GULPS_CHECK_AND_ASSERT_THROW_MES(false, "warning, amount decoded incorrectly, will be unable to spend"); } return h2d(amount); } @@ -1238,19 +1239,19 @@ ryo_amount decodeRctSimple(const rctSig &rv, const key &sk, unsigned int i, hw:: bool signMultisig(rctSig &rv, const std::vector &indices, const keyV &k, const multisig_out &msout, const key &secret_key) { - CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, + GULPS_CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull || rv.type == RCTTypeSimple || rv.type == RCTTypeBulletproof, false, "unsupported rct type"); - CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes"); - CHECK_AND_ASSERT_MES(k.size() == rv.p.MGs.size(), false, "Mismatched k/MGs size"); - CHECK_AND_ASSERT_MES(k.size() == msout.c.size(), false, "Mismatched k/msout.c size"); + GULPS_CHECK_AND_ASSERT_MES(indices.size() == k.size(), false, "Mismatched k/indices sizes"); + GULPS_CHECK_AND_ASSERT_MES(k.size() == rv.p.MGs.size(), false, "Mismatched k/MGs size"); + GULPS_CHECK_AND_ASSERT_MES(k.size() == msout.c.size(), false, "Mismatched k/msout.c size"); if(rv.type == RCTTypeFull) { - CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "MGs not a single element"); + GULPS_CHECK_AND_ASSERT_MES(rv.p.MGs.size() == 1, false, "MGs not a single element"); } for(size_t n = 0; n < indices.size(); ++n) { - CHECK_AND_ASSERT_MES(indices[n] < rv.p.MGs[n].ss.size(), false, "Index out of range"); - CHECK_AND_ASSERT_MES(!rv.p.MGs[n].ss[indices[n]].empty(), false, "empty ss line"); + GULPS_CHECK_AND_ASSERT_MES(indices[n] < rv.p.MGs[n].ss.size(), false, "Index out of range"); + GULPS_CHECK_AND_ASSERT_MES(!rv.p.MGs[n].ss[indices[n]].empty(), false, "empty ss line"); } for(size_t n = 0; n < indices.size(); ++n) diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index e5634780..d00e2c1f 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -1,4 +1,5 @@ -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // diff --git a/src/ringct/rctTypes.cpp b/src/ringct/rctTypes.cpp index b2751e04..424c65be 100644 --- a/src/ringct/rctTypes.cpp +++ b/src/ringct/rctTypes.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // @@ -18,17 +19,16 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cryptonote_config.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include "rctTypes.h" using namespace crypto; using namespace std; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "ringct" - namespace rct { +GULPS_CAT_MAJOR("rctTypes"); + //dp //Debug printing for the above types //Actually use DP(value) and #define DBG @@ -36,86 +36,84 @@ namespace rct void dp(key a) { int j = 0; - printf("\""); + GULPS_PRINT("\""); for(j = 0; j < 32; j++) { - printf("%02x", (unsigned char)a.bytes[j]); + GULPSF_PRINT("{0:x}", (unsigned char)a.bytes[j]); } - printf("\""); - printf("\n"); + GULPS_PRINT("\""); + GULPS_PRINT("\n"); } void dp(bool a) { - printf(" ... %s ... ", a ? "true" : "false"); - printf("\n"); + GULPSF_PRINT(" ... {} ... ", a ? "true" : "false"); + GULPS_PRINT("\n"); } void dp(const char *a, int l) { int j = 0; - printf("\""); + GULPS_PRINT("\""); for(j = 0; j < l; j++) { - printf("%02x", (unsigned char)a[j]); + GULPSF_PRINT("{0:x}", (unsigned char)a[j]); } - printf("\""); - printf("\n"); + GULPS_PRINT("\""); + GULPS_PRINT("\n"); } void dp(keyV a) { size_t j = 0; - printf("["); + GULPS_PRINT("["); for(j = 0; j < a.size(); j++) { dp(a[j]); if(j < a.size() - 1) { - printf(","); + GULPS_PRINT(","); } } - printf("]"); - printf("\n"); + GULPS_PRINT("]"); + GULPS_PRINT("\n"); } void dp(keyM a) { size_t j = 0; - printf("["); + GULPS_PRINT("["); for(j = 0; j < a.size(); j++) { dp(a[j]); if(j < a.size() - 1) { - printf(","); + GULPS_PRINT(","); } } - printf("]"); - printf("\n"); + GULPS_PRINT("]"); + GULPS_PRINT("\n"); } void dp(ryo_amount vali) { - printf("x: "); - std::cout << vali; - printf("\n\n"); + GULPS_PRINT("x: ", vali, "\n\n"); } void dp(int vali) { - printf("x: %d\n", vali); - printf("\n"); + GULPSF_PRINT("x: {}\n", vali); + GULPS_PRINT("\n"); } void dp(bits amountb) { for(int i = 0; i < 64; i++) { - printf("%d", amountb[i]); + GULPS_PRINT(amountb[i]); } - printf("\n"); + GULPS_PRINT("\n"); } void dp(const char *st) { - printf("%s\n", st); + GULPSF_PRINT("{}\n", st); } //Various Conversions @@ -237,14 +235,14 @@ ryo_amount b2d(bits amountb) size_t n_bulletproof_amounts(const Bulletproof &proof) { - CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); static const size_t extra_bits = 4; static_assert((1 << extra_bits) == cryptonote::common_config::BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date"); - CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.V.size() <= (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); - CHECK_AND_ASSERT_MES(proof.V.size() * 2 > (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); - CHECK_AND_ASSERT_MES(proof.V.size() > 0, 0, "Empty bulletproof"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); + GULPS_CHECK_AND_ASSERT_MES(proof.V.size() <= (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); + GULPS_CHECK_AND_ASSERT_MES(proof.V.size() * 2 > (1u<<(proof.L.size()-6)), 0, "Invalid bulletproof V/L"); + GULPS_CHECK_AND_ASSERT_MES(proof.V.size() > 0, 0, "Empty bulletproof"); return proof.V.size(); } @@ -254,7 +252,7 @@ size_t n_bulletproof_amounts(const std::vector &proofs) for(const Bulletproof &proof: proofs) { size_t n2 = n_bulletproof_amounts(proof); - CHECK_AND_ASSERT_MES(n2 < std::numeric_limits::max() - n, 0, "Invalid number of bulletproofs"); + GULPS_CHECK_AND_ASSERT_MES(n2 < std::numeric_limits::max() - n, 0, "Invalid number of bulletproofs"); if(n2 == 0) return 0; n += n2; @@ -264,11 +262,11 @@ size_t n_bulletproof_amounts(const std::vector &proofs) size_t n_bulletproof_max_amounts(const Bulletproof &proof) { - CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); - CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() >= 6, 0, "Invalid bulletproof L size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() == proof.R.size(), 0, "Mismatched bulletproof L/R size"); static const size_t extra_bits = 4; static_assert((1 << extra_bits) == cryptonote::common_config::BULLETPROOF_MAX_OUTPUTS, "log2(BULLETPROOF_MAX_OUTPUTS) is out of date"); - CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); + GULPS_CHECK_AND_ASSERT_MES(proof.L.size() <= 6 + extra_bits, 0, "Invalid bulletproof L size"); return 1 << (proof.L.size() - 6); } @@ -278,7 +276,7 @@ size_t n_bulletproof_max_amounts(const std::vector &proofs) for (const Bulletproof &proof: proofs) { size_t n2 = n_bulletproof_max_amounts(proof); - CHECK_AND_ASSERT_MES(n2 < std::numeric_limits::max() - n, 0, "Invalid number of bulletproofs"); + GULPS_CHECK_AND_ASSERT_MES(n2 < std::numeric_limits::max() - n, 0, "Invalid number of bulletproofs"); if (n2 == 0) return 0; n += n2; diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index e01de012..105b5647 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -1,4 +1,5 @@ -// Copyright (c) 2016, Monero Research Labs +// Copyright (c) 2019, Ryo Currency Project +// Portions copyright (c) 2016, Monero Research Labs // // Author: Shen Noether // diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 921a19c0..417d8ab3 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -118,6 +118,7 @@ target_link_libraries(rpc_base ${Boost_REGEX_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) @@ -130,10 +131,13 @@ target_link_libraries(rpc epee ${Boost_REGEX_LIBRARY} ${Boost_THREAD_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) target_link_libraries(daemon_messages + LINK_PUBLIC + fmt::fmt-header-only LINK_PRIVATE cryptonote_core cryptonote_protocol @@ -141,6 +145,8 @@ target_link_libraries(daemon_messages ${EXTRA_LIBRARIES}) target_link_libraries(daemon_rpc_server + LINK_PUBLIC + fmt::fmt-header-only LINK_PRIVATE rpc cryptonote_core diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index d0a3317a..d9bfdfaa 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -40,12 +40,14 @@ using namespace epee; #include "storages/http_abstract_invoke.h" #include "version.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon.rpc" +#include "common/gulps.hpp" + #define MAX_RESTRICTED_FAKE_OUTS_COUNT 40 #define MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT 5000 +extern gulps_log_level log_scr; + namespace { void add_reason(std::string &reasons, const char *reason) @@ -58,7 +60,7 @@ void add_reason(std::string &reasons, const char *reason) namespace cryptonote { - +GULPS_CAT_MAJOR("c_rpc_serv"); //----------------------------------------------------------------------------------- void core_rpc_server::init_options(boost::program_options::options_description &desc) { @@ -203,27 +205,6 @@ bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request &req, COMM return true; } //------------------------------------------------------------------------------------------------------------------------------ -static cryptonote::blobdata get_pruned_tx_blob(cryptonote::transaction &tx) -{ - std::stringstream ss; - binary_archive ba(ss); - bool r = tx.serialize_base(ba); - CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); - return ss.str(); -} -//------------------------------------------------------------------------------------------------------------------------------ -static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobdata) -{ - cryptonote::transaction tx; - - if(!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx)) - { - MERROR("Failed to parse and validate tx from blob"); - return cryptonote::blobdata(); - } - return get_pruned_tx_blob(tx); -} -//------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request &req, COMMAND_RPC_GET_BLOCKS_FAST::response &res) { PERF_TIMER(on_get_blocks); @@ -231,59 +212,19 @@ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request & if(use_bootstrap_daemon_if_necessary(invoke_http_mode::BIN, "/getblocks.bin", req, res, r)) return r; - std::list>> bs; - - if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) + if(!req.prune) { res.status = "Failed"; return false; } - size_t pruned_size = 0, unpruned_size = 0, ntxes = 0; - for(auto &bd : bs) + if(!m_core.find_blockchain_supplement_indexed(req.start_height, req.block_ids, res.blocks, res.output_indices, + res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) { - res.blocks.resize(res.blocks.size() + 1); - res.blocks.back().block = bd.first; - pruned_size += bd.first.size(); - unpruned_size += bd.first.size(); - res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices()); - res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); - block b; - if(!parse_and_validate_block_from_blob(bd.first, b)) - { - res.status = "Invalid block"; - return false; - } - bool r = m_core.get_tx_outputs_gindexs(get_transaction_hash(b.miner_tx), res.output_indices.back().indices.back().indices); - if(!r) - { - res.status = "Failed"; - return false; - } - size_t txidx = 0; - ntxes += bd.second.size(); - for(std::list::iterator i = bd.second.begin(); i != bd.second.end(); ++i) - { - unpruned_size += i->size(); - if(req.prune) - res.blocks.back().txs.push_back(get_pruned_tx_blob(std::move(*i))); - else - res.blocks.back().txs.push_back(std::move(*i)); - i->clear(); - i->shrink_to_fit(); - pruned_size += res.blocks.back().txs.back().size(); - - res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); - bool r = m_core.get_tx_outputs_gindexs(b.tx_hashes[txidx++], res.output_indices.back().indices.back().indices); - if(!r) - { - res.status = "Failed"; - return false; - } - } + res.status = "Failed"; + return false; } - MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, pruned size " << pruned_size << ", unpruned size " << unpruned_size); res.status = CORE_RPC_STATUS_OK; return true; } @@ -309,7 +250,7 @@ bool core_rpc_server::on_get_alt_blocks_hashes(const COMMAND_RPC_GET_ALT_BLOCKS_ res.blks_hashes.push_back(epee::string_tools::pod_to_hex(get_block_hash(blk))); } - MDEBUG("on_get_alt_blocks_hashes: " << blks.size() << " blocks "); + GULPSF_LOG_L1("on_get_alt_blocks_hashes: {} blocks ", blks.size() ); res.status = CORE_RPC_STATUS_OK; return true; } @@ -400,14 +341,14 @@ bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FO typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; std::for_each(res.outs.begin(), res.outs.end(), [&](outs_for_amount &ofa) { ss << "[" << ofa.amount << "]:"; - CHECK_AND_ASSERT_MES(ofa.outs.size(), ;, "internal error: ofa.outs.size() is empty for amount " << ofa.amount); + GULPS_CHECK_AND_ASSERT_MES(ofa.outs.size(), ;, "internal error: ofa.outs.size() is empty for amount " , ofa.amount); std::for_each(ofa.outs.begin(), ofa.outs.end(), [&](out_entry &oe) { ss << oe.global_amount_index << " "; }); - ss << ENDL; + ss << "\n"; }); std::string s = ss.str(); - LOG_PRINT_L2("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: " << ENDL << s); + GULPSF_LOG_L2("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: \n{}", s); res.status = CORE_RPC_STATUS_OK; return true; } @@ -497,13 +438,13 @@ bool core_rpc_server::on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OU res.status = CORE_RPC_STATUS_OK; std::stringstream ss; typedef COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry out_entry; - CHECK_AND_ASSERT_MES(res.outs.size(), true, "internal error: res.outs.size() is empty"); + GULPS_CHECK_AND_ASSERT_MES(res.outs.size(), true, "internal error: res.outs.size() is empty"); std::for_each(res.outs.begin(), res.outs.end(), [&](out_entry &oe) { ss << oe.global_amount_index << " "; }); - ss << ENDL; + ss << "\n"; std::string s = ss.str(); - LOG_PRINT_L2("COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS: " << ENDL << s); + GULPSF_LOG_L2("COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS: \n{}", s); res.status = CORE_RPC_STATUS_OK; return true; } @@ -522,7 +463,7 @@ bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_IND return true; } res.status = CORE_RPC_STATUS_OK; - LOG_PRINT_L2("COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES: [" << res.o_indexes.size() << "]"); + GULPSF_LOG_L2("COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES: [{}]", res.o_indexes.size() ); return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -557,7 +498,7 @@ bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::re res.status = "Failed"; return true; } - LOG_PRINT_L2("Found " << txs.size() << "/" << vh.size() << " transactions on the blockchain"); + GULPSF_LOG_L2("Found {}/{} transactions on the blockchain", txs.size() , vh.size() ); // try the pool for any missing txes size_t found_in_pool = 0; @@ -616,7 +557,7 @@ bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::re } txs = sorted_txs; } - LOG_PRINT_L2("Found " << found_in_pool << "/" << vh.size() << " transactions in the pool"); + GULPSF_LOG_L2("Found {}/{} transactions in the pool", found_in_pool , vh.size() ); } std::list::const_iterator txhi = req.txs_hashes.begin(); @@ -642,7 +583,7 @@ bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::re } else { - MERROR("Failed to determine double spend status for " << tx_hash); + GULPS_ERROR("Failed to determine double spend status for {}", tx_hash); e.double_spend_seen = false; } } @@ -675,7 +616,7 @@ bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::re res.missed_tx.push_back(string_tools::pod_to_hex(miss_tx)); } - LOG_PRINT_L2(res.txs.size() << " transactions found, " << res.missed_tx.size() << " not found"); + GULPSF_LOG_L2("{} transactions found, {} not found", res.txs.size(), res.missed_tx.size()); res.status = CORE_RPC_STATUS_OK; return true; } @@ -759,7 +700,7 @@ bool core_rpc_server::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request &req std::string tx_blob; if(!string_tools::parse_hexstr_to_binbuff(req.tx_as_hex, tx_blob)) { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to parse tx from hexbuff: " << req.tx_as_hex); + GULPSF_PRINT("[on_send_raw_tx]: Failed to parse tx from hexbuff: {}", req.tx_as_hex); res.status = "Failed"; return true; } @@ -789,18 +730,18 @@ bool core_rpc_server::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request &req const std::string punctuation = res.reason.empty() ? "" : ": "; if(tvc.m_verifivation_failed) { - LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed" << punctuation << res.reason); + GULPSF_PRINT("[on_send_raw_tx]: tx verification failed{} {}", punctuation, res.reason); } else { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx" << punctuation << res.reason); + GULPSF_PRINT("[on_send_raw_tx]: Failed to process tx {} {}", punctuation, res.reason); } return true; } if(!tvc.m_should_be_relayed) { - LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); + GULPS_PRINT("[on_send_raw_tx]: tx accepted, but not relayed"); res.reason = "Not relayed"; res.not_relayed = true; res.status = CORE_RPC_STATUS_OK; @@ -823,22 +764,22 @@ bool core_rpc_server::on_start_mining(const COMMAND_RPC_START_MINING::request &r if(!get_account_address_from_str(m_nettype, info, req.miner_address)) { res.status = "Failed, wrong address"; - LOG_PRINT_L0(res.status); + GULPS_PRINT(res.status); return true; } - if(req.miner_address == common_config::DEV_FUND_ADDRESS) - { - res.status = "Dev fund address is not mineable. If you would like to support the dev team please mine to "; - res.status += common_config::RYO_DONATION_ADDR; - LOG_PRINT_L0(res.status); - return true; + if(req.miner_address == common_config::DEV_FUND_ADDRESS) + { + res.status = "Dev fund address is not mineable. If you would like to support the dev team please mine to "; + res.status += common_config::RYO_DONATION_ADDR; + GULPS_PRINT(res.status); + return true; } if(info.is_subaddress) { res.status = "Mining to subaddress isn't supported yet"; - LOG_PRINT_L0(res.status); + GULPS_PRINT(res.status); return true; } @@ -855,7 +796,7 @@ bool core_rpc_server::on_start_mining(const COMMAND_RPC_START_MINING::request &r if(req.threads_count > concurrency_count) { res.status = "Failed, too many threads relative to CPU cores."; - LOG_PRINT_L0(res.status); + GULPS_PRINT(res.status); return true; } @@ -865,7 +806,7 @@ bool core_rpc_server::on_start_mining(const COMMAND_RPC_START_MINING::request &r if(!m_core.get_miner().start(info.address, static_cast(req.threads_count), attrs, req.do_background_mining, req.ignore_battery)) { res.status = "Failed, mining not started"; - LOG_PRINT_L0(res.status); + GULPS_PRINT(res.status); return true; } res.status = CORE_RPC_STATUS_OK; @@ -878,7 +819,7 @@ bool core_rpc_server::on_stop_mining(const COMMAND_RPC_STOP_MINING::request &req if(!m_core.get_miner().stop()) { res.status = "Failed, mining not stopped"; - LOG_PRINT_L0(res.status); + GULPS_PRINT(res.status); return true; } res.status = CORE_RPC_STATUS_OK; @@ -969,7 +910,8 @@ bool core_rpc_server::on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request res.status = "Error: log level not valid"; return true; } - mlog_set_log_level(req.level); + + log_scr.parse_cat_string(std::to_string(req.level).c_str()); res.status = CORE_RPC_STATUS_OK; return true; } @@ -977,8 +919,9 @@ bool core_rpc_server::on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request bool core_rpc_server::on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request &req, COMMAND_RPC_SET_LOG_CATEGORIES::response &res) { PERF_TIMER(on_set_log_categories); - mlog_set_log(req.categories.c_str()); - res.categories = mlog_get_categories(); + + log_scr.parse_cat_string(req.categories.c_str()); + res.categories = log_scr.get_current_cat_str(); res.status = CORE_RPC_STATUS_OK; return true; } @@ -1141,7 +1084,7 @@ bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::re { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to create block template"); + GULPS_LOG_ERROR("Failed to create block template"); return false; } blobdata block_blob = t_serializable_object_to_blob(b); @@ -1150,7 +1093,7 @@ bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::re { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to tx pub key in coinbase extra"); + GULPS_LOG_ERROR("Failed to tx pub key in coinbase extra"); return false; } res.reserved_offset = slow_memmem((void *)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); @@ -1158,7 +1101,7 @@ bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::re { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to find tx pub key in blockblob"); + GULPS_LOG_ERROR("Failed to find tx pub key in blockblob"); return false; } res.reserved_offset += sizeof(tx_pub_key) + 2; //2 bytes: tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte) @@ -1166,7 +1109,7 @@ bool core_rpc_server::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::re { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Internal error: failed to create block template"; - LOG_ERROR("Failed to calculate offset for "); + GULPS_LOG_ERROR("Failed to calculate offset for "); return false; } blobdata hashing_blob = get_block_hashing_blob(b); @@ -1271,7 +1214,7 @@ bool core_rpc_server::use_bootstrap_daemon_if_necessary(const invoke_http_mode & boost::unique_lock lock(m_bootstrap_daemon_mutex); if(!m_should_use_bootstrap_daemon) { - MINFO("The local daemon is fully synced. Not switching back to the bootstrap daemon"); + GULPS_INFO("The local daemon is fully synced. Not switching back to the bootstrap daemon"); return false; } @@ -1292,7 +1235,7 @@ bool core_rpc_server::use_bootstrap_daemon_if_necessary(const invoke_http_mode & ok = ok && getheight_res.status == CORE_RPC_STATUS_OK; m_should_use_bootstrap_daemon = ok && top_height + 10 < getheight_res.height; - MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << getheight_res.height << ")"); + GULPSF_INFO("{} the bootstrap daemon (our height: {} , bootstrap daemon's height: {})", (m_should_use_bootstrap_daemon ? "Using" : "Not using"), top_height, getheight_res.height); } if(!m_should_use_bootstrap_daemon) return false; @@ -1319,7 +1262,7 @@ bool core_rpc_server::use_bootstrap_daemon_if_necessary(const invoke_http_mode & } else { - MERROR("Unknown invoke_http_mode: " << mode); + GULPS_ERROR("Unknown invoke_http_mode: {}", mode); return false; } m_was_bootstrap_ever_used = true; @@ -1793,7 +1736,8 @@ bool core_rpc_server::on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CH std::list> chains = m_core.get_blockchain_storage().get_alternative_chains(); for(const auto &i : chains) { - res.chains.push_back(COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info{epee::string_tools::pod_to_hex(get_block_hash(i.first.bl)), i.first.height, i.second, i.first.cumulative_difficulty}); + res.chains.emplace_back(COMMAND_RPC_GET_ALTERNATE_CHAINS::chain_info{epee::string_tools::pod_to_hex(get_block_hash(i.first.bl)), i.first.height, + i.second, i.first.cumulative_difficulty}); } res.status = CORE_RPC_STATUS_OK; } @@ -1943,27 +1887,27 @@ bool core_rpc_server::on_update(const COMMAND_RPC_UPDATE::request &req, COMMAND_ crypto::hash file_hash; if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash))) { - MDEBUG("We don't have that file already, downloading"); + GULPS_LOG_L1("We don't have that file already, downloading"); if (!tools::download(path.string(), res.auto_uri)) { - MERROR("Failed to download " << res.auto_uri); + GULPS_ERROR("Failed to download {}", res.auto_uri); return false; } if (!tools::sha256sum(path.string(), file_hash)) { - MERROR("Failed to hash " << path); + GULPS_ERROR("Failed to hash {}", path); return false; } if (hash != epee::string_tools::pod_to_hex(file_hash)) { - MERROR("Download from " << res.auto_uri << " does not match the expected hash"); + GULPS_ERROR("Download from {} does not match the expected hash", res.auto_uri ); return false; } - MINFO("New version downloaded to " << path); + GULPSF_INFO("New version downloaded to {}", path); } else { - MDEBUG("We already have " << path << " with expected hash"); + GULPSF_LOG_L1("We already have {} with expected hash", path ); } res.path = path.string(); diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index b17d50bf..5e88425e 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,6 +30,8 @@ #include "net/http_server_impl_base.h" #include "p2p/net_node.h" +#include "common/gulps.hpp" + // yes, epee doesn't properly use its full namespace when calling its // functions from macros. *sigh* using namespace epee; @@ -41,6 +43,7 @@ namespace cryptonote /************************************************************************/ class core_rpc_server : public epee::http_server_impl_base { + GULPS_CAT_MAJOR("c_rpc_serv"); public: static const command_line::arg_descriptor arg_rpc_bind_port; static const command_line::arg_descriptor arg_rpc_restricted_bind_port; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 32a752b7..4fc8b6fe 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -47,7 +47,7 @@ struct COMMAND_RPC_GET_HEIGHT { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -57,7 +57,7 @@ struct COMMAND_RPC_GET_HEIGHT std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(height) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -73,7 +73,7 @@ struct COMMAND_RPC_GET_BLOCKS_FAST std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ uint64_t start_height; bool prune; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) KV_SERIALIZE(start_height) KV_SERIALIZE(prune) @@ -84,7 +84,7 @@ struct COMMAND_RPC_GET_BLOCKS_FAST { std::vector indices; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(tx_output_indices) KV_SERIALIZE(indices) END_KV_SERIALIZE_MAP() }; @@ -93,21 +93,21 @@ struct COMMAND_RPC_GET_BLOCKS_FAST { std::vector indices; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(block_output_indices) KV_SERIALIZE(indices) END_KV_SERIALIZE_MAP() }; struct response { - std::list blocks; + std::vector blocks; uint64_t start_height; uint64_t current_height; std::string status; std::vector output_indices; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(blocks) KV_SERIALIZE(start_height) KV_SERIALIZE(current_height) @@ -123,7 +123,7 @@ struct COMMAND_RPC_GET_BLOCKS_BY_HEIGHT struct request { std::vector heights; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(heights) END_KV_SERIALIZE_MAP() }; @@ -134,7 +134,7 @@ struct COMMAND_RPC_GET_BLOCKS_BY_HEIGHT std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(blocks) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -146,7 +146,7 @@ struct COMMAND_RPC_GET_ALT_BLOCKS_HASHES { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -156,7 +156,7 @@ struct COMMAND_RPC_GET_ALT_BLOCKS_HASHES std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(blks_hashes) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -170,7 +170,7 @@ struct COMMAND_RPC_GET_HASHES_FAST { std::list block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ uint64_t start_height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) KV_SERIALIZE(start_height) END_KV_SERIALIZE_MAP() @@ -184,7 +184,7 @@ struct COMMAND_RPC_GET_HASHES_FAST std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_block_ids) KV_SERIALIZE(start_height) KV_SERIALIZE(current_height) @@ -202,7 +202,7 @@ struct COMMAND_RPC_GET_ADDRESS_TXS std::string address; std::string view_key; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(address) KV_SERIALIZE(view_key) END_KV_SERIALIZE_MAP() @@ -216,7 +216,7 @@ struct COMMAND_RPC_GET_ADDRESS_TXS uint64_t out_index; uint32_t mixin; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(spent_output) KV_SERIALIZE(amount) KV_SERIALIZE(key_image) KV_SERIALIZE(tx_pub_key) @@ -240,7 +240,7 @@ struct COMMAND_RPC_GET_ADDRESS_TXS bool mempool; uint32_t mixin; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(transaction) KV_SERIALIZE(id) KV_SERIALIZE(hash) KV_SERIALIZE(timestamp) @@ -266,7 +266,7 @@ struct COMMAND_RPC_GET_ADDRESS_TXS uint64_t blockchain_height; uint64_t scanned_block_height; std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(total_received) KV_SERIALIZE(total_received_unlocked) KV_SERIALIZE(scanned_height) @@ -286,7 +286,7 @@ struct COMMAND_RPC_GET_ADDRESS_INFO std::string address; std::string view_key; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(address) KV_SERIALIZE(view_key) END_KV_SERIALIZE_MAP() @@ -300,7 +300,7 @@ struct COMMAND_RPC_GET_ADDRESS_INFO uint64_t out_index; uint32_t mixin; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(spent_output) KV_SERIALIZE(amount) KV_SERIALIZE(key_image) KV_SERIALIZE(tx_pub_key) @@ -320,7 +320,7 @@ struct COMMAND_RPC_GET_ADDRESS_INFO uint64_t transaction_height; uint64_t blockchain_height; std::list spent_outputs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(locked_funds) KV_SERIALIZE(total_received) KV_SERIALIZE(total_sent) @@ -347,7 +347,7 @@ struct COMMAND_RPC_GET_UNSPENT_OUTS bool use_dust; std::string dust_threshold; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(amount) KV_SERIALIZE(address) KV_SERIALIZE(view_key) @@ -371,7 +371,7 @@ struct COMMAND_RPC_GET_UNSPENT_OUTS uint64_t timestamp; uint64_t height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(output) KV_SERIALIZE(amount) KV_SERIALIZE(public_key) KV_SERIALIZE(index) @@ -393,7 +393,7 @@ struct COMMAND_RPC_GET_UNSPENT_OUTS uint64_t per_kb_fee; std::string status; std::string reason; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(amount) KV_SERIALIZE(outputs) KV_SERIALIZE(per_kb_fee) @@ -411,7 +411,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTS std::vector amounts; uint32_t count; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(amounts) KV_SERIALIZE(count) END_KV_SERIALIZE_MAP() @@ -423,7 +423,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTS uint64_t global_index; std::string rct; // 64+64+64 characters long ( + + ) - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(output) KV_SERIALIZE(public_key) KV_SERIALIZE(global_index) KV_SERIALIZE(rct) @@ -434,7 +434,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTS { uint64_t amount; std::vector outputs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(amount_out) KV_SERIALIZE(amount) KV_SERIALIZE(outputs) END_KV_SERIALIZE_MAP() @@ -444,7 +444,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTS { std::vector amount_outs; std::string Error; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(amount_outs) KV_SERIALIZE(Error) END_KV_SERIALIZE_MAP() @@ -459,7 +459,7 @@ struct COMMAND_RPC_SUBMIT_RAW_TX std::string view_key; std::string tx; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(address) KV_SERIALIZE(view_key) KV_SERIALIZE(tx) @@ -471,7 +471,7 @@ struct COMMAND_RPC_SUBMIT_RAW_TX std::string status; std::string error; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(error) END_KV_SERIALIZE_MAP() @@ -486,7 +486,7 @@ struct COMMAND_RPC_LOGIN std::string view_key; bool create_account; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(address) KV_SERIALIZE(view_key) KV_SERIALIZE(create_account) @@ -499,7 +499,7 @@ struct COMMAND_RPC_LOGIN std::string reason; bool new_address; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(reason) KV_SERIALIZE(new_address) @@ -514,7 +514,7 @@ struct COMMAND_RPC_IMPORT_WALLET_REQUEST std::string address; std::string view_key; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(address) KV_SERIALIZE(view_key) END_KV_SERIALIZE_MAP() @@ -529,7 +529,7 @@ struct COMMAND_RPC_IMPORT_WALLET_REQUEST std::string payment_address; std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(payment_id) KV_SERIALIZE(import_fee) KV_SERIALIZE(new_request) @@ -548,7 +548,7 @@ struct COMMAND_RPC_GET_TRANSACTIONS bool decode_as_json; bool prune; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(txs_hashes) KV_SERIALIZE(decode_as_json) KV_SERIALIZE_OPT(prune, false) @@ -566,7 +566,7 @@ struct COMMAND_RPC_GET_TRANSACTIONS uint64_t block_timestamp; std::vector output_indices; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(entry) KV_SERIALIZE(tx_hash) KV_SERIALIZE(as_hex) KV_SERIALIZE(as_json) @@ -592,7 +592,7 @@ struct COMMAND_RPC_GET_TRANSACTIONS std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(txs_as_hex) KV_SERIALIZE(txs_as_json) KV_SERIALIZE(txs) @@ -617,7 +617,7 @@ struct COMMAND_RPC_IS_KEY_IMAGE_SPENT { std::vector key_images; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(key_images) END_KV_SERIALIZE_MAP() }; @@ -628,7 +628,7 @@ struct COMMAND_RPC_IS_KEY_IMAGE_SPENT std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(spent_status) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -642,7 +642,7 @@ struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES struct request { crypto::hash txid; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE_VAL_POD_AS_BLOB(txid) END_KV_SERIALIZE_MAP() }; @@ -652,7 +652,7 @@ struct COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES std::vector o_indexes; std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(o_indexes) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -666,7 +666,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS { std::vector amounts; uint64_t outs_count; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(amounts) KV_SERIALIZE(outs_count) END_KV_SERIALIZE_MAP() @@ -685,7 +685,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS uint64_t amount; std::list outs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(outs_for_amount) KV_SERIALIZE(amount) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) END_KV_SERIALIZE_MAP() @@ -696,7 +696,7 @@ struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS std::vector outs; std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(outs) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -706,10 +706,12 @@ struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS //----------------------------------------------- struct get_outputs_out { + get_outputs_out(uint64_t amount, uint64_t index) : amount(amount), index(index) {} + uint64_t amount; uint64_t index; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(get_outputs_out) KV_SERIALIZE(amount) KV_SERIALIZE(index) END_KV_SERIALIZE_MAP() @@ -721,20 +723,23 @@ struct COMMAND_RPC_GET_OUTPUTS_BIN { std::vector outputs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(outputs) END_KV_SERIALIZE_MAP() }; struct outkey { + outkey(crypto::public_key key, rct::key mask, bool unlocked, uint64_t height, crypto::hash txid) : key(key), mask(mask), + unlocked(unlocked), height(height), txid(txid) {} + crypto::public_key key; rct::key mask; bool unlocked; uint64_t height; crypto::hash txid; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(outkey) KV_SERIALIZE_VAL_POD_AS_BLOB(key) KV_SERIALIZE_VAL_POD_AS_BLOB(mask) KV_SERIALIZE(unlocked) @@ -749,7 +754,7 @@ struct COMMAND_RPC_GET_OUTPUTS_BIN std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(outs) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -763,7 +768,7 @@ struct COMMAND_RPC_GET_OUTPUTS { std::vector outputs; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(outputs) END_KV_SERIALIZE_MAP() }; @@ -776,7 +781,7 @@ struct COMMAND_RPC_GET_OUTPUTS uint64_t height; std::string txid; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(outkey) KV_SERIALIZE(key) KV_SERIALIZE(mask) KV_SERIALIZE(unlocked) @@ -791,7 +796,7 @@ struct COMMAND_RPC_GET_OUTPUTS std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(outs) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -804,7 +809,7 @@ struct COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS struct request { uint64_t outs_count; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(outs_count) END_KV_SERIALIZE_MAP() }; @@ -824,7 +829,7 @@ struct COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS std::list outs; std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outs) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -839,10 +844,9 @@ struct COMMAND_RPC_SEND_RAW_TX std::string tx_as_hex; bool do_not_relay; - request() {} explicit request(const transaction &); - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(tx_as_hex) KV_SERIALIZE_OPT(do_not_relay, false) END_KV_SERIALIZE_MAP() @@ -863,7 +867,7 @@ struct COMMAND_RPC_SEND_RAW_TX bool not_rct; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(reason) KV_SERIALIZE(not_relayed) @@ -889,7 +893,7 @@ struct COMMAND_RPC_START_MINING bool do_background_mining; bool ignore_battery; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(miner_address) KV_SERIALIZE(threads_count) KV_SERIALIZE(do_background_mining) @@ -901,7 +905,7 @@ struct COMMAND_RPC_START_MINING { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -912,7 +916,7 @@ struct COMMAND_RPC_GET_INFO struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -947,7 +951,7 @@ struct COMMAND_RPC_GET_INFO uint64_t height_without_bootstrap; bool was_bootstrap_ever_used; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(height) KV_SERIALIZE(target_height) @@ -986,7 +990,7 @@ struct COMMAND_RPC_STOP_MINING struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -994,7 +998,7 @@ struct COMMAND_RPC_STOP_MINING { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1006,7 +1010,7 @@ struct COMMAND_RPC_MINING_STATUS struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1019,7 +1023,7 @@ struct COMMAND_RPC_MINING_STATUS std::string address; bool is_background_mining_enabled; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(active) KV_SERIALIZE(speed) @@ -1036,7 +1040,7 @@ struct COMMAND_RPC_SAVE_BC struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1044,7 +1048,7 @@ struct COMMAND_RPC_SAVE_BC { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1060,7 +1064,7 @@ struct COMMAND_RPC_GETBLOCKCOUNT uint64_t count; std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(count) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() @@ -1081,7 +1085,7 @@ struct COMMAND_RPC_GETBLOCKTEMPLATE uint64_t reserve_size; //max 255 bytes std::string wallet_address; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(reserve_size) KV_SERIALIZE(wallet_address) END_KV_SERIALIZE_MAP() @@ -1099,7 +1103,7 @@ struct COMMAND_RPC_GETBLOCKTEMPLATE std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(difficulty) KV_SERIALIZE(height) KV_SERIALIZE(reserved_offset) @@ -1121,7 +1125,7 @@ struct COMMAND_RPC_SUBMITBLOCK { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1143,7 +1147,7 @@ struct block_header_response uint64_t block_size; uint64_t num_txes; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(block_header_response) KV_SERIALIZE(major_version) KV_SERIALIZE(minor_version) KV_SERIALIZE(timestamp) @@ -1164,7 +1168,7 @@ struct COMMAND_RPC_GET_LAST_BLOCK_HEADER { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1174,7 +1178,7 @@ struct COMMAND_RPC_GET_LAST_BLOCK_HEADER block_header_response block_header; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(block_header) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -1188,7 +1192,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH { std::string hash; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(hash) END_KV_SERIALIZE_MAP() }; @@ -1199,7 +1203,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH block_header_response block_header; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(block_header) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -1213,7 +1217,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT { uint64_t height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(height) END_KV_SERIALIZE_MAP() }; @@ -1224,7 +1228,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT block_header_response block_header; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(block_header) KV_SERIALIZE(status) KV_SERIALIZE(untrusted) @@ -1239,7 +1243,7 @@ struct COMMAND_RPC_GET_BLOCK std::string hash; uint64_t height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(hash) KV_SERIALIZE(height) END_KV_SERIALIZE_MAP() @@ -1255,7 +1259,7 @@ struct COMMAND_RPC_GET_BLOCK std::string json; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(block_header) KV_SERIALIZE(miner_tx_hash) KV_SERIALIZE(tx_hashes) @@ -1275,8 +1279,6 @@ struct peer uint16_t port; uint64_t last_seen; - peer() = default; - peer(uint64_t id, const std::string &host, uint64_t last_seen) : id(id), host(host), ip(0), port(0), last_seen(last_seen) { @@ -1286,7 +1288,7 @@ struct peer { } - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(peer) KV_SERIALIZE(id) KV_SERIALIZE(host) KV_SERIALIZE(ip) @@ -1299,7 +1301,7 @@ struct COMMAND_RPC_GET_PEER_LIST { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1309,7 +1311,7 @@ struct COMMAND_RPC_GET_PEER_LIST std::vector white_list; std::vector gray_list; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(white_list) KV_SERIALIZE(gray_list) @@ -1323,7 +1325,7 @@ struct COMMAND_RPC_SET_LOG_HASH_RATE { bool visible; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(visible) END_KV_SERIALIZE_MAP() }; @@ -1331,7 +1333,7 @@ struct COMMAND_RPC_SET_LOG_HASH_RATE struct response { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1343,7 +1345,7 @@ struct COMMAND_RPC_SET_LOG_LEVEL { int8_t level; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(level) END_KV_SERIALIZE_MAP() }; @@ -1351,7 +1353,7 @@ struct COMMAND_RPC_SET_LOG_LEVEL struct response { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1363,7 +1365,7 @@ struct COMMAND_RPC_SET_LOG_CATEGORIES { std::string categories; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(categories) END_KV_SERIALIZE_MAP() }; @@ -1373,7 +1375,7 @@ struct COMMAND_RPC_SET_LOG_CATEGORIES std::string status; std::string categories; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(categories) END_KV_SERIALIZE_MAP() @@ -1398,7 +1400,7 @@ struct tx_info bool double_spend_seen; std::string tx_blob; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(tx_info) KV_SERIALIZE(id_hash) KV_SERIALIZE(tx_json) KV_SERIALIZE(blob_size) @@ -1422,7 +1424,7 @@ struct spent_key_image_info std::string id_hash; std::vector txs_hashes; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(spent_key_image_info) KV_SERIALIZE(id_hash) KV_SERIALIZE(txs_hashes) END_KV_SERIALIZE_MAP() @@ -1432,7 +1434,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1443,7 +1445,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL std::vector spent_key_images; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(transactions) KV_SERIALIZE(spent_key_images) @@ -1456,7 +1458,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_HASHES { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1466,7 +1468,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_HASHES std::vector tx_hashes; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(tx_hashes) KV_SERIALIZE(untrusted) @@ -1485,7 +1487,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1495,7 +1497,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG std::vector backlog; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(backlog) KV_SERIALIZE(untrusted) @@ -1508,7 +1510,7 @@ struct txpool_histo uint32_t txs; uint64_t bytes; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(txpool_histo) KV_SERIALIZE(txs) KV_SERIALIZE(bytes) END_KV_SERIALIZE_MAP() @@ -1547,7 +1549,7 @@ struct txpool_stats num_double_spends = 0; } - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(txpool_stats) KV_SERIALIZE(bytes_total) KV_SERIALIZE(bytes_min) KV_SERIALIZE(bytes_max) @@ -1568,7 +1570,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_STATS { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1578,7 +1580,7 @@ struct COMMAND_RPC_GET_TRANSACTION_POOL_STATS txpool_stats pool_stats; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(pool_stats) KV_SERIALIZE(untrusted) @@ -1590,7 +1592,7 @@ struct COMMAND_RPC_GET_CONNECTIONS { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1599,7 +1601,7 @@ struct COMMAND_RPC_GET_CONNECTIONS std::string status; std::list connections; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(connections) END_KV_SERIALIZE_MAP() @@ -1613,7 +1615,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADERS_RANGE uint64_t start_height; uint64_t end_height; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(start_height) KV_SERIALIZE(end_height) END_KV_SERIALIZE_MAP() @@ -1625,7 +1627,7 @@ struct COMMAND_RPC_GET_BLOCK_HEADERS_RANGE std::vector headers; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(headers) KV_SERIALIZE(untrusted) @@ -1637,7 +1639,7 @@ struct COMMAND_RPC_STOP_DAEMON { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1645,7 +1647,7 @@ struct COMMAND_RPC_STOP_DAEMON { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1655,7 +1657,7 @@ struct COMMAND_RPC_FAST_EXIT { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1663,7 +1665,7 @@ struct COMMAND_RPC_FAST_EXIT { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1673,7 +1675,7 @@ struct COMMAND_RPC_GET_LIMIT { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1684,7 +1686,7 @@ struct COMMAND_RPC_GET_LIMIT uint64_t limit_down; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(limit_up) KV_SERIALIZE(limit_down) @@ -1700,7 +1702,7 @@ struct COMMAND_RPC_SET_LIMIT int64_t limit_down; // all limits (for get and set) are kB/s int64_t limit_up; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(limit_down) KV_SERIALIZE(limit_up) END_KV_SERIALIZE_MAP() @@ -1712,7 +1714,7 @@ struct COMMAND_RPC_SET_LIMIT int64_t limit_up; int64_t limit_down; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(limit_up) KV_SERIALIZE(limit_down) @@ -1725,7 +1727,7 @@ struct COMMAND_RPC_OUT_PEERS struct request { uint64_t out_peers; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(out_peers) END_KV_SERIALIZE_MAP() }; @@ -1734,7 +1736,7 @@ struct COMMAND_RPC_OUT_PEERS { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1745,7 +1747,7 @@ struct COMMAND_RPC_IN_PEERS struct request { uint64_t in_peers; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(in_peers) END_KV_SERIALIZE_MAP() }; @@ -1754,7 +1756,7 @@ struct COMMAND_RPC_IN_PEERS { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1766,7 +1768,7 @@ struct COMMAND_RPC_HARD_FORK_INFO { uint8_t version; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(version) END_KV_SERIALIZE_MAP() }; @@ -1784,7 +1786,7 @@ struct COMMAND_RPC_HARD_FORK_INFO std::string status; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(version) KV_SERIALIZE(enabled) KV_SERIALIZE(window) @@ -1807,7 +1809,7 @@ struct COMMAND_RPC_GETBANS uint32_t ip; uint32_t seconds; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(ban) KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(seconds) @@ -1816,7 +1818,7 @@ struct COMMAND_RPC_GETBANS struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1825,7 +1827,7 @@ struct COMMAND_RPC_GETBANS std::string status; std::vector bans; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(bans) END_KV_SERIALIZE_MAP() @@ -1834,14 +1836,14 @@ struct COMMAND_RPC_GETBANS struct COMMAND_RPC_SETBANS { - struct ban + struct ban_data { std::string host; uint32_t ip; bool ban; uint32_t seconds; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(ban_data) KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(ban) @@ -1851,9 +1853,9 @@ struct COMMAND_RPC_SETBANS struct request { - std::vector bans; + std::vector bans; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(bans) END_KV_SERIALIZE_MAP() }; @@ -1862,7 +1864,7 @@ struct COMMAND_RPC_SETBANS { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1874,7 +1876,7 @@ struct COMMAND_RPC_FLUSH_TRANSACTION_POOL { std::list txids; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(txids) END_KV_SERIALIZE_MAP() }; @@ -1883,7 +1885,7 @@ struct COMMAND_RPC_FLUSH_TRANSACTION_POOL { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -1899,7 +1901,7 @@ struct COMMAND_RPC_GET_OUTPUT_HISTOGRAM bool unlocked; uint64_t recent_cutoff; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(amounts); KV_SERIALIZE(min_count); KV_SERIALIZE(max_count); @@ -1915,7 +1917,7 @@ struct COMMAND_RPC_GET_OUTPUT_HISTOGRAM uint64_t unlocked_instances; uint64_t recent_instances; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(entry) KV_SERIALIZE(amount); KV_SERIALIZE(total_instances); KV_SERIALIZE(unlocked_instances); @@ -1923,7 +1925,6 @@ struct COMMAND_RPC_GET_OUTPUT_HISTOGRAM END_KV_SERIALIZE_MAP() entry(uint64_t amount, uint64_t total_instances, uint64_t unlocked_instances, uint64_t recent_instances) : amount(amount), total_instances(total_instances), unlocked_instances(unlocked_instances), recent_instances(recent_instances) {} - entry() {} }; struct response @@ -1932,7 +1933,7 @@ struct COMMAND_RPC_GET_OUTPUT_HISTOGRAM std::vector histogram; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(histogram) KV_SERIALIZE(untrusted) @@ -1944,7 +1945,7 @@ struct COMMAND_RPC_GET_VERSION { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; @@ -1954,7 +1955,7 @@ struct COMMAND_RPC_GET_VERSION uint32_t version; bool untrusted; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(version) KV_SERIALIZE(untrusted) @@ -1969,7 +1970,7 @@ struct COMMAND_RPC_GET_COINBASE_TX_SUM uint64_t height; uint64_t count; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(height); KV_SERIALIZE(count); END_KV_SERIALIZE_MAP() @@ -1981,7 +1982,7 @@ struct COMMAND_RPC_GET_COINBASE_TX_SUM uint64_t emission_amount; uint64_t fee_amount; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(emission_amount) KV_SERIALIZE(fee_amount) @@ -1993,18 +1994,20 @@ struct COMMAND_RPC_GET_ALTERNATE_CHAINS { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; struct chain_info { + chain_info(std::string block_hash, const uint64_t height, const uint64_t length, const uint64_t difficulty) : block_hash(block_hash), height(height), length(length), difficulty(difficulty) {} + std::string block_hash; uint64_t height; uint64_t length; uint64_t difficulty; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(chain_info) KV_SERIALIZE(block_hash) KV_SERIALIZE(height) KV_SERIALIZE(length) @@ -2017,7 +2020,7 @@ struct COMMAND_RPC_GET_ALTERNATE_CHAINS std::string status; std::list chains; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(chains) END_KV_SERIALIZE_MAP() @@ -2031,7 +2034,7 @@ struct COMMAND_RPC_UPDATE std::string command; std::string path; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(command); KV_SERIALIZE(path); END_KV_SERIALIZE_MAP() @@ -2047,7 +2050,7 @@ struct COMMAND_RPC_UPDATE std::string hash; std::string path; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(update) KV_SERIALIZE(version) @@ -2065,7 +2068,7 @@ struct COMMAND_RPC_RELAY_TX { std::list txids; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(txids) END_KV_SERIALIZE_MAP() }; @@ -2074,7 +2077,7 @@ struct COMMAND_RPC_RELAY_TX { std::string status; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) END_KV_SERIALIZE_MAP() }; @@ -2084,21 +2087,26 @@ struct COMMAND_RPC_SYNC_INFO { struct request { - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) END_KV_SERIALIZE_MAP() }; struct peer { + peer(connection_info info) : info(info) {} + connection_info info; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(peer) KV_SERIALIZE(info) END_KV_SERIALIZE_MAP() }; struct span { + span(uint64_t start_block_height, uint64_t nblocks, std::string connection_id, uint32_t rate, uint32_t speed, uint64_t size, std::string remote_address) : + start_block_height(start_block_height), nblocks(nblocks), connection_id(connection_id), rate(rate), speed(speed), size(size), remote_address(remote_address) {} + uint64_t start_block_height; uint64_t nblocks; std::string connection_id; @@ -2107,7 +2115,7 @@ struct COMMAND_RPC_SYNC_INFO uint64_t size; std::string remote_address; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(span) KV_SERIALIZE(start_block_height) KV_SERIALIZE(nblocks) KV_SERIALIZE(connection_id) @@ -2126,7 +2134,7 @@ struct COMMAND_RPC_SYNC_INFO std::list peers; std::list spans; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(height) KV_SERIALIZE(target_height) @@ -2145,7 +2153,7 @@ struct COMMAND_RPC_GET_OUTPUT_DISTRIBUTION uint64_t to_height; bool cumulative; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(request) KV_SERIALIZE(amounts) KV_SERIALIZE_OPT(from_height, (uint64_t)0) KV_SERIALIZE_OPT(to_height, (uint64_t)0) @@ -2153,14 +2161,16 @@ struct COMMAND_RPC_GET_OUTPUT_DISTRIBUTION END_KV_SERIALIZE_MAP() }; - struct distribution + struct distribution_data { + distribution_data(uint64_t amount, uint64_t start_height, std::vector distribution, uint64_t base) : + amount(amount), start_height(start_height), distribution(distribution), base(base) {} uint64_t amount; uint64_t start_height; std::vector distribution; uint64_t base; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(distribution_data) KV_SERIALIZE(amount) KV_SERIALIZE(start_height) KV_SERIALIZE_CONTAINER_POD_AS_BLOB(distribution) @@ -2171,9 +2181,9 @@ struct COMMAND_RPC_GET_OUTPUT_DISTRIBUTION struct response { std::string status; - std::vector distributions; + std::vector distributions; - BEGIN_KV_SERIALIZE_MAP() + BEGIN_KV_SERIALIZE_MAP(response) KV_SERIALIZE(status) KV_SERIALIZE(distributions) END_KV_SERIALIZE_MAP() diff --git a/src/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h index 332812ed..229a3f47 100644 --- a/src/rpc/core_rpc_server_error_codes.h +++ b/src/rpc/core_rpc_server_error_codes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index 9d0ad443..51b6ccd5 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -17,6 +17,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "daemon_handler.h" +#include "common/gulps.hpp" // likely included by daemon_handler.h's includes, // but including here for clarity @@ -30,7 +31,7 @@ namespace cryptonote namespace rpc { - +GULPS_CAT_MAJOR("rpc_args"); void DaemonHandler::handle(const GetHeight::Request &req, GetHeight::Response &res) { res.height = m_core.get_current_blockchain_height(); @@ -318,11 +319,11 @@ void DaemonHandler::handle(const SendRawTx::Request &req, SendRawTx::Response &r { if(tvc.m_verifivation_failed) { - LOG_PRINT_L0("[on_send_raw_tx]: tx verification failed"); + GULPS_PRINT("[on_send_raw_tx]: tx verification failed"); } else { - LOG_PRINT_L0("[on_send_raw_tx]: Failed to process tx"); + GULPS_PRINT("[on_send_raw_tx]: Failed to process tx"); } res.status = Message::STATUS_FAILED; res.error_details = ""; @@ -383,7 +384,7 @@ void DaemonHandler::handle(const SendRawTx::Request &req, SendRawTx::Response &r if(!tvc.m_should_be_relayed || !req.relay) { - LOG_PRINT_L0("[on_send_raw_tx]: tx accepted, but not relayed"); + GULPS_PRINT("[on_send_raw_tx]: tx accepted, but not relayed"); res.error_details = "Not relayed"; res.relayed = false; res.status = Message::STATUS_OK; @@ -408,14 +409,14 @@ void DaemonHandler::handle(const StartMining::Request &req, StartMining::Respons if(!get_account_address_from_str(m_core.get_nettype(), info, req.miner_address)) { res.error_details = "Failed, wrong address"; - LOG_PRINT_L0(res.error_details); + GULPS_PRINT(res.error_details); res.status = Message::STATUS_FAILED; return; } if(info.is_subaddress) { res.error_details = "Failed, mining to subaddress isn't supported yet"; - LOG_PRINT_L0(res.error_details); + GULPS_PRINT(res.error_details); res.status = Message::STATUS_FAILED; return; } @@ -433,7 +434,7 @@ void DaemonHandler::handle(const StartMining::Request &req, StartMining::Respons if(req.threads_count > concurrency_count) { res.error_details = "Failed, too many threads relative to CPU cores."; - LOG_PRINT_L0(res.error_details); + GULPS_PRINT(res.error_details); res.status = Message::STATUS_FAILED; return; } @@ -444,7 +445,7 @@ void DaemonHandler::handle(const StartMining::Request &req, StartMining::Respons if(!m_core.get_miner().start(info.address, static_cast(req.threads_count), attrs, req.do_background_mining, req.ignore_battery)) { res.error_details = "Failed, mining not started"; - LOG_PRINT_L0(res.error_details); + GULPS_PRINT(res.error_details); res.status = Message::STATUS_FAILED; return; } @@ -499,7 +500,7 @@ void DaemonHandler::handle(const StopMining::Request &req, StopMining::Response if(!m_core.get_miner().stop()) { res.error_details = "Failed, mining not stopped"; - LOG_PRINT_L0(res.error_details); + GULPS_PRINT(res.error_details); res.status = Message::STATUS_FAILED; return; } @@ -653,7 +654,6 @@ void DaemonHandler::handle(const SetLogLevel::Request &req, SetLogLevel::Respons else { res.status = Message::STATUS_OK; - mlog_set_log_level(req.level); } } @@ -816,7 +816,7 @@ bool DaemonHandler::getBlockHeaderByHash(const crypto::hash &hash_in, cryptonote std::string DaemonHandler::handle(const std::string &request) { - MDEBUG("Handling RPC request: " << request); + GULPSF_LOG_L1("Handling RPC request: {}", request); Message *resp_message = NULL; @@ -867,7 +867,7 @@ std::string DaemonHandler::handle(const std::string &request) delete resp_message; resp_message = NULL; - MDEBUG("Returning RPC response: " << response); + GULPSF_LOG_L1("Returning RPC response: {}", response); return response; } diff --git a/src/rpc/daemon_handler.h b/src/rpc/daemon_handler.h index a4c7583c..319f1c77 100644 --- a/src/rpc/daemon_handler.h +++ b/src/rpc/daemon_handler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index efd0cb19..54b31bdc 100644 --- a/src/rpc/daemon_messages.cpp +++ b/src/rpc/daemon_messages.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index 750d324c..543fd661 100644 --- a/src/rpc/daemon_messages.h +++ b/src/rpc/daemon_messages.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/daemon_rpc_version.h b/src/rpc/daemon_rpc_version.h index 99512bba..714d10d2 100644 --- a/src/rpc/daemon_rpc_version.h +++ b/src/rpc/daemon_rpc_version.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/instanciations.cpp b/src/rpc/instanciations.cpp index d7ea7131..e9289587 100644 --- a/src/rpc/instanciations.cpp +++ b/src/rpc/instanciations.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/message.cpp b/src/rpc/message.cpp index 44e2ecf0..ec3bf73d 100644 --- a/src/rpc/message.cpp +++ b/src/rpc/message.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/message.h b/src/rpc/message.h index 34961ace..644060e1 100644 --- a/src/rpc/message.h +++ b/src/rpc/message.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index 1cdbec06..2fece7c8 100644 --- a/src/rpc/message_data_structs.h +++ b/src/rpc/message_data_structs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index eae73cce..cd7c8479 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,6 +16,7 @@ // 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 "rpc_args.h" #include "common/command_line.h" @@ -24,8 +25,11 @@ #include #include +#include "common/gulps.hpp" + namespace cryptonote { +GULPS_CAT_MAJOR("rpc_args"); rpc_args::descriptors::descriptors() : rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"}), rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true}), confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")}), rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""}) { @@ -55,14 +59,14 @@ boost::optional rpc_args::process(const boost::program_options::variab const auto parsed_ip = boost::asio::ip::address::from_string(config.bind_ip, ec); if(ec) { - LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_bind_ip.name); + GULPS_ERROR(tr("Invalid IP address given for --"), arg.rpc_bind_ip.name); return boost::none; } if(!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg.confirm_external_bind)) { - LOG_ERROR( - "--" << arg.rpc_bind_ip.name << tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --") << arg.confirm_external_bind.name); + GULPS_ERROR( + "--", arg.rpc_bind_ip.name, tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --"), arg.confirm_external_bind.name); return boost::none; } } @@ -77,7 +81,7 @@ boost::optional rpc_args::process(const boost::program_options::variab if(config.login->username.empty()) { - LOG_ERROR(tr("Username specified with --") << arg.rpc_login.name << tr(" cannot be empty")); + GULPS_ERROR(tr("Username specified with --"), arg.rpc_login.name, tr(" cannot be empty")); return boost::none; } } @@ -87,7 +91,7 @@ boost::optional rpc_args::process(const boost::program_options::variab { if(!config.login) { - LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RFC server password --") << arg.rpc_login.name << tr(" cannot be empty")); + GULPS_ERROR(arg.rpc_access_control_origins.name, tr(" requires RFC server password --"), arg.rpc_login.name, tr(" cannot be empty")); return boost::none; } diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index ec0efa65..db5d188f 100644 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/rpc_handler.h b/src/rpc/rpc_handler.h index f73a7956..5e27a727 100644 --- a/src/rpc/rpc_handler.h +++ b/src/rpc/rpc_handler.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp index 3c67fab1..aa95ee1e 100644 --- a/src/rpc/zmq_server.cpp +++ b/src/rpc/zmq_server.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -16,9 +16,12 @@ // 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 "zmq_server.h" #include +#include "common/gulps.hpp" + namespace cryptonote { @@ -53,7 +56,7 @@ void ZmqServer::serve() { std::string message_string(reinterpret_cast(message.data()), message.size()); - MDEBUG(std::string("Received RPC request: \"") + message_string + "\""); + GULPS_LOG_L1(std::string("Received RPC request: \""), message_string, "\""); std::string response = handler.handle(message_string); @@ -61,16 +64,16 @@ void ZmqServer::serve() memcpy((void *)reply.data(), response.c_str(), response.size()); rep_socket->send(reply); - MDEBUG(std::string("Sent RPC reply: \"") + response + "\""); + GULPS_LOG_L1(std::string("Sent RPC reply: \""), response, "\""); } } catch(const boost::thread_interrupted &e) { - MDEBUG("ZMQ Server thread interrupted."); + GULPS_LOG_L1("ZMQ Server thread interrupted."); } catch(const zmq::error_t &e) { - MERROR(std::string("ZMQ error: ") + e.what()); + GULPS_ERROR(std::string("ZMQ error: "), e.what()); } boost::this_thread::interruption_point(); } @@ -78,7 +81,7 @@ void ZmqServer::serve() bool ZmqServer::addIPCSocket(std::string address, std::string port) { - MERROR("ZmqServer::addIPCSocket not yet implemented!"); + GULPS_ERROR("ZmqServer::addIPCSocket not yet implemented!"); return false; } @@ -97,7 +100,7 @@ bool ZmqServer::addTCPSocket(std::string address, std::string port) } catch(const std::exception &e) { - MERROR(std::string("Error creating ZMQ Socket: ") + e.what()); + GULPS_ERROR(std::string("Error creating ZMQ Socket: "), e.what()); return false; } return true; diff --git a/src/rpc/zmq_server.h b/src/rpc/zmq_server.h index f74f1a03..ca1ac0b9 100644 --- a/src/rpc/zmq_server.h +++ b/src/rpc/zmq_server.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -38,6 +38,7 @@ static constexpr int DEFAULT_RPC_RECV_TIMEOUT_MS = 1000; class ZmqServer { + GULPS_CAT_MAJOR("zmq_serv"); public: ZmqServer(RpcHandler &h); diff --git a/src/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index 626f6cc0..d5143077 100644 --- a/src/serialization/CMakeLists.txt +++ b/src/serialization/CMakeLists.txt @@ -29,7 +29,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 @@ -56,6 +56,8 @@ ryo_add_library(serialization ${serialization_headers} ${serialization_private_headers}) target_link_libraries(serialization + LINK_PUBLIC + fmt::fmt-header-only LINK_PRIVATE cryptonote_core cryptonote_protocol diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index ba10ac4d..4cb57ce4 100644 --- a/src/serialization/binary_archive.h +++ b/src/serialization/binary_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/binary_utils.h b/src/serialization/binary_utils.h index 219bca7f..88cef8ac 100644 --- a/src/serialization/binary_utils.h +++ b/src/serialization/binary_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/container.h b/src/serialization/container.h index 5f8db727..b22c71c7 100644 --- a/src/serialization/container.h +++ b/src/serialization/container.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/crypto.h b/src/serialization/crypto.h index 13586e2e..da021e54 100644 --- a/src/serialization/crypto.h +++ b/src/serialization/crypto.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/debug_archive.h b/src/serialization/debug_archive.h index 373239a6..8eb234f1 100644 --- a/src/serialization/debug_archive.h +++ b/src/serialization/debug_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/deque.h b/src/serialization/deque.h index 39afa93b..94932c9c 100644 --- a/src/serialization/deque.h +++ b/src/serialization/deque.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/json_archive.h b/src/serialization/json_archive.h index 0b303d42..af1c080b 100644 --- a/src/serialization/json_archive.h +++ b/src/serialization/json_archive.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 18f7a848..76087982 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/json_object.h b/src/serialization/json_object.h index 7e26e254..1d564c64 100644 --- a/src/serialization/json_object.h +++ b/src/serialization/json_object.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/json_utils.h b/src/serialization/json_utils.h index e3a5faf6..8648027f 100644 --- a/src/serialization/json_utils.h +++ b/src/serialization/json_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/list.h b/src/serialization/list.h index d988d348..1849524a 100644 --- a/src/serialization/list.h +++ b/src/serialization/list.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/pair.h b/src/serialization/pair.h index f71d04c0..0f90d871 100644 --- a/src/serialization/pair.h +++ b/src/serialization/pair.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h index d60ae929..d7f81c96 100644 --- a/src/serialization/serialization.h +++ b/src/serialization/serialization.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/set.h b/src/serialization/set.h index bae08cc0..4efcb41a 100644 --- a/src/serialization/set.h +++ b/src/serialization/set.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/string.h b/src/serialization/string.h index bf936697..8ea3b3fc 100644 --- a/src/serialization/string.h +++ b/src/serialization/string.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/unordered_set.h b/src/serialization/unordered_set.h index 37e5c412..41b39640 100644 --- a/src/serialization/unordered_set.h +++ b/src/serialization/unordered_set.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/variant.h b/src/serialization/variant.h index 30943df0..1bb113b9 100644 --- a/src/serialization/variant.h +++ b/src/serialization/variant.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/serialization/vector.h b/src/serialization/vector.h index 1cf95aa2..472e36c3 100644 --- a/src/serialization/vector.h +++ b/src/serialization/vector.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt index 890d969a..4b94e741 100644 --- a/src/simplewallet/CMakeLists.txt +++ b/src/simplewallet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2018, Ryo Currency Project +# Copyright (c) 2019, Ryo Currency Project # Portions copyright (c) 2014-2018, The Monero Project # # Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -30,7 +30,7 @@ # Authors and copyright holders agree that: # # 8. This licence expires and the work covered by it is released into the -# public domain on 1st of February 2019 +# public domain on 1st of February 2020 # # 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 diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f99bbd7f..7ff321e7 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018, Ryo Currency Project +// Copyright (c) 2019, Ryo Currency Project // Portions copyright (c) 2014-2018, The Monero Project // // Portions of this file are available under BSD-3 license. Please see ORIGINAL-LICENSE for details @@ -20,16 +20,16 @@ /*! * \file simplewallet.cpp - * + * * \brief Source file that defines simple_wallet class. */ + #include "simplewallet.h" #include "common/base58.h" #include "common/command_line.h" #include "common/dns_utils.h" #include "common/i18n.h" #include "common/json_util.h" -#include "common/scoped_message_writer.h" #include "common/util.h" #include "crypto/pow_hash/cn_slow_hash.hpp" #include "crypto/crypto.h" // for crypto::secret_key definition @@ -56,15 +56,25 @@ #include #include +#include "common/gulps.hpp" + #ifdef WIN32 +#undef fmt #include #include #include #endif -#ifdef HAVE_READLINE #include "readline_buffer.h" -#endif + +#define GULPS_PRINT_FAIL(...) do{PAUSE_READLINE();GULPS_ERROR(tr("Error: "), __VA_ARGS__);}while(false) +#define GULPS_PRINT_OK(...) do{PAUSE_READLINE();GULPS_PRINT(__VA_ARGS__);}while(false) +#define GULPSF_PRINT_OK(...) do{PAUSE_READLINE();GULPSF_PRINT(__VA_ARGS__);}while(false) +#define GULPS_PRINT_BOLD(...) do{PAUSE_READLINE();GULPS_PRINT_CLR(gulps::COLOR_BOLD_WHITE, __VA_ARGS__);}while(false) +#define GULPS_PRINT_GREEN(...) do{PAUSE_READLINE();GULPS_PRINT_CLR(gulps::COLOR_GREEN, __VA_ARGS__);}while(false) +#define GULPSF_PRINT_GREEN(...) do{PAUSE_READLINE();GULPSF_PRINT_CLR(gulps::COLOR_GREEN, __VA_ARGS__);}while(false) +#define GULPS_PRINT_SECRET(...) do{PAUSE_READLINE();GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, gulps_major_cat::c_str(), "secret", gulps::COLOR_WHITE, __VA_ARGS__);}while(false) + using namespace std; using namespace epee; @@ -73,8 +83,7 @@ using boost::lexical_cast; namespace po = boost::program_options; typedef cryptonote::simple_wallet sw; -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "wallet.simplewallet" +GULPS_CAT_MAJOR("wallet_cli"); #define EXTENDED_LOGS_FILE "wallet_details.log" @@ -103,6 +112,12 @@ enum TransferType TransferLocked, }; +namespace wallet_args +{ +// provided by wallet_args.cpp +extern gulps_log_level log_scr; +} + namespace { const std::array allowed_priority_strings = {{"default", "unimportant", "normal", "elevated", "priority"}}; @@ -130,10 +145,9 @@ const command_line::arg_descriptor> arg_command = {"com std::string input_line(const std::string &prompt) { -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif - std::cout << prompt; + PAUSE_READLINE(); + + GULPS_PRINT_NOLF(prompt); #ifdef WIN32 HANDLE hConIn = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); @@ -151,7 +165,7 @@ std::string input_line(const std::string &prompt) SetConsoleMode(hConIn, oldMode); CloseHandle(hConIn); - + int size_needed = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL); std::string buf(size_needed, '\0'); WideCharToMultiByte(CP_UTF8, 0, buffer, -1, &buf[0], size_needed, NULL, NULL); @@ -166,13 +180,11 @@ std::string input_line(const std::string &prompt) boost::optional password_prompter(const char *prompt, bool verify) { -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif + PAUSE_READLINE(); auto pwd_container = tools::password_container::prompt(verify, prompt); if(!pwd_container) { - tools::fail_msg_writer() << tr("failed to read wallet password"); + GULPS_PRINT_FAIL(tr("failed to read wallet password")); } return pwd_container; } @@ -203,21 +215,6 @@ inline std::string interpret_rpc_response(bool ok, const std::string &status) return err; } -tools::scoped_message_writer success_msg_writer(bool color = false) -{ - return tools::scoped_message_writer(color ? console_color_green : console_color_default, false, std::string(), el::Level::Info); -} - -tools::scoped_message_writer message_writer(epee::console_colors color = epee::console_color_default, bool bright = false) -{ - return tools::scoped_message_writer(color, bright); -} - -tools::scoped_message_writer fail_msg_writer() -{ - return tools::scoped_message_writer(console_color_red, true, sw::tr("Error: "), el::Level::Error); -} - bool parse_bool(const std::string &s, bool &result) { if(s == "1" || command_line::is_yes(s)) @@ -257,7 +254,7 @@ bool parse_bool_and_use(const std::string &s, F func) } else { - fail_msg_writer() << tr("invalid argument: must be either 0/1, true/false, y/n, yes/no"); + GULPS_PRINT_FAIL(tr("invalid argument: must be either 0/1, true/false, y/n, yes/no")); return false; } } @@ -267,10 +264,8 @@ const struct const char *name; tools::wallet2::RefreshType refresh_type; } refresh_type_names[] = - { +{ {"full", tools::wallet2::RefreshFull}, - {"optimize-coinbase", tools::wallet2::RefreshOptimizeCoinbase}, - {"optimized-coinbase", tools::wallet2::RefreshOptimizeCoinbase}, {"no-coinbase", tools::wallet2::RefreshNoCoinbase}, {"default", tools::wallet2::RefreshDefault}, }; @@ -285,7 +280,7 @@ bool parse_refresh_type(const std::string &s, tools::wallet2::RefreshType &refre return true; } } - fail_msg_writer() << cryptonote::simple_wallet::tr("failed to parse refresh type"); + GULPS_PRINT_FAIL(tr("failed to parse refresh type")); return false; } @@ -319,7 +314,7 @@ bool parse_subaddress_indices(const std::string &arg, std::set &subadd uint32_t subaddr_index; if(!epee::string_tools::get_xtype_from_string(subaddr_index, subaddr_index_str)) { - fail_msg_writer() << tr("failed to parse index: ") << subaddr_index_str; + GULPS_PRINT_FAIL(tr("failed to parse index: "), subaddr_index_str); subaddr_indices.clear(); return false; } @@ -342,7 +337,7 @@ boost::optional> parse_subaddress_lookahead(const } else { - fail_msg_writer() << tr("invalid format for subaddress lookahead; must be :"); + GULPS_PRINT_FAIL(tr("invalid format for subaddress lookahead; must be :")); return {}; } } @@ -356,50 +351,48 @@ void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon) } catch(const tools::error::daemon_busy &) { - fail_msg_writer() << tr("daemon is busy. Please try again later."); + GULPS_PRINT_FAIL(tr("daemon is busy. Please try again later.")); } catch(const tools::error::no_connection_to_daemon &) { - fail_msg_writer() << tr("no connection to daemon. Please make sure daemon is running."); + GULPS_PRINT_FAIL(tr("no connection to daemon. Please make sure daemon is running.")); } catch(const tools::error::wallet_rpc_error &e) { - LOG_ERROR("RPC error: " << e.to_string()); - fail_msg_writer() << tr("RPC error: ") << e.what(); + GULPS_LOG_ERROR("RPC error: ", e.to_string()); + GULPS_ERROR(tr("RPC error: "), e.what()); } catch(const tools::error::get_random_outs_error &e) { - fail_msg_writer() << tr("failed to get random outputs to mix: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to get random outputs to mix: "), e.what()); } catch(const tools::error::not_enough_unlocked_money &e) { - LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % - print_money(e.available()) % - print_money(e.tx_amount())); - fail_msg_writer() << tr("Not enough money in unlocked balance"); + GULPSF_LOG_L0("not enough money to transfer, available only {}, sent amount {}", + print_money(e.available()), print_money(e.tx_amount())); + + GULPS_PRINT_FAIL(tr("Not enough money in unlocked balance")); warn_of_possible_attack = false; } catch(const tools::error::not_enough_money &e) { - LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, sent amount %s") % - print_money(e.available()) % - print_money(e.tx_amount())); - fail_msg_writer() << tr("Not enough money in unlocked balance"); + GULPSF_LOG_L0("not enough money to transfer, available only {}, sent amount {}", + print_money(e.available()), print_money(e.tx_amount())); + + GULPS_PRINT_FAIL(tr("Not enough money in unlocked balance")); warn_of_possible_attack = false; } catch(const tools::error::tx_not_possible &e) { - LOG_PRINT_L0(boost::format("not enough money to transfer, available only %s, transaction amount %s = %s + %s (fee)") % - print_money(e.available()) % - print_money(e.tx_amount() + e.fee()) % - print_money(e.tx_amount()) % - print_money(e.fee())); - fail_msg_writer() << tr("Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees"); + GULPSF_LOG_L0("not enough money to transfer, available only {}, transaction amount {} = {} + {} (fee)", + print_money(e.available()), print_money(e.tx_amount() + e.fee()), print_money(e.tx_amount()), print_money(e.fee())); + + GULPS_PRINT_FAIL(tr("Failed to find a way to create transactions. This is usually due to dust which is so small it cannot pay for itself in fees, or trying to send more money than the unlocked balance, or not leaving enough for fees")); warn_of_possible_attack = false; } catch(const tools::error::not_enough_outs_to_mix &e) { - auto writer = fail_msg_writer(); + std::stringstream writer; writer << tr("not enough outputs for specified ring size") << " = " << (e.mixin_count() + 1) << ":"; for(std::pair outs_for_amount : e.scanty_outs()) { @@ -407,58 +400,61 @@ void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon) << tr("output amount") << " = " << print_money(outs_for_amount.first) << ", " << tr("found outputs to use") << " = " << outs_for_amount.second; } writer << tr("Please use sweep_unmixable."); + GULPS_PRINT_FAIL(writer.str()); } catch(const tools::error::tx_not_constructed &) { - fail_msg_writer() << tr("transaction was not constructed"); + GULPS_PRINT_FAIL(tr("transaction was not constructed")); warn_of_possible_attack = false; } catch(const tools::error::tx_rejected &e) { - fail_msg_writer() << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status(); + GULPSF_ERROR(tr("Error: transaction {} was rejected by daemon with status: {}"), get_transaction_hash(e.tx()), e.status()); std::string reason = e.reason(); if(!reason.empty()) - fail_msg_writer() << tr("Reason: ") << reason; + GULPS_ERROR(tr("Reason: "), reason); } catch(const tools::error::tx_sum_overflow &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); warn_of_possible_attack = false; } catch(const tools::error::zero_destination &) { - fail_msg_writer() << tr("one of destinations is zero"); + GULPS_PRINT_FAIL(tr("one of destinations is zero")); warn_of_possible_attack = false; } catch(const tools::error::tx_too_big &e) { - fail_msg_writer() << tr("failed to find a suitable way to split transactions"); + GULPS_PRINT_FAIL(tr("failed to find a suitable way to split transactions")); warn_of_possible_attack = false; } catch(const tools::error::transfer_error &e) { - LOG_ERROR("unknown transfer error: " << e.to_string()); - fail_msg_writer() << tr("unknown transfer error: ") << e.what(); + GULPS_LOG_ERROR("unknown transfer error: ", e.to_string()); + GULPS_PRINT_FAIL(tr("unknown transfer error: "), e.what()); } catch(const tools::error::multisig_export_needed &e) { - LOG_ERROR("Multisig error: " << e.to_string()); - fail_msg_writer() << tr("Multisig error: ") << e.what(); + GULPS_LOG_ERROR("Multisig error: ", e.to_string()); + GULPS_PRINT_FAIL(tr("Multisig error: "), e.what()); warn_of_possible_attack = false; } catch(const tools::error::wallet_internal_error &e) { - LOG_ERROR("internal error: " << e.to_string()); - fail_msg_writer() << tr("internal error: ") << e.what(); + GULPS_LOG_ERROR("internal error: ", e.to_string()); + GULPS_PRINT_FAIL(tr("internal error: "), e.what()); } catch(const std::exception &e) { - LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << tr("unexpected error: ") << e.what(); + GULPS_LOG_ERROR("unexpected error: ", e.what()); + GULPS_PRINT_FAIL(tr("unexpected error: "), e.what()); } if(warn_of_possible_attack) - fail_msg_writer() << tr("There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a tranasction immediately. Alternatively, connect to another node so the original node cannot correlate information."); + GULPS_PRINT_FAIL(tr("There was an error, which could mean the node may be trying to get you to retry creating a transaction, and zero in on " + "which outputs you own. Or it could be a bona fide error. It may be prudent to disconnect from this node, and not try to send a tranasction " + "immediately. Alternatively, connect to another node so the original node cannot correlate information.")); } bool check_file_overwrite(const std::string &filename) @@ -468,10 +464,10 @@ bool check_file_overwrite(const std::string &filename) { if(boost::ends_with(filename, ".keys")) { - fail_msg_writer() << boost::format(tr("File %s likely stores wallet private keys! Use a different file name.")) % filename; + GULPSF_ERROR(tr("Error: File {} likely stores wallet private keys! Use a different file name."), filename); return false; } - return command_line::is_yes(input_line((boost::format(tr("File %s already exists. Are you sure to overwrite it? (Y/Yes/N/No): ")) % filename).str())); + return command_line::is_yes(input_line(fmt::format(tr("File {} already exists. Are you sure to overwrite it? (Y/Yes/N/No): "), filename))); } return true; } @@ -494,11 +490,11 @@ bool parse_priority(const std::string &arg, uint32_t &priority) std::string simple_wallet::get_commands_str() { std::stringstream ss; - ss << tr("Commands: ") << ENDL; + ss << tr("Commands: ") << "\n"; std::string usage = m_cmd_binder.get_usage(); boost::replace_all(usage, "\n", "\n "); usage.insert(0, " "); - ss << usage << ENDL; + ss << usage << "\n"; return ss.str(); } @@ -515,10 +511,10 @@ std::string simple_wallet::get_command_usage(const std::vector &arg std::string usage = documentation.second.empty() ? args.front() : documentation.first; std::string description = documentation.second.empty() ? documentation.first : documentation.second; usage.insert(0, " "); - ss << tr("Command usage: ") << ENDL << usage << ENDL << ENDL; + ss << tr("Command usage: ") << "\n" << usage << "\n" << "\n"; boost::replace_all(description, "\n", "\n "); description.insert(0, " "); - ss << tr("Command description: ") << ENDL << description << ENDL; + ss << tr("Command description: ") << "\n" << description << "\n"; } return ss.str(); } @@ -532,20 +528,19 @@ bool simple_wallet::viewkey(const std::vector &args /* = std::vecto if(m_wallet->get_account().is_kurz()) { - fail_msg_writer() << tr("This wallet is in kurz format and has no viewkey."); + GULPS_PRINT_FAIL(tr("This wallet is in kurz format and has no viewkey.")); return true; } - // don't log if(m_wallet->key_on_device()) { - std::cout << "secret: On device. Not available" << std::endl; + GULPS_PRINT_FAIL(tr("Key is on a device and is not available")); } else { - std::cout << "secret: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << std::endl; + GULPS_PRINT_SECRET("secret: ", string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key)); } - std::cout << "public: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key) << std::endl; + GULPS_PRINT_SECRET("public: ", string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_view_public_key)); return true; } @@ -554,23 +549,24 @@ bool simple_wallet::spendkey(const std::vector &args /* = std::vect { if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and has no spend key"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and has no spend key")); return true; } + if(m_wallet->ask_password() && !get_and_verify_password()) { return true; } - // don't log + if(m_wallet->key_on_device()) { - std::cout << "secret: On device. Not available" << std::endl; + GULPS_PRINT_FAIL(tr("Key is on a device and is not available")); } else { - std::cout << "secret: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key) << std::endl; + GULPS_PRINT_SECRET("secret: ", string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_spend_secret_key)); } - std::cout << "public: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_spend_public_key) << std::endl; + GULPS_PRINT_SECRET("public: ", string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_account_address.m_spend_public_key)); return true; } @@ -584,12 +580,12 @@ bool simple_wallet::print_seed() if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and has no seed"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and has no seed")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -602,13 +598,13 @@ bool simple_wallet::print_seed() { if(!ready) { - fail_msg_writer() << tr("wallet is multisig but not yet finalized"); + GULPS_PRINT_FAIL(tr("wallet is multisig but not yet finalized")); return true; } } else if(!has_seed) { - fail_msg_writer() << tr("wallet is non-deterministic and has no seed"); + GULPS_PRINT_FAIL(tr("wallet is non-deterministic and has no seed")); return true; } @@ -624,7 +620,7 @@ bool simple_wallet::print_seed() } else { - fail_msg_writer() << tr("Failed to retrieve seed"); + GULPS_PRINT_FAIL(tr("Failed to retrieve seed")); } return true; } @@ -638,22 +634,22 @@ bool simple_wallet::seed_set_language(const std::vector &args /* = { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(m_wallet->multisig()) { - fail_msg_writer() << tr("wallet is multisig and has no seed"); + GULPS_PRINT_FAIL(tr("wallet is multisig and has no seed")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and has no seed"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and has no seed")); return true; } if(!m_wallet->has_25word_seed() && !m_wallet->has_14word_seed()) { - fail_msg_writer() << tr("wallet is non-deterministic and has no seed"); + GULPS_PRINT_FAIL(tr("wallet is non-deterministic and has no seed")); return true; } @@ -676,7 +672,7 @@ bool simple_wallet::change_password(const std::vector &args) if(orig_pwd_container == boost::none) { - fail_msg_writer() << tr("Your original password was incorrect."); + GULPS_PRINT_FAIL(tr("Your original password was incorrect.")); return true; } @@ -692,7 +688,7 @@ bool simple_wallet::change_password(const std::vector &args) } catch(const tools::error::wallet_logic_error &e) { - fail_msg_writer() << tr("Error with wallet rewrite: ") << e.what(); + GULPS_PRINT_FAIL(tr("Error with wallet rewrite: "), e.what()); return true; } @@ -704,11 +700,11 @@ bool simple_wallet::payment_id(const std::vector &args /* = std::ve crypto::hash payment_id; if(args.size() > 0) { - fail_msg_writer() << tr("usage: payment_id"); + GULPS_PRINT_FAIL(tr("usage: payment_id")); return true; } payment_id = crypto::rand(); - success_msg_writer() << tr("Random payment ID: ") << payment_id; + GULPS_PRINT_OK(tr("Random payment ID: "), payment_id); return true; } @@ -716,15 +712,15 @@ bool simple_wallet::print_fee_info(const std::vector &args /* = std { if(!try_connect_to_daemon()) { - fail_msg_writer() << tr("Cannot connect to daemon"); + GULPS_PRINT_FAIL(tr("Cannot connect to daemon")); return true; } using namespace cryptonote; constexpr uint64_t typical_size_kb = 15; - message_writer() << (boost::format(tr("Current fee is %s %s per kB and %s %s per ring member.")) % - print_money(common_config::FEE_PER_KB) % get_unit(get_default_decimal_point()) % - print_money(common_config::FEE_PER_RING_MEMBER) % get_unit(get_default_decimal_point())); + GULPSF_PRINT_OK(tr("Current fee is {} {} per kB and {} {} per ring member."), + print_money(common_config::FEE_PER_KB) , get_unit(get_default_decimal_point()), + print_money(common_config::FEE_PER_RING_MEMBER), get_unit(get_default_decimal_point())); std::vector fees; for(uint32_t priority = 1; priority <= 4; ++priority) @@ -742,12 +738,12 @@ bool simple_wallet::print_fee_info(const std::vector &args /* = std } catch(const std::exception &e) { - fail_msg_writer() << tr("Error: failed to estimate backlog array size: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to estimate backlog array size: "), e.what()); return true; } if(blocks.size() != 4) { - fail_msg_writer() << tr("Error: bad estimated backlog array size"); + GULPS_PRINT_FAIL(tr("bad estimated backlog array size")); return true; } @@ -762,12 +758,12 @@ bool simple_wallet::print_fee_info(const std::vector &args /* = std msg = tr(" (current)"); uint64_t minutes_low = nblocks_low * common_config::DIFFICULTY_TARGET / 60, minutes_high = nblocks_high * common_config::DIFFICULTY_TARGET / 60; if(nblocks_high == nblocks_low) - message_writer() << (boost::format(tr("%u block (%u minutes) backlog at priority %u%s")) % nblocks_low % minutes_low % priority % msg).str(); + GULPSF_PRINT_OK(tr("{} block ({} minutes) backlog at priority {}{}"), nblocks_low, minutes_low, priority, msg); else - message_writer() << (boost::format(tr("%u to %u block (%u to %u minutes) backlog at priority %u")) % nblocks_low % nblocks_high % minutes_low % minutes_high % priority).str(); + GULPSF_PRINT_OK(tr("{} to {} block ({} to {} minutes) backlog at priority {}"), nblocks_low, nblocks_high, minutes_low, minutes_high, priority); } else - message_writer() << tr("No backlog at priority ") << priority; + GULPS_PRINT_OK(tr("No backlog at priority "), priority); } return true; } @@ -776,45 +772,45 @@ bool simple_wallet::prepare_multisig(const std::vector &args) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(m_wallet->is_kurz()) { - fail_msg_writer() << tr("Multisig wallets need a viewkey, therefore kurz wallets are not supported."); + GULPS_PRINT_FAIL(tr("Multisig wallets need a viewkey, therefore kurz wallets are not supported.")); return true; } if(m_wallet->multisig()) { - fail_msg_writer() << tr("This wallet is already multisig"); + GULPS_PRINT_FAIL(tr("This wallet is already multisig")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and cannot be made multisig"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and cannot be made multisig")); return true; } if(m_wallet->get_num_transfer_details()) { - fail_msg_writer() << tr("This wallet has been used before, please use a new wallet to create a multisig wallet"); + GULPS_PRINT_FAIL(tr("This wallet has been used before, please use a new wallet to create a multisig wallet")); return true; } const auto orig_pwd_container = get_and_verify_password(); if(orig_pwd_container == boost::none) { - fail_msg_writer() << tr("Your password is incorrect."); + GULPS_PRINT_FAIL(tr("Your password is incorrect.")); return true; } std::string multisig_info = m_wallet->get_multisig_info(); - success_msg_writer() << multisig_info; - success_msg_writer() << tr("Send this multisig info to all other participants, then use make_multisig [...] with others' multisig info"); - success_msg_writer() << tr("This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants "); + GULPS_PRINT_OK(multisig_info); + GULPS_PRINT_OK(tr("Send this multisig info to all other participants, then use make_multisig [...] with others' multisig info")); + GULPS_PRINT_OK(tr("This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants ")); return true; } @@ -822,44 +818,44 @@ bool simple_wallet::make_multisig(const std::vector &args) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(m_wallet->is_kurz()) { - fail_msg_writer() << tr("Multisig wallets need a viewkey, therefore kurz wallets are not supported."); + GULPS_PRINT_FAIL(tr("Multisig wallets need a viewkey, therefore kurz wallets are not supported.")); return true; } if(m_wallet->multisig()) { - fail_msg_writer() << tr("This wallet is already multisig"); + GULPS_PRINT_FAIL(tr("This wallet is already multisig")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and cannot be made multisig"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and cannot be made multisig")); return true; } if(m_wallet->get_num_transfer_details()) { - fail_msg_writer() << tr("This wallet has been used before, please use a new wallet to create a multisig wallet"); + GULPS_PRINT_FAIL(tr("This wallet has been used before, please use a new wallet to create a multisig wallet")); return true; } const auto orig_pwd_container = get_and_verify_password(); if(orig_pwd_container == boost::none) { - fail_msg_writer() << tr("Your original password was incorrect."); + GULPS_PRINT_FAIL(tr("Your original password was incorrect.")); return true; } if(args.size() < 2) { - fail_msg_writer() << tr("usage: make_multisig [...]"); + GULPS_PRINT_FAIL(tr("usage: make_multisig [...]")); return true; } @@ -867,7 +863,7 @@ bool simple_wallet::make_multisig(const std::vector &args) uint32_t threshold; if(!string_tools::get_xtype_from_string(threshold, args[0])) { - fail_msg_writer() << tr("Invalid threshold"); + GULPS_PRINT_FAIL(tr("Invalid threshold")); return true; } @@ -880,26 +876,25 @@ bool simple_wallet::make_multisig(const std::vector &args) std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold); if(!multisig_extra_info.empty()) { - success_msg_writer() << tr("Another step is needed"); - success_msg_writer() << multisig_extra_info; - success_msg_writer() << tr("Send this multisig info to all other participants, then use finalize_multisig [...] with others' multisig info"); + GULPS_PRINT_OK(tr("Another step is needed")); + GULPS_PRINT_OK(multisig_extra_info); + GULPS_PRINT_OK(tr("Send this multisig info to all other participants, then use finalize_multisig [...] with others' multisig info")); return true; } } catch(const std::exception &e) { - fail_msg_writer() << tr("Error creating multisig: ") << e.what(); + GULPS_PRINT_FAIL(tr("Error creating multisig: "), e.what()); return true; } uint32_t total; if(!m_wallet->multisig(NULL, &threshold, &total)) { - fail_msg_writer() << tr("Error creating multisig: new wallet is not multisig"); + GULPS_PRINT_FAIL(tr("Error creating multisig: new wallet is not multisig")); return true; } - success_msg_writer() << std::to_string(threshold) << "/" << total << tr(" multisig address: ") - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + GULPS_PRINT_OK(std::to_string(threshold), "/", std::to_string(total), tr(" multisig address: "), m_wallet->get_account().get_public_address_str(m_wallet->nettype())); return true; } @@ -909,30 +904,30 @@ bool simple_wallet::finalize_multisig(const std::vector &args) bool ready; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready)) { - fail_msg_writer() << tr("This wallet is not multisig"); + GULPS_PRINT_FAIL(tr("This wallet is not multisig")); return true; } if(ready) { - fail_msg_writer() << tr("This wallet is already finalized"); + GULPS_PRINT_FAIL(tr("This wallet is already finalized")); return true; } const auto orig_pwd_container = get_and_verify_password(); if(orig_pwd_container == boost::none) { - fail_msg_writer() << tr("Your original password was incorrect."); + GULPS_PRINT_FAIL(tr("Your original password was incorrect.")); return true; } if(args.size() < 2) { - fail_msg_writer() << tr("usage: finalize_multisig [...]"); + GULPS_PRINT_FAIL(tr("usage: finalize_multisig [...]")); return true; } @@ -940,13 +935,13 @@ bool simple_wallet::finalize_multisig(const std::vector &args) { if(!m_wallet->finalize_multisig(orig_pwd_container->password(), args)) { - fail_msg_writer() << tr("Failed to finalize multisig"); + GULPS_PRINT_FAIL(tr("Failed to finalize multisig")); return true; } } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to finalize multisig: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to finalize multisig: "), e.what()); return true; } @@ -958,22 +953,22 @@ bool simple_wallet::export_multisig(const std::vector &args) bool ready; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready)) { - fail_msg_writer() << tr("This wallet is not multisig"); + GULPS_PRINT_FAIL(tr("This wallet is not multisig")); return true; } if(!ready) { - fail_msg_writer() << tr("This multisig wallet is not yet finalized"); + GULPS_PRINT_FAIL(tr("This multisig wallet is not yet finalized")); return true; } if(args.size() != 1) { - fail_msg_writer() << tr("usage: export_multisig_info "); + GULPS_PRINT_FAIL(tr("usage: export_multisig_info ")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -989,18 +984,18 @@ bool simple_wallet::export_multisig(const std::vector &args) bool r = epee::file_io_utils::save_string_to_file(filename, ciphertext); if(!r) { - fail_msg_writer() << tr("failed to save file ") << filename; + GULPS_PRINT_FAIL(tr("failed to save file "), filename); return true; } } catch(const std::exception &e) { - LOG_ERROR("Error exporting multisig info: " << e.what()); - fail_msg_writer() << tr("Error exporting multisig info: ") << e.what(); + GULPS_LOG_ERROR("Error exporting multisig info: ", e.what()); + GULPS_PRINT_FAIL(tr("Error exporting multisig info: "), e.what()); return true; } - success_msg_writer() << tr("Multisig info exported to ") << filename; + GULPS_PRINT_OK(tr("Multisig info exported to "), filename); return true; } @@ -1010,22 +1005,22 @@ bool simple_wallet::import_multisig(const std::vector &args) uint32_t threshold, total; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready, &threshold, &total)) { - fail_msg_writer() << tr("This wallet is not multisig"); + GULPS_PRINT_FAIL(tr("This wallet is not multisig")); return true; } if(!ready) { - fail_msg_writer() << tr("This multisig wallet is not yet finalized"); + GULPS_PRINT_FAIL(tr("This multisig wallet is not yet finalized")); return true; } if(args.size() < threshold - 1) { - fail_msg_writer() << tr("usage: import_multisig_info [...] - one for each other participant"); + GULPS_PRINT_FAIL(tr("usage: import_multisig_info [...] - one for each other participant")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -1039,7 +1034,7 @@ bool simple_wallet::import_multisig(const std::vector &args) bool r = epee::file_io_utils::load_file_to_string(filename, data); if(!r) { - fail_msg_writer() << tr("failed to read file ") << filename; + GULPS_PRINT_FAIL(tr("failed to read file "), filename); return true; } info.push_back(std::move(data)); @@ -1051,13 +1046,11 @@ bool simple_wallet::import_multisig(const std::vector &args) try { size_t n_outputs = m_wallet->import_multisig(info); - // Clear line "Height xxx of xxx" - std::cout << "\r \r"; - success_msg_writer() << tr("Multisig info imported"); + GULPS_PRINT_OK(tr("Multisig info imported")); } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to import multisig info: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to import multisig info: "), e.what()); return true; } if(m_trusted_daemon) @@ -1068,12 +1061,12 @@ bool simple_wallet::import_multisig(const std::vector &args) } catch(const std::exception &e) { - message_writer() << tr("Failed to update spent status after importing multisig info: ") << e.what(); + GULPS_PRINT_OK(tr("Failed to update spent status after importing multisig info: "), e.what()); } } else { - message_writer() << tr("Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run \"rescan_spent\""); + GULPS_PRINT_OK(tr("Untrusted daemon, spent status may be incorrect. Use a trusted daemon and run \"rescan_spent\"")); } return true; } @@ -1089,22 +1082,22 @@ bool simple_wallet::sign_multisig(const std::vector &args) bool ready; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready)) { - fail_msg_writer() << tr("This is not a multisig wallet"); + GULPS_PRINT_FAIL(tr("This is not a multisig wallet")); return true; } if(!ready) { - fail_msg_writer() << tr("This multisig wallet is not yet finalized"); + GULPS_PRINT_FAIL(tr("This multisig wallet is not yet finalized")); return true; } if(args.size() != 1) { - fail_msg_writer() << tr("usage: sign_multisig "); + GULPS_PRINT_FAIL(tr("usage: sign_multisig ")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -1120,18 +1113,18 @@ bool simple_wallet::sign_multisig(const std::vector &args) bool r = m_wallet->sign_multisig_tx_from_file(filename, txids, [&](const tools::wallet2::multisig_tx_set &tx) { signers = tx.m_signers.size(); return accept_loaded_tx(tx); }); if(!r) { - fail_msg_writer() << tr("Failed to sign multisig transaction"); + GULPS_PRINT_FAIL(tr("Failed to sign multisig transaction")); return true; } } catch(const tools::error::multisig_export_needed &e) { - fail_msg_writer() << tr("Multisig error: ") << e.what(); + GULPS_PRINT_FAIL(tr("Multisig error: "), e.what()); return true; } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to sign multisig transaction: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to sign multisig transaction: "), e.what()); return true; } @@ -1140,8 +1133,7 @@ bool simple_wallet::sign_multisig(const std::vector &args) uint32_t threshold; m_wallet->multisig(NULL, &threshold); uint32_t signers_needed = threshold - signers - 1; - success_msg_writer(true) << tr("Transaction successfully signed to file ") << filename << ", " - << signers_needed << " more signer(s) needed"; + GULPS_PRINT_GREEN(tr("Transaction successfully signed to file "), filename, ", ", signers_needed, " more signer(s) needed"); return true; } else @@ -1153,8 +1145,8 @@ bool simple_wallet::sign_multisig(const std::vector &args) txids_as_text += (", "); txids_as_text += epee::string_tools::pod_to_hex(txid); } - success_msg_writer(true) << tr("Transaction successfully signed to file ") << filename << ", txid " << txids_as_text; - success_msg_writer(true) << tr("It may be relayed to the network with submit_multisig"); + GULPS_PRINT_GREEN(tr("Transaction successfully signed to file "), filename, ", txid ", txids_as_text); + GULPS_PRINT_GREEN(tr("It may be relayed to the network with submit_multisig")); } return true; } @@ -1165,22 +1157,22 @@ bool simple_wallet::submit_multisig(const std::vector &args) uint32_t threshold; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready, &threshold)) { - fail_msg_writer() << tr("This is not a multisig wallet"); + GULPS_PRINT_FAIL(tr("This is not a multisig wallet")); return true; } if(!ready) { - fail_msg_writer() << tr("This multisig wallet is not yet finalized"); + GULPS_PRINT_FAIL(tr("This multisig wallet is not yet finalized")); return true; } if(args.size() != 1) { - fail_msg_writer() << tr("usage: submit_multisig "); + GULPS_PRINT_FAIL(tr("usage: submit_multisig ")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -1198,12 +1190,12 @@ bool simple_wallet::submit_multisig(const std::vector &args) bool r = m_wallet->load_multisig_tx_from_file(filename, txs, [&](const tools::wallet2::multisig_tx_set &tx) { return accept_loaded_tx(tx); }); if(!r) { - fail_msg_writer() << tr("Failed to load multisig transaction from file"); + GULPS_PRINT_FAIL(tr("Failed to load multisig transaction from file")); return true; } if(txs.m_signers.size() < threshold) { - fail_msg_writer() << (boost::format(tr("Multisig transaction signed by only %u signers, needs %u more signatures")) % txs.m_signers.size() % (threshold - txs.m_signers.size())).str(); + GULPSF_ERROR(tr("Error: Multisig transaction signed by only {} signers, needs {} more signatures"), txs.m_signers.size(), threshold - txs.m_signers.size()); return true; } @@ -1211,8 +1203,8 @@ bool simple_wallet::submit_multisig(const std::vector &args) for(auto &ptx : txs.m_ptx) { m_wallet->commit_tx(ptx); - success_msg_writer(true) << tr("Transaction successfully submitted, transaction ") << get_transaction_hash(ptx.tx) << ENDL - << tr("You can check its status by using the `show_transfers` command."); + GULPS_PRINT_GREEN(tr("Transaction successfully submitted, transaction "), get_transaction_hash(ptx.tx), "\n", + tr("You can check its status by using the `show_transfers` command.")); } } catch(const std::exception &e) @@ -1221,8 +1213,8 @@ bool simple_wallet::submit_multisig(const std::vector &args) } catch(...) { - LOG_ERROR("unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -1234,22 +1226,22 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) uint32_t threshold; if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!m_wallet->multisig(&ready, &threshold)) { - fail_msg_writer() << tr("This is not a multisig wallet"); + GULPS_PRINT_FAIL(tr("This is not a multisig wallet")); return true; } if(!ready) { - fail_msg_writer() << tr("This multisig wallet is not yet finalized"); + GULPS_PRINT_FAIL(tr("This multisig wallet is not yet finalized")); return true; } if(args.size() != 1) { - fail_msg_writer() << tr("usage: export_raw_multisig "); + GULPS_PRINT_FAIL(tr("usage: export_raw_multisig ")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -1266,12 +1258,12 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) bool r = m_wallet->load_multisig_tx_from_file(filename, txs, [&](const tools::wallet2::multisig_tx_set &tx) { return accept_loaded_tx(tx); }); if(!r) { - fail_msg_writer() << tr("Failed to load multisig transaction from file"); + GULPS_PRINT_FAIL(tr("Failed to load multisig transaction from file")); return true; } if(txs.m_signers.size() < threshold) { - fail_msg_writer() << (boost::format(tr("Multisig transaction signed by only %u signers, needs %u more signatures")) % txs.m_signers.size() % (threshold - txs.m_signers.size())).str(); + GULPSF_ERROR(tr("Error: Multisig transaction signed by only {} signers, needs {} more signatures"), txs.m_signers.size(), threshold - txs.m_signers.size()); return true; } @@ -1286,21 +1278,21 @@ bool simple_wallet::export_raw_multisig(const std::vector &args) filenames += filename; if(!epee::file_io_utils::save_string_to_file(filename, cryptonote::tx_to_blob(ptx.tx))) { - fail_msg_writer() << tr("Failed to export multisig transaction to file ") << filename; + GULPS_PRINT_FAIL(tr("Failed to export multisig transaction to file "), filename); return true; } } - success_msg_writer() << tr("Saved exported multisig transaction file(s): ") << filenames; + GULPS_PRINT_OK(tr("Saved exported multisig transaction file(s): "), filenames); } catch(const std::exception &e) { - LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << tr("unexpected error: ") << e.what(); + GULPS_LOG_ERROR("unexpected error: ", e.what()); + GULPS_PRINT_FAIL(tr("unexpected error: "), e.what()); } catch(...) { - LOG_ERROR("Unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("Unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -1312,19 +1304,19 @@ bool simple_wallet::print_ring(const std::vector &args) crypto::hash txid; if(args.size() != 1) { - fail_msg_writer() << tr("usage: print_ring "); + GULPS_PRINT_FAIL(tr("usage: print_ring ")); return true; } if(!epee::string_tools::hex_to_pod(args[0], key_image)) { - fail_msg_writer() << tr("Invalid key image"); + GULPS_PRINT_FAIL(tr("Invalid key image")); return true; } // this one will always work, they're all 32 byte hex if(!epee::string_tools::hex_to_pod(args[0], txid)) { - fail_msg_writer() << tr("Invalid txid"); + GULPS_PRINT_FAIL(tr("Invalid txid")); return true; } @@ -1336,7 +1328,7 @@ bool simple_wallet::print_ring(const std::vector &args) rings.push_back({key_image, ring}); else if(!m_wallet->get_rings(txid, rings)) { - fail_msg_writer() << tr("Key image either not spent, or spent with mixin 0"); + GULPS_PRINT_FAIL(tr("Key image either not spent, or spent with mixin 0")); return true; } @@ -1346,12 +1338,12 @@ bool simple_wallet::print_ring(const std::vector &args) for(const auto &x : ring.second) str << x << " "; // do NOT translate this "absolute" below, the lin can be used as input to set_ring - success_msg_writer() << epee::string_tools::pod_to_hex(ring.first) << " absolute " << str.str(); + GULPS_PRINT_OK(epee::string_tools::pod_to_hex(ring.first), " absolute ", str.str()); } } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to get key image ring: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to get key image ring: "), e.what()); } return true; @@ -1362,13 +1354,13 @@ bool simple_wallet::set_ring(const std::vector &args) crypto::key_image key_image; if(args.size() < 3) { - fail_msg_writer() << tr("usage: set_ring absolute|relative [...]"); + GULPS_PRINT_FAIL(tr("usage: set_ring absolute|relative [...]")); return true; } if(!epee::string_tools::hex_to_pod(args[0], key_image)) { - fail_msg_writer() << tr("Invalid key image"); + GULPS_PRINT_FAIL(tr("Invalid key image")); return true; } @@ -1383,7 +1375,7 @@ bool simple_wallet::set_ring(const std::vector &args) } else { - fail_msg_writer() << tr("Missing absolute or relative keyword"); + GULPS_PRINT_FAIL(tr("Missing absolute or relative keyword")); return true; } @@ -1393,14 +1385,14 @@ bool simple_wallet::set_ring(const std::vector &args) ring.resize(ring.size() + 1); if(!string_tools::get_xtype_from_string(ring.back(), args[n])) { - fail_msg_writer() << tr("invalid index: must be a strictly positive unsigned integer"); + GULPS_PRINT_FAIL(tr("invalid index: must be a strictly positive unsigned integer")); return true; } if(relative) { if(ring.size() > 1 && !ring.back()) { - fail_msg_writer() << tr("invalid index: must be a strictly positive unsigned integer"); + GULPS_PRINT_FAIL(tr("invalid index: must be a strictly positive unsigned integer")); return true; } uint64_t sum = 0; @@ -1408,7 +1400,7 @@ bool simple_wallet::set_ring(const std::vector &args) { if(out > std::numeric_limits::max() - sum) { - fail_msg_writer() << tr("invalid index: indices wrap"); + GULPS_PRINT_FAIL(tr("invalid index: indices wrap")); return true; } sum += out; @@ -1418,14 +1410,14 @@ bool simple_wallet::set_ring(const std::vector &args) { if(ring.size() > 1 && ring[ring.size() - 2] >= ring[ring.size() - 1]) { - fail_msg_writer() << tr("invalid index: indices should be in strictly ascending order"); + GULPS_PRINT_FAIL(tr("invalid index: indices should be in strictly ascending order")); return true; } } } if(!m_wallet->set_ring(key_image, ring, relative)) { - fail_msg_writer() << tr("failed to set ring"); + GULPS_PRINT_FAIL(tr("failed to set ring")); return true; } @@ -1437,7 +1429,7 @@ bool simple_wallet::blackball(const std::vector &args) crypto::public_key output; if(args.size() == 0) { - fail_msg_writer() << tr("usage: blackball | [add]"); + GULPS_PRINT_FAIL(tr("usage: blackball | [add]")); return true; } @@ -1467,7 +1459,7 @@ bool simple_wallet::blackball(const std::vector &args) outputs.push_back(crypto::public_key()); if(!epee::string_tools::hex_to_pod(str, outputs.back())) { - fail_msg_writer() << tr("Invalid public key: ") << str; + GULPS_PRINT_FAIL(tr("Invalid public key: "), str); return true; } } @@ -1477,7 +1469,7 @@ bool simple_wallet::blackball(const std::vector &args) { if(args[1] != "add") { - fail_msg_writer() << tr("Bad argument: ") + args[1] + ": " + tr("should be \"add\""); + GULPS_PRINT_FAIL(tr("Bad argument: ") + args[1] + ": " + tr("should be \"add\"")); return true; } add = true; @@ -1486,19 +1478,19 @@ bool simple_wallet::blackball(const std::vector &args) } else { - fail_msg_writer() << tr("Failed to open file"); + GULPS_PRINT_FAIL(tr("Failed to open file")); return true; } } else { - fail_msg_writer() << tr("Invalid public key, and file doesn't exist"); + GULPS_PRINT_FAIL(tr("Invalid public key, and file doesn't exist")); return true; } } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to blackball output: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to blackball output: "), e.what()); } return true; @@ -1509,13 +1501,13 @@ bool simple_wallet::unblackball(const std::vector &args) crypto::public_key output; if(args.size() != 1) { - fail_msg_writer() << tr("usage: unblackball "); + GULPS_PRINT_FAIL(tr("usage: unblackball ")); return true; } if(!epee::string_tools::hex_to_pod(args[0], output)) { - fail_msg_writer() << tr("Invalid public key"); + GULPS_PRINT_FAIL(tr("Invalid public key")); return true; } @@ -1525,7 +1517,7 @@ bool simple_wallet::unblackball(const std::vector &args) } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to unblackball output: "), e.what()); } return true; @@ -1536,26 +1528,26 @@ bool simple_wallet::blackballed(const std::vector &args) crypto::public_key output; if(args.size() != 1) { - fail_msg_writer() << tr("usage: blackballed "); + GULPS_PRINT_FAIL(tr("usage: blackballed ")); return true; } if(!epee::string_tools::hex_to_pod(args[0], output)) { - fail_msg_writer() << tr("Invalid public key"); + GULPS_PRINT_FAIL(tr("Invalid public key")); return true; } try { if(m_wallet->is_output_blackballed(output)) - message_writer() << tr("Blackballed: ") << output; + GULPS_PRINT_OK(tr("Blackballed: "), output); else - message_writer() << tr("not blackballed: ") << output; + GULPS_PRINT_OK(tr("not blackballed: "), output); } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to unblackball output: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to unblackball output: "), e.what()); } return true; @@ -1570,14 +1562,14 @@ bool simple_wallet::save_known_rings(const std::vector &args) } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to save known rings: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to save known rings: "), e.what()); } return true; } bool simple_wallet::version(const std::vector &args) { - message_writer() << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")"; + GULPS_PRINT_OK("Ryo '", RYO_RELEASE_NAME, "' (", RYO_VERSION_FULL, ")"); return true; } @@ -1611,7 +1603,7 @@ bool simple_wallet::set_store_tx_info(const std::vector &args /* = { if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and cannot transfer"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and cannot transfer")); return true; } @@ -1630,7 +1622,7 @@ bool simple_wallet::set_default_ring_size(const std::vector &args / { if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and cannot transfer"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and cannot transfer")); return true; } @@ -1638,18 +1630,18 @@ bool simple_wallet::set_default_ring_size(const std::vector &args / { if(strchr(args[1].c_str(), '-')) { - fail_msg_writer() << tr("ring size must be an integer >= ") << get_min_ring_size(); + GULPS_PRINT_FAIL(tr("ring size must be an integer >= "), get_min_ring_size()); return true; } uint32_t ring_size = boost::lexical_cast(args[1]); if(ring_size < get_min_ring_size() && ring_size != 0) { - fail_msg_writer() << tr("ring size must be an integer >= ") << get_min_ring_size(); + GULPS_PRINT_FAIL(tr("ring size must be an integer >= "), get_min_ring_size()); return true; } if(ring_size != 0 && ring_size != get_min_ring_size()) - message_writer() << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended."); + GULPS_PRINT_OK(tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended.")); const auto pwd_container = get_and_verify_password(); if(pwd_container) @@ -1661,12 +1653,12 @@ bool simple_wallet::set_default_ring_size(const std::vector &args / } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("ring size must be an integer >= ") << get_min_ring_size(); + GULPS_PRINT_FAIL(tr("ring size must be an integer >= "), get_min_ring_size()); return true; } catch(...) { - fail_msg_writer() << tr("could not change default ring size"); + GULPS_PRINT_FAIL(tr("could not change default ring size")); return true; } } @@ -1678,7 +1670,7 @@ bool simple_wallet::set_default_priority(const std::vector &args /* { if(strchr(args[1].c_str(), '-')) { - fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4 "); + GULPS_PRINT_FAIL(tr("priority must be 0, 1, 2, 3, or 4 ")); return true; } if(args[1] == "0") @@ -1690,7 +1682,7 @@ bool simple_wallet::set_default_priority(const std::vector &args /* priority = boost::lexical_cast(args[1]); if(priority < 1u || priority > 4u) { - fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4"); + GULPS_PRINT_FAIL(tr("priority must be 0, 1, 2, 3, or 4")); return true; } } @@ -1705,12 +1697,12 @@ bool simple_wallet::set_default_priority(const std::vector &args /* } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4"); + GULPS_PRINT_FAIL(tr("priority must be 0, 1, 2, 3, or 4")); return true; } catch(...) { - fail_msg_writer() << tr("could not change default priority"); + GULPS_PRINT_FAIL(tr("could not change default priority")); return true; } } @@ -1791,7 +1783,7 @@ bool simple_wallet::set_unit(const std::vector &args /* = std::vect decimal_point = 0; else { - fail_msg_writer() << tr("invalid unit"); + GULPS_PRINT_FAIL(tr("invalid unit")); return true; } @@ -1809,7 +1801,7 @@ bool simple_wallet::set_min_output_count(const std::vector &args /* uint32_t count; if(!string_tools::get_xtype_from_string(count, args[1])) { - fail_msg_writer() << tr("invalid count: must be an unsigned integer"); + GULPS_PRINT_FAIL(tr("invalid count: must be an unsigned integer")); return true; } @@ -1827,7 +1819,7 @@ bool simple_wallet::set_min_output_value(const std::vector &args /* uint64_t value; if(!cryptonote::parse_amount(value, args[1])) { - fail_msg_writer() << tr("invalid value"); + GULPS_PRINT_FAIL(tr("invalid value")); return true; } @@ -1871,7 +1863,7 @@ bool simple_wallet::set_confirm_backlog_threshold(const std::vector uint32_t threshold; if(!string_tools::get_xtype_from_string(threshold, args[1])) { - fail_msg_writer() << tr("invalid count: must be an unsigned integer"); + GULPS_PRINT_FAIL(tr("invalid count: must be an unsigned integer")); return true; } @@ -1905,7 +1897,7 @@ bool simple_wallet::set_refresh_from_block_height(const std::vector uint64_t height; if(!epee::string_tools::get_xtype_from_string(height, args[1])) { - fail_msg_writer() << tr("Invalid height"); + GULPS_PRINT_FAIL(tr("Invalid height")); return true; } m_wallet->set_refresh_from_block_height(height); @@ -1976,7 +1968,7 @@ bool simple_wallet::set_segregation_height(const std::vector &args uint64_t height; if(!epee::string_tools::get_xtype_from_string(height, args[1])) { - fail_msg_writer() << tr("Invalid height"); + GULPS_PRINT_FAIL(tr("Invalid height")); return true; } m_wallet->segregation_height(height); @@ -1989,11 +1981,11 @@ bool simple_wallet::help(const std::vector &args /* = std::vector\n " " Set the wallet's refresh behaviour.\n " "priority [0|1|2|3|4]\n " - " Set the fee too default/unimportant/normal/elevated/priority.\n " + " Set the fee to default/unimportant/normal/elevated/priority.\n " "confirm-missing-payment-id <1|0>\n " "ask-password <1|0>\n " "unit \n " @@ -2327,6 +2319,24 @@ simple_wallet::simple_wallet() tr("Show the help section or the documentation about a .")); } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::check_simple_variable(const std::vector &args, const char* name, wallet_cmd_fun fun, const char* help) +{ + if(args[0] == name) + { + if(args.size() <= 1) + { + GULPS_PRINT_FAIL("set ", name, ": ", tr("needs an argument") , " (", help, ")"); + return true; + } + else + { + (this->*fun)(args); + return true; + } + } + return false; +} + bool simple_wallet::set_variable(const std::vector &args) { if(args.empty()) @@ -2334,57 +2344,39 @@ bool simple_wallet::set_variable(const std::vector &args) std::string seed_language = m_wallet->get_seed_language(); if(m_use_english_language_names) seed_language = crypto::Electrum::get_english_name_for(seed_language); - success_msg_writer() << "seed = " << seed_language; - success_msg_writer() << "always-confirm-transfers = " << m_wallet->always_confirm_transfers(); - success_msg_writer() << "print-ring-members = " << m_wallet->print_ring_members(); - success_msg_writer() << "store-tx-info = " << m_wallet->store_tx_info(); - success_msg_writer() << "default-ring-size = " << (m_wallet->default_mixin() ? m_wallet->default_mixin() + 1 : 0); - success_msg_writer() << "auto-refresh = " << m_wallet->auto_refresh(); - success_msg_writer() << "refresh-type = " << get_refresh_type_name(m_wallet->get_refresh_type()); - success_msg_writer() << "priority = " << m_wallet->get_default_priority(); - success_msg_writer() << "confirm-missing-payment-id = " << m_wallet->confirm_missing_payment_id(); - success_msg_writer() << "ask-password = " << m_wallet->ask_password(); - success_msg_writer() << "unit = " << cryptonote::get_unit(cryptonote::get_default_decimal_point()); - success_msg_writer() << "min-outputs-count = " << m_wallet->get_min_output_count(); - success_msg_writer() << "min-outputs-value = " << cryptonote::print_money(m_wallet->get_min_output_value()); - success_msg_writer() << "merge-destinations = " << m_wallet->merge_destinations(); - success_msg_writer() << "confirm-backlog = " << m_wallet->confirm_backlog(); - success_msg_writer() << "confirm-backlog-threshold = " << m_wallet->get_confirm_backlog_threshold(); - success_msg_writer() << "confirm-export-overwrite = " << m_wallet->confirm_export_overwrite(); - success_msg_writer() << "refresh-from-block-height = " << m_wallet->get_refresh_from_block_height(); - success_msg_writer() << "auto-low-priority = " << m_wallet->auto_low_priority(); - success_msg_writer() << "segregate-pre-fork-outputs = " << m_wallet->segregate_pre_fork_outputs(); - success_msg_writer() << "key-reuse-mitigation2 = " << m_wallet->key_reuse_mitigation2(); + GULPS_PRINT_OK("seed = ", seed_language); + GULPS_PRINT_OK("always-confirm-transfers = ", m_wallet->always_confirm_transfers()); + GULPS_PRINT_OK("print-ring-members = ", m_wallet->print_ring_members()); + GULPS_PRINT_OK("store-tx-info = ", m_wallet->store_tx_info()); + GULPS_PRINT_OK("default-ring-size = ", (m_wallet->default_mixin() ? m_wallet->default_mixin() + 1 : 0)); + GULPS_PRINT_OK("auto-refresh = ", m_wallet->auto_refresh()); + GULPS_PRINT_OK("refresh-type = ", get_refresh_type_name(m_wallet->get_refresh_type())); + GULPS_PRINT_OK("priority = ", m_wallet->get_default_priority()); + GULPS_PRINT_OK("confirm-missing-payment-id = ", m_wallet->confirm_missing_payment_id()); + GULPS_PRINT_OK("ask-password = ", m_wallet->ask_password()); + GULPS_PRINT_OK("unit = ", cryptonote::get_unit(cryptonote::get_default_decimal_point())); + GULPS_PRINT_OK("min-outputs-count = ", m_wallet->get_min_output_count()); + GULPS_PRINT_OK("min-outputs-value = ", cryptonote::print_money(m_wallet->get_min_output_value())); + GULPS_PRINT_OK("merge-destinations = ", m_wallet->merge_destinations()); + GULPS_PRINT_OK("confirm-backlog = ", m_wallet->confirm_backlog()); + GULPS_PRINT_OK("confirm-backlog-threshold = ", m_wallet->get_confirm_backlog_threshold()); + GULPS_PRINT_OK("confirm-export-overwrite = ", m_wallet->confirm_export_overwrite()); + GULPS_PRINT_OK("refresh-from-block-height = ", m_wallet->get_refresh_from_block_height()); + GULPS_PRINT_OK("auto-low-priority = ", m_wallet->auto_low_priority()); + GULPS_PRINT_OK("segregate-pre-fork-outputs = ", m_wallet->segregate_pre_fork_outputs()); + GULPS_PRINT_OK("key-reuse-mitigation2 = ", m_wallet->key_reuse_mitigation2()); const std::pair lookahead = m_wallet->get_subaddress_lookahead(); - success_msg_writer() << "subaddress-lookahead = " << lookahead.first << ":" << lookahead.second; - success_msg_writer() << "segregation-height = " << m_wallet->segregation_height(); + GULPS_PRINT_OK("subaddress-lookahead = ", lookahead.first, ":", lookahead.second); + GULPS_PRINT_OK("segregation-height = ", m_wallet->segregation_height()); return true; } else { - -#define CHECK_SIMPLE_VARIABLE(name, f, help) \ - do \ - if(args[0] == name) \ - { \ - if(args.size() <= 1) \ - { \ - fail_msg_writer() << "set " << #name << ": " << tr("needs an argument") << " (" << help << ")"; \ - return true; \ - } \ - else \ - { \ - f(args); \ - return true; \ - } \ - } \ - while(0) - if(args[0] == "seed") { if(args.size() == 1) { - fail_msg_writer() << tr("set seed: needs an argument. available options: language"); + GULPS_PRINT_FAIL(tr("set seed: needs an argument. available options: language")); return true; } else if(args[1] == "language") @@ -2393,30 +2385,35 @@ bool simple_wallet::set_variable(const std::vector &args) return true; } } - CHECK_SIMPLE_VARIABLE("always-confirm-transfers", set_always_confirm_transfers, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("print-ring-members", set_print_ring_members, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("store-tx-info", set_store_tx_info, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("default-ring-size", set_default_ring_size, tr("integer >= ") << get_min_ring_size()); - CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)")); - CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4")); - CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", set_confirm_missing_payment_id, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("ryo, milliryo, microryo, nanoryo")); - CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer")); - CHECK_SIMPLE_VARIABLE("min-outputs-value", set_min_output_value, tr("amount")); - CHECK_SIMPLE_VARIABLE("merge-destinations", set_merge_destinations, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("confirm-backlog", set_confirm_backlog, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("confirm-backlog-threshold", set_confirm_backlog_threshold, tr("unsigned integer")); - CHECK_SIMPLE_VARIABLE("confirm-export-overwrite", set_confirm_export_overwrite, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("refresh-from-block-height", set_refresh_from_block_height, tr("block height")); - CHECK_SIMPLE_VARIABLE("auto-low-priority", set_auto_low_priority, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("segregate-pre-fork-outputs", set_segregate_pre_fork_outputs, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("key-reuse-mitigation2", set_key_reuse_mitigation2, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("subaddress-lookahead", set_subaddress_lookahead, tr(":")); - CHECK_SIMPLE_VARIABLE("segregation-height", set_segregation_height, tr("unsigned integer")); - } - fail_msg_writer() << tr("set: unrecognized argument(s)"); + + #define CHECK_SIMPLE_VARIABLE(name, f, help) if(check_simple_variable(args, name, f, help)) return true + + std::string rs = fmt::format(tr("integer >= {}"), get_min_ring_size()); + CHECK_SIMPLE_VARIABLE("always-confirm-transfers", &simple_wallet::set_always_confirm_transfers, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("print-ring-members", &simple_wallet::set_print_ring_members, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("store-tx-info", &simple_wallet::set_store_tx_info, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("default-ring-size", &simple_wallet::set_default_ring_size, rs.c_str()); + CHECK_SIMPLE_VARIABLE("auto-refresh", &simple_wallet::set_auto_refresh, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("refresh-type", &simple_wallet::set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)")); + CHECK_SIMPLE_VARIABLE("priority", &simple_wallet::set_default_priority, tr("0, 1, 2, 3, or 4")); + CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", &simple_wallet::set_confirm_missing_payment_id, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("ask-password", &simple_wallet::set_ask_password, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("unit", &simple_wallet::set_unit, tr("ryo, milliryo, microryo, nanoryo")); + CHECK_SIMPLE_VARIABLE("min-outputs-count", &simple_wallet::set_min_output_count, tr("unsigned integer")); + CHECK_SIMPLE_VARIABLE("min-outputs-value", &simple_wallet::set_min_output_value, tr("amount")); + CHECK_SIMPLE_VARIABLE("merge-destinations", &simple_wallet::set_merge_destinations, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("confirm-backlog", &simple_wallet::set_confirm_backlog, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("confirm-backlog-threshold", &simple_wallet::set_confirm_backlog_threshold, tr("unsigned integer")); + CHECK_SIMPLE_VARIABLE("confirm-export-overwrite", &simple_wallet::set_confirm_export_overwrite, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("refresh-from-block-height", &simple_wallet::set_refresh_from_block_height, tr("block height")); + CHECK_SIMPLE_VARIABLE("auto-low-priority", &simple_wallet::set_auto_low_priority, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("segregate-pre-fork-outputs", &simple_wallet::set_segregate_pre_fork_outputs, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("key-reuse-mitigation2", &simple_wallet::set_key_reuse_mitigation2, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("subaddress-lookahead", &simple_wallet::set_subaddress_lookahead, tr(":")); + CHECK_SIMPLE_VARIABLE("segregation-height", &simple_wallet::set_segregation_height, tr("unsigned integer")); + + } + GULPS_PRINT_FAIL(tr("set: unrecognized argument(s)")); return true; } @@ -2425,18 +2422,21 @@ bool simple_wallet::set_log(const std::vector &args) { if(args.size() > 1) { - fail_msg_writer() << tr("usage: set_log | "); + GULPS_PRINT_FAIL(tr("usage: set_log | ")); return true; } - if(!args.empty()) - mlog_set_log(args[0].c_str()); - success_msg_writer() << "New log categories: " << mlog_get_categories(); + + if(wallet_args::log_scr.parse_cat_string(args[0].c_str())) + GULPS_PRINT_OK("New log categories: ", args[0]); + else + GULPS_PRINT_FAIL(tr("Wrong log level or category.\nusage: set_log | ")); + return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::ask_wallet_create_if_needed() { - LOG_PRINT_L3("simple_wallet::ask_wallet_create_if_needed() started"); + GULPS_LOG_L1("simple_wallet::ask_wallet_create_if_needed() started"); std::string wallet_path; std::string confirm_creation; bool wallet_name_valid = false; @@ -2445,7 +2445,7 @@ bool simple_wallet::ask_wallet_create_if_needed() do { - LOG_PRINT_L3("User asked to specify wallet file name."); + GULPS_LOG_L1("User asked to specify wallet file name."); wallet_path = input_line( tr(m_restoring ? "Specify a new wallet file name for your restored wallet (e.g., MyWallet).\n" "Wallet file name (or Ctrl-C to quit): " @@ -2453,41 +2453,40 @@ bool simple_wallet::ask_wallet_create_if_needed() "Wallet file name (or Ctrl-C to quit): ")); if(std::cin.eof()) { - LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()"); + GULPS_LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()"); return false; } if(!tools::wallet2::wallet_valid_path_format(wallet_path)) { - fail_msg_writer() << tr("Wallet name not valid. Please try again or use Ctrl-C to quit."); + GULPS_PRINT_FAIL(tr("Wallet name not valid. Please try again or use Ctrl-C to quit.")); wallet_name_valid = false; } else { tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exists); - LOG_PRINT_L3("wallet_path: " << wallet_path << ""); - LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha - << " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha); + GULPS_LOG_L1("wallet_path: ", wallet_path); + GULPSF_LOG_L1("keys_file_exists: {} wallet_file_exists: {}", keys_file_exists, wallet_file_exists); if((keys_file_exists || wallet_file_exists) && (!m_generate_new.empty() || m_restoring)) { - fail_msg_writer() << tr("Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting."); + GULPS_PRINT_FAIL(tr("Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.")); return false; } if(wallet_file_exists && keys_file_exists) //Yes wallet, yes keys { - success_msg_writer() << tr("Wallet and key files found, loading..."); + GULPS_PRINT_OK(tr("Wallet and key files found, loading...")); m_wallet_file = wallet_path; return true; } else if(!wallet_file_exists && keys_file_exists) //No wallet, yes keys { - success_msg_writer() << tr("Key file found but not wallet file. Regenerating..."); + GULPS_PRINT_OK(tr("Key file found but not wallet file. Regenerating...")); m_wallet_file = wallet_path; return true; } else if(wallet_file_exists && !keys_file_exists) //Yes wallet, no keys { - fail_msg_writer() << tr("Key file not found. Failed to open wallet: ") << "\"" << wallet_path << "\". Exiting."; + GULPS_PRINT_FAIL(tr("Key file not found. Failed to open wallet: "), "\"", wallet_path, "\". Exiting."); return false; } else if(!wallet_file_exists && !keys_file_exists) //No wallet, no keys @@ -2495,18 +2494,18 @@ bool simple_wallet::ask_wallet_create_if_needed() bool ok = true; if(!m_restoring) { - message_writer() << tr("No wallet found with that name. Confirm creation of new wallet named: ") << wallet_path; + GULPS_PRINT_OK(tr("No wallet found with that name. Confirm creation of new wallet named: "), wallet_path); confirm_creation = input_line(tr("(Y/Yes/N/No): ")); if(std::cin.eof()) { - LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()"); + GULPS_LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()"); return false; } ok = command_line::is_yes(confirm_creation); } if(ok) { - success_msg_writer() << tr("Generating new wallet..."); + GULPS_PRINT_OK(tr("Generating new wallet...")); m_generate_new = wallet_path; return true; } @@ -2514,7 +2513,7 @@ bool simple_wallet::ask_wallet_create_if_needed() } } while(!wallet_name_valid); - LOG_ERROR("Failed out of do-while loop in ask_wallet_create_if_needed()"); + GULPS_LOG_ERROR("Failed out of do-while loop in ask_wallet_create_if_needed()"); return false; } @@ -2524,10 +2523,10 @@ bool simple_wallet::ask_wallet_create_if_needed() */ void simple_wallet::print_seed(std::string seed, bool short_seed) { - success_msg_writer(true) << "\n" - << tr("NOTE: the following ") << (short_seed ? 14 : 25) << tr(" words can be used to recover access to your wallet. " - "Write them down and store them somewhere safe and secure. Please do not store them in " - "your email or on file storage services outside of your immediate control.\n"); + GULPS_PRINT_GREEN("\n", tr("NOTE: the following "), short_seed ? "14" : "25", + tr(" words can be used to recover access to your wallet. " + "Write them down and store them somewhere safe and secure. Please do not store them in " + "your email or on file storage services outside of your immediate control.\n\n")); if(short_seed) { @@ -2540,7 +2539,7 @@ void simple_wallet::print_seed(std::string seed, bool short_seed) } // don't log - std::cout << seed << std::endl; + GULPS_PRINT_SECRET(seed); } //---------------------------------------------------------------------------------------------------- static bool might_be_partial_seed(std::string words) @@ -2559,7 +2558,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) const bool stagenet = tools::wallet2::has_stagenet_option(vm); if(testnet && stagenet) { - fail_msg_writer() << tr("Can't specify more than one of --testnet and --stagenet"); + GULPS_PRINT_FAIL(tr("Can't specify more than one of --testnet and --stagenet")); return false; } const network_type nettype = testnet ? TESTNET : stagenet ? STAGENET : MAINNET; @@ -2569,12 +2568,15 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) if(!handle_command_line(vm)) return false; - if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_device.empty()) + (!m_generate_from_view_key.empty()) + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1) + if((!m_generate_new.empty()) + (!m_wallet_file.empty()) + (!m_generate_from_device.empty()) + (!m_generate_from_view_key.empty()) + + (!m_generate_from_spend_key.empty()) + (!m_generate_from_keys.empty()) + (!m_generate_from_multisig_keys.empty()) + (!m_generate_from_json.empty()) > 1) { - fail_msg_writer() << tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", --generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-device=\"wallet_name\""); + GULPS_PRINT_FAIL(tr("can't specify more than one of --generate-new-wallet=\"wallet_name\", --wallet-file=\"wallet_name\", --generate-from-view-key=\"wallet_name\", " + "--generate-from-spend-key=\"wallet_name\", --generate-from-keys=\"wallet_name\", --generate-from-multisig-keys=\"wallet_name\", --generate-from-json=\"jsonfilename\" and --generate-from-device=\"wallet_name\"")); return false; } - else if(m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_device.empty() && m_generate_from_view_key.empty() && m_generate_from_spend_key.empty() && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty()) + else if(m_generate_new.empty() && m_wallet_file.empty() && m_generate_from_device.empty() && m_generate_from_view_key.empty() && m_generate_from_spend_key.empty() + && m_generate_from_keys.empty() && m_generate_from_multisig_keys.empty() && m_generate_from_json.empty()) { if(!ask_wallet_create_if_needed()) return false; @@ -2592,9 +2594,9 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) if(!m_wallet_file.empty()) { if(m_restore_multisig_wallet) - fail_msg_writer() << tr("--restore-multisig-wallet uses --generate-new-wallet, not --wallet-file"); + GULPS_PRINT_FAIL(tr("--restore-multisig-wallet uses --generate-new-wallet, not --wallet-file")); else - fail_msg_writer() << tr("--restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file"); + GULPS_PRINT_FAIL(tr("--restore-deterministic-wallet uses --generate-new-wallet, not --wallet-file")); return false; } @@ -2608,13 +2610,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(m_electrum_seed.empty()) { - fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"multisig seed here\""); + GULPS_PRINT_FAIL(tr("specify a recovery parameter with the --electrum-seed=\"multisig seed here\"")); return false; } if(!epee::string_tools::parse_hexstr_to_binbuff(m_electrum_seed, multisig_keys)) { - fail_msg_writer() << tr("Multisig seed failed verification"); + GULPS_PRINT_FAIL(tr("Multisig seed failed verification")); return false; } @@ -2633,7 +2635,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(line.empty()) { - fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"words list here\""); + GULPS_PRINT_FAIL(tr("specify a recovery parameter with the --electrum-seed=\"words list here\"")); return false; } m_electrum_seed += line; @@ -2651,18 +2653,18 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(address_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::address_parse_info info; if(!get_account_address_from_str(nettype, info, address_string)) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return false; } if(info.is_subaddress) { - fail_msg_writer() << tr("This address is a subaddress which cannot be used here."); + GULPS_PRINT_FAIL(tr("This address is a subaddress which cannot be used here.")); return false; } @@ -2672,13 +2674,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(viewkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::blobdata viewkey_data; if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key)) { - fail_msg_writer() << tr("failed to parse view key secret key"); + GULPS_PRINT_FAIL(tr("failed to parse view key secret key")); return false; } crypto::secret_key viewkey = *reinterpret_cast(viewkey_data.data()); @@ -2689,17 +2691,17 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) crypto::public_key pkey; if(!crypto::secret_key_to_public_key(viewkey, pkey)) { - fail_msg_writer() << tr("failed to verify view key secret key"); + GULPS_PRINT_FAIL(tr("failed to verify view key secret key")); return false; } if(info.address.m_view_public_key != pkey) { - fail_msg_writer() << tr("view key does not match standard address"); + GULPS_PRINT_FAIL(tr("view key does not match standard address")); return false; } bool r = new_wallet(vm, info.address, boost::none, viewkey); - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } else if(!m_generate_from_spend_key.empty()) { @@ -2710,18 +2712,18 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(spendkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } crypto::secret_key recovery_key; if(!epee::string_tools::hex_to_pod(spendkey_string, recovery_key)) { - fail_msg_writer() << tr("failed to parse spend key secret key"); + GULPS_PRINT_FAIL(tr("failed to parse spend key secret key")); return false; } bool r = restore_legacy_wallet(vm, get_mnemonic_language(false), recovery_key); - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } else if(!m_generate_from_keys.empty()) { @@ -2732,18 +2734,18 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(address_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::address_parse_info info; if(!get_account_address_from_str(nettype, info, address_string)) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return false; } if(info.is_subaddress) { - fail_msg_writer() << tr("This address is a subaddress which cannot be used here."); + GULPS_PRINT_FAIL(tr("This address is a subaddress which cannot be used here.")); return false; } @@ -2753,13 +2755,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(spendkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::blobdata spendkey_data; if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key)) { - fail_msg_writer() << tr("failed to parse spend key secret key"); + GULPS_PRINT_FAIL(tr("failed to parse spend key secret key")); return false; } crypto::secret_key spendkey = *reinterpret_cast(spendkey_data.data()); @@ -2770,13 +2772,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(viewkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::blobdata viewkey_data; if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key)) { - fail_msg_writer() << tr("failed to parse view key secret key"); + GULPS_PRINT_FAIL(tr("failed to parse view key secret key")); return false; } crypto::secret_key viewkey = *reinterpret_cast(viewkey_data.data()); @@ -2787,26 +2789,26 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) crypto::public_key pkey; if(!crypto::secret_key_to_public_key(spendkey, pkey)) { - fail_msg_writer() << tr("failed to verify spend key secret key"); + GULPS_PRINT_FAIL(tr("failed to verify spend key secret key")); return false; } if(info.address.m_spend_public_key != pkey) { - fail_msg_writer() << tr("spend key does not match standard address"); + GULPS_PRINT_FAIL(tr("spend key does not match standard address")); return false; } if(!crypto::secret_key_to_public_key(viewkey, pkey)) { - fail_msg_writer() << tr("failed to verify view key secret key"); + GULPS_PRINT_FAIL(tr("failed to verify view key secret key")); return false; } if(info.address.m_view_public_key != pkey) { - fail_msg_writer() << tr("view key does not match standard address"); + GULPS_PRINT_FAIL(tr("view key does not match standard address")); return false; } bool r = new_wallet(vm, info.address, spendkey, viewkey); - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } // Asks user for all the data required to merge secret keys from multisig wallets into one master wallet, which then gets full control of the multisig wallet. The resulting wallet will be the same as any other regular wallet. @@ -2822,25 +2824,25 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(multisig_type_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } if(sscanf(multisig_type_string.c_str(), "%u/%u", &multisig_m, &multisig_n) != 2) { - fail_msg_writer() << tr("Error: expected M/N, but got: ") << multisig_type_string; + GULPS_PRINT_FAIL(tr("Error: expected M/N, but got: "), multisig_type_string); return false; } if(multisig_m <= 1 || multisig_m > multisig_n) { - fail_msg_writer() << tr("Error: expected N > 1 and N <= M, but got: ") << multisig_type_string; + GULPS_PRINT_FAIL(tr("Error: expected N > 1 and N <= M, but got: "), multisig_type_string); return false; } if(multisig_m != multisig_n) { - fail_msg_writer() << tr("Error: M/N is currently unsupported. "); + GULPS_PRINT_FAIL(tr("Error: M/N is currently unsupported. ")); return false; } - message_writer() << boost::format(tr("Generating master wallet from %u of %u multisig wallet keys")) % multisig_m % multisig_n; + GULPSF_PRINT_OK(tr("Generating master wallet from {} of {} multisig wallet keys"), multisig_m, multisig_n); // parse multisig address std::string address_string = input_line("Multisig wallet address: "); @@ -2848,13 +2850,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(address_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::address_parse_info info; if(!get_account_address_from_str(nettype, info, address_string)) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return false; } @@ -2864,13 +2866,13 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) return false; if(viewkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } cryptonote::blobdata viewkey_data; if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key)) { - fail_msg_writer() << tr("failed to parse secret view key"); + GULPS_PRINT_FAIL(tr("failed to parse secret view key")); return false; } crypto::secret_key viewkey = *reinterpret_cast(viewkey_data.data()); @@ -2879,12 +2881,12 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) crypto::public_key pkey; if(!crypto::secret_key_to_public_key(viewkey, pkey)) { - fail_msg_writer() << tr("failed to verify secret view key"); + GULPS_PRINT_FAIL(tr("failed to verify secret view key")); return false; } if(info.address.m_view_public_key != pkey) { - fail_msg_writer() << tr("view key does not match standard address"); + GULPS_PRINT_FAIL(tr("view key does not match standard address")); return false; } @@ -2899,17 +2901,17 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) // get N secret spend keys from user for(unsigned int i = 0; i < multisig_n; ++i) { - spendkey_string = input_line(tr((boost::format(tr("Secret spend key (%u of %u):")) % (i + 1) % multisig_m).str().c_str())); + spendkey_string = input_line(fmt::format(tr("Secret spend key ({} of {}):"), i + 1, multisig_m)); if(std::cin.eof()) return false; if(spendkey_string.empty()) { - fail_msg_writer() << tr("No data supplied, cancelled"); + GULPS_PRINT_FAIL(tr("No data supplied, cancelled")); return false; } if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key)) { - fail_msg_writer() << tr("failed to parse spend key secret key"); + GULPS_PRINT_FAIL(tr("failed to parse spend key secret key")); return false; } multisig_secret_spendkeys[i] = *reinterpret_cast(spendkey_data.data()); @@ -2923,25 +2925,25 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) // parsing M/N else { - fail_msg_writer() << tr("Error: M/N is currently unsupported"); + GULPS_PRINT_FAIL(tr("Error: M/N is currently unsupported")); return false; } // check that the spend key matches the given address if(!crypto::secret_key_to_public_key(spendkey, pkey)) { - fail_msg_writer() << tr("failed to verify spend key secret key"); + GULPS_PRINT_FAIL(tr("failed to verify spend key secret key")); return false; } if(info.address.m_spend_public_key != pkey) { - fail_msg_writer() << tr("spend key does not match standard address"); + GULPS_PRINT_FAIL(tr("spend key does not match standard address")); return false; } // create wallet bool r = new_wallet(vm, info.address, spendkey, viewkey); - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } else if(!m_generate_from_json.empty()) @@ -2953,7 +2955,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); return false; } if(!m_wallet) @@ -2964,19 +2966,17 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) m_wallet_file = m_generate_from_device; // create wallet bool r = new_wallet_dev(vm, "Ledger"); - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); // if no block_height is specified, assume its a new account and start it "now" if(m_wallet->get_refresh_from_block_height() == 0) { - { - tools::scoped_message_writer wrt = tools::msg_writer(); - wrt << tr("No restore height is specified."); - wrt << tr("Assumed you are creating a new account, restore will be done from current estimated blockchain height."); - wrt << tr("Use --restore-height if you want to restore an already setup account from a specific height"); - } + GULPS_PRINT_OK(tr("No restore height is specified.")); + GULPS_PRINT_OK(tr("Assumed you are creating a new account, restore will be done from current estimated blockchain height.")); + GULPS_PRINT_OK(tr("Use --restore-height if you want to restore an already setup account from a specific height")); + std::string confirm = input_line(tr("Is this okay? (Y/Yes/N/No): ")); if(std::cin.eof() || !command_line::is_yes(confirm)) - CHECK_AND_ASSERT_MES(false, false, tr("account creation aborted")); + GULPS_CHECK_AND_ASSERT_MES(false, false, tr("account creation aborted")); m_wallet->set_refresh_from_block_height(m_wallet->estimate_blockchain_height() - 1); m_wallet->explicit_refresh_from_block_height(true); @@ -2987,7 +2987,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) { if(m_generate_new.empty()) { - fail_msg_writer() << tr("specify a wallet path with --generate-new-wallet (not --wallet-file)"); + GULPS_PRINT_FAIL(tr("specify a wallet path with --generate-new-wallet (not --wallet-file)")); return false; } m_wallet_file = m_generate_new; @@ -3004,7 +3004,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) else r = new_wallet_from_seed(vm, m_electrum_seed); } - CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } if(m_restoring && m_generate_from_json.empty() && m_generate_from_device.empty()) @@ -3038,12 +3038,12 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) { if(!connected || version < MAKE_CORE_RPC_VERSION(1, 6)) { - fail_msg_writer() << tr("bad m_restore_height parameter: ") << heightstr; + GULPS_PRINT_FAIL(tr("bad m_restore_height parameter: "), heightstr); continue; } if(heightstr.size() != 10 || heightstr[4] != '-' || heightstr[7] != '-') { - fail_msg_writer() << tr("date format must be YYYY-MM-DD"); + GULPS_PRINT_FAIL(tr("date format must be YYYY-MM-DD")); continue; } uint16_t year; @@ -3056,7 +3056,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) month = boost::lexical_cast(heightstr.substr(5, 2)); day = boost::lexical_cast(heightstr.substr(8, 2)); m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day); - success_msg_writer() << tr("Restore height is: ") << m_restore_height; + GULPS_PRINT_OK(tr("Restore height is: "), m_restore_height); std::string confirm = input_line(tr("Is this okay? (Y/Yes/N/No): ")); if(std::cin.eof()) return false; @@ -3065,11 +3065,11 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("bad m_restore_height parameter: ") << heightstr; + GULPS_PRINT_FAIL(tr("bad m_restore_height parameter: "), heightstr); } catch(const std::runtime_error &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } } } @@ -3079,7 +3079,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) uint64_t estimate_height = m_wallet->estimate_blockchain_height(); if(m_restore_height >= estimate_height) { - success_msg_writer() << tr("Restore height ") << m_restore_height << (" is not yet reached. The current estimated height is ") << estimate_height; + GULPS_PRINT_OK(tr("Restore height "), m_restore_height, (" is not yet reached. The current estimated height is "), estimate_height); std::string confirm = input_line(tr("Still apply restore height? (Y/Yes/N/No): ")); if(std::cin.eof() || command_line::is_no(confirm)) m_restore_height = 0; @@ -3092,15 +3092,15 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) assert(!m_wallet_file.empty()); if(!m_subaddress_lookahead.empty()) { - fail_msg_writer() << tr("can't specify --subaddress-lookahead and --wallet-file at the same time"); + GULPS_PRINT_FAIL(tr("can't specify --subaddress-lookahead and --wallet-file at the same time")); return false; } bool r = open_wallet(vm); - CHECK_AND_ASSERT_MES(r, false, tr("failed to open account")); + GULPS_CHECK_AND_ASSERT_MES(r, false, tr("failed to open account")); } if(!m_wallet) { - fail_msg_writer() << tr("wallet is null"); + GULPS_PRINT_FAIL(tr("wallet is null")); return false; } @@ -3109,7 +3109,7 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) { if(tools::is_local_address(m_wallet->get_daemon_address())) { - MINFO(tr("Daemon is local, assuming trusted")); + GULPS_INFO(tr("Daemon is local, assuming trusted")); m_trusted_daemon = true; } } @@ -3118,10 +3118,10 @@ bool simple_wallet::init(const boost::program_options::variables_map &vm) } if(!m_trusted_daemon) - message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str(); + GULPSF_PRINT_OK(tr("Warning: using an untrusted daemon at {}, privacy will be lessened"), m_wallet->get_daemon_address()); if(m_wallet->get_ring_database().empty()) - fail_msg_writer() << tr("Failed to initialize ring database: privacy enhancing features will be inactive"); + GULPS_PRINT_FAIL(tr("Failed to initialize ring database: privacy enhancing features will be inactive")); m_wallet->callback(this); @@ -3176,14 +3176,19 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t *version) if(!m_wallet->check_connection(version)) { if(!silent) - fail_msg_writer() << tr("wallet failed to connect to daemon: ") << m_wallet->get_daemon_address() << ". " << tr("Daemon either is not started or wrong port was passed. " - "Please make sure daemon is running or change the daemon address using the 'set_daemon' command."); + { + GULPS_PRINT_FAIL(tr("wallet failed to connect to daemon: "), m_wallet->get_daemon_address(), ".\n", + tr("Daemon either is not started or wrong port was passed. Please make sure daemon is running or change the daemon address using the 'set_daemon' command.")); + } return false; } if(!m_allow_mismatched_daemon_version && ((*version >> 16) != CORE_RPC_VERSION_MAJOR)) { if(!silent) - fail_msg_writer() << boost::format(tr("Daemon uses a different RPC major version (%u) than the wallet (%u): %s. Either update one of them, or use --allow-mismatched-daemon-version.")) % (*version >> 16) % CORE_RPC_VERSION_MAJOR % m_wallet->get_daemon_address(); + { + GULPSF_ERROR(tr("Error: Daemon uses a different RPC major version ({}) than the wallet ({}): {}. Either update one of them, or use --allow-mismatched-daemon-version."), + *version >> 16, CORE_RPC_VERSION_MAJOR, m_wallet->get_daemon_address()); + } return false; } return true; @@ -3191,9 +3196,9 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t *version) /*! * \brief Gets the word seed language from the user. - * + * * User is asked to choose from a list of supported languages. - * + * * \return The chosen language. */ std::string simple_wallet::get_mnemonic_language(bool ignore_cmd_arg) @@ -3209,18 +3214,18 @@ std::string simple_wallet::get_mnemonic_language(bool ignore_cmd_arg) //Don't return smelly user input here if(!ret.empty()) - return ret; + return ret; - fail_msg_writer() << boost::format(tr("Language '%s' is not in the language list. Please specify the language manually.\n")) % m_mnemonic_language.c_str(); + GULPSF_ERROR(tr("Error: Language '{}' is not in the language list. Please specify the language manually.\n"), m_mnemonic_language); } - std::cout << tr("List of available languages for your wallet's seed:") << std::endl; - std::cout << tr("If your display freezes, exit blind with ^C, then run again with --use-english-language-names") << std::endl; + GULPS_PRINT_OK(tr("List of available languages for your wallet's seed:")); + GULPS_PRINT_OK(tr("If your display freezes, exit blind with ^C, then run again with --use-english-language-names")); int ii; std::vector::iterator it; for(it = language_list.begin(), ii = 0; it != language_list.end(); it++, ii++) { - std::cout << ii << " : " << *it << std::endl; + GULPS_PRINT_OK(ii, " : ", *it); } while(language_number < 0) { @@ -3233,12 +3238,12 @@ std::string simple_wallet::get_mnemonic_language(bool ignore_cmd_arg) if(!((language_number >= 0) && (static_cast(language_number) < language_list.size()))) { language_number = -1; - fail_msg_writer() << tr("invalid language choice entered. Please try again.\n"); + GULPS_PRINT_FAIL(tr("invalid language choice entered. Please try again.\n")); } } catch(const std::exception &e) { - fail_msg_writer() << tr("invalid language choice entered. Please try again.\n"); + GULPS_PRINT_FAIL(tr("invalid language choice entered. Please try again.\n")); } } return language_list[language_number]; @@ -3252,7 +3257,7 @@ boost::optional simple_wallet::get_and_verify_passwor if(!m_wallet->verify_password(pwd_container->password())) { - fail_msg_writer() << tr("invalid password"); + GULPS_PRINT_FAIL(tr("invalid password")); return boost::none; } return pwd_container; @@ -3292,13 +3297,13 @@ bool simple_wallet::new_wallet_from_seed(const boost::program_options::variables } else { - fail_msg_writer() << tr("Unkown seed size ") << wseed.size() << tr(" please enter 12, 14, 24, 25 or 26 words"); + GULPS_PRINT_FAIL(tr("Unkown seed size "), wseed.size(), tr(" please enter 12, 14, 24, 25 or 26 words")); return false; } if(!decode_14 && !decode_25) { - fail_msg_writer() << tr("Electrum-style word list failed verification"); + GULPS_PRINT_FAIL(tr("Electrum-style word list failed verification")); return false; } @@ -3308,7 +3313,7 @@ bool simple_wallet::new_wallet_from_seed(const boost::program_options::variables return restore_legacy_wallet(vm, language, seed_25); } -std::pair, tools::password_container> simple_wallet::make_new_wrapped(const boost::program_options::variables_map &vm, +std::pair, tools::password_container> simple_wallet::make_new_wrapped(const boost::program_options::variables_map &vm, const std::function(const char *, bool)> &password_prompter) { try @@ -3317,7 +3322,7 @@ std::pair, tools::password_container> simple_wal } catch(const std::exception &e) { - fail_msg_writer() << tr("Initialization error: ") << e.what(); + GULPS_PRINT_FAIL(tr("Initialization error: "), e.what()); return {nullptr, tools::password_container{}}; } } @@ -3347,14 +3352,13 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map &vm, try { recovery_val = m_wallet->generate_new(m_wallet_file, std::move(rc.second).password(), seed, seed_extra, create_address_file); - message_writer(console_color_white, true) << tr("Generated new wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + GULPS_PRINT_BOLD(tr("Generated new wallet: "), m_wallet->get_account().get_public_address_str(m_wallet->nettype())); if(!m_wallet->get_account().is_kurz()) - std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL; + GULPS_PRINT_SECRET(tr("View key: "), string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key)); } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to generate new wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to generate new wallet: "), e.what()); return false; } @@ -3365,18 +3369,18 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map &vm, else crypto::Electrum14Words::bytes_to_words(*seed, seed_extra, electrum_words, m_wallet->get_seed_language()); - success_msg_writer() << "**********************************************************************\n" - << tr("Your wallet has been generated!\n" - "To start synchronizing with the daemon, use the \"refresh\" command.\n" - "Use the \"help\" command to see the list of available commands.\n" - "Use \"help \" to see a command's documentation.\n" - "Always use the \"exit\" command when closing ryo-wallet-cli to save \n" - "your current session's state. Otherwise, you might need to synchronize \n" - "your wallet again (your wallet keys are NOT at risk in any case).\n"); + GULPS_PRINT_OK("**********************************************************************\n", + tr("Your wallet has been generated!\n" + "To start synchronizing with the daemon, use the \"refresh\" command.\n" + "Use the \"help\" command to see the list of available commands.\n" + "Use \"help \" to see a command's documentation.\n" + "Always use the \"exit\" command when closing ryo-wallet-cli to save \n" + "your current session's state. Otherwise, you might need to synchronize \n" + "your wallet again (your wallet keys are NOT at risk in any case).\n\n")); print_seed(electrum_words, true); - success_msg_writer() << "**********************************************************************"; + GULPS_PRINT_OK("**********************************************************************"); return true; } @@ -3404,31 +3408,30 @@ bool simple_wallet::restore_legacy_wallet(const boost::program_options::variable try { m_wallet->generate_legacy(m_wallet_file, std::move(rc.second).password(), seed_legacy, create_address_file); - message_writer(console_color_white, true) << tr("Restored wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); - std::cout << tr("View key: ") << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key) << ENDL; + GULPS_PRINT_BOLD(tr("Restored wallet: "), m_wallet->get_account().get_public_address_str(m_wallet->nettype())); + GULPS_PRINT_SECRET(tr("View key: "), string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key)); } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to restore wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to restore wallet: "), e.what()); return false; } std::string electrum_words; crypto::Electrum25Words::bytes_to_words(seed_legacy, electrum_words, m_wallet->get_seed_language()); - success_msg_writer() << "**********************************************************************\n" - << tr("Your wallet has been restored!\n" - "To start synchronizing with the daemon, use the \"refresh\" command.\n" - "Use the \"help\" command to see the list of available commands.\n" - "Use \"help \" to see a command's documentation.\n" - "Always use the \"exit\" command when closing ryo-wallet-cli to save \n" - "your current session's state. Otherwise, you might need to synchronize \n" - "your wallet again (your wallet keys are NOT at risk in any case).\n"); + GULPS_PRINT_OK("**********************************************************************\n", + tr("Your wallet has been restored!\n" + "To start synchronizing with the daemon, use the \"refresh\" command.\n" + "Use the \"help\" command to see the list of available commands.\n" + "Use \"help \" to see a command's documentation.\n" + "Always use the \"exit\" command when closing ryo-wallet-cli to save \n" + "your current session's state. Otherwise, you might need to synchronize \n" + "your wallet again (your wallet keys are NOT at risk in any case).\n\n")); print_seed(electrum_words, false); - success_msg_writer() << "**********************************************************************"; + GULPS_PRINT_OK("**********************************************************************"); return true; } //---------------------------------------------------------------------------------------------------- @@ -3465,12 +3468,11 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map &vm, { m_wallet->generate(m_wallet_file, std::move(rc.second).password(), address, viewkey, create_address_file); } - message_writer(console_color_white, true) << tr("Generated new wallet: ") - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + GULPS_PRINT_BOLD(tr("Generated new wallet: "), m_wallet->get_account().get_public_address_str(m_wallet->nettype())); } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to generate new wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to generate new wallet: "), e.what()); return false; } @@ -3500,12 +3502,11 @@ bool simple_wallet::new_wallet_dev(const boost::program_options::variables_map & try { m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name); - message_writer(console_color_white, true) << tr("Generated new wallet on hw device: ") - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + GULPS_PRINT_BOLD(tr("Generated new wallet on hw device: "), m_wallet->get_account().get_public_address_str(m_wallet->nettype())); } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to generate new wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to generate new wallet: "), e.what()); return false; } @@ -3548,15 +3549,15 @@ bool simple_wallet::new_wallet_msig(const boost::program_options::variables_map uint32_t threshold, total; if(!m_wallet->multisig(&ready, &threshold, &total) || !ready) { - fail_msg_writer() << tr("failed to generate new mutlisig wallet"); + GULPS_PRINT_FAIL(tr("failed to generate new mutlisig wallet")); return false; } - message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total - << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + + GULPSF_PRINT_OK(tr("Generated new {}/{} multisig wallet: {}"), threshold, total, m_wallet->get_account().get_public_address_str(m_wallet->nettype())); } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to generate new wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to generate new wallet: "), e.what()); return false; } @@ -3567,7 +3568,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map &vm) { if(!tools::wallet2::wallet_valid_path_format(m_wallet_file)) { - fail_msg_writer() << tr("wallet file path not valid: ") << m_wallet_file; + GULPS_PRINT_FAIL(tr("wallet file path not valid: "), m_wallet_file); return false; } epee::wipeable_string password; @@ -3587,18 +3588,19 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map &vm) if(m_wallet->watch_only()) prefix = tr("Opened watch-only wallet"); else if(m_wallet->multisig(&ready, &threshold, &total)) - prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str(); + prefix = fmt::format(tr("Opened {}/{} multisig wallet{}"), threshold, total, ready ? "" : " (not yet finalized)"); else prefix = tr("Opened wallet"); - message_writer(console_color_white, true) << prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + + GULPS_PRINT_BOLD(prefix, ": ", m_wallet->get_account().get_public_address_str(m_wallet->nettype())); if(m_wallet->get_account().get_device()) { - message_writer(console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name(); + GULPS_PRINT_BOLD("Wallet is on device: ", m_wallet->get_account().get_device().get_name()); } } catch(const std::exception &e) { - fail_msg_writer() << tr("failed to load wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("failed to load wallet: "), e.what()); if(m_wallet) { // only suggest removing cache if the password was actually correct @@ -3611,12 +3613,14 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map &vm) { } // guard against I/O errors if(password_is_correct) - fail_msg_writer() << boost::format(tr("You may want to remove the file \"%s\" and try again")) % m_wallet_file; + GULPSF_ERROR(tr("Error: You may want to remove the file \"{}\" and try again"), m_wallet_file); } return false; } - success_msg_writer() << "**********************************************************************\n" - << tr("Use the \"help\" command to see the list of available commands.\n") << tr("Use \"help \" to see a command's documentation.\n") << "**********************************************************************"; + GULPS_PRINT_OK("**********************************************************************\n", + tr("Use the \"help\" command to see the list of available commands.\n"), + tr("Use \"help \" to see a command's documentation.\n"), + "**********************************************************************"); return true; } //---------------------------------------------------------------------------------------------------- @@ -3636,7 +3640,7 @@ bool simple_wallet::close_wallet() bool r = m_wallet->deinit(); if(!r) { - fail_msg_writer() << tr("failed to deinitialize wallet"); + GULPS_PRINT_FAIL(tr("failed to deinitialize wallet")); return false; } @@ -3646,7 +3650,7 @@ bool simple_wallet::close_wallet() } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); return false; } @@ -3659,11 +3663,11 @@ bool simple_wallet::save(const std::vector &args) { LOCK_IDLE_SCOPE(); m_wallet->store(); - success_msg_writer() << tr("Wallet data saved"); + GULPS_PRINT_OK(tr("Wallet data saved")); } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } return true; @@ -3673,7 +3677,7 @@ bool simple_wallet::save_watch_only(const std::vector &args /* = st { if(m_wallet->multisig()) { - fail_msg_writer() << tr("wallet is multisig and cannot save a watch-only version"); + GULPS_PRINT_FAIL(tr("wallet is multisig and cannot save a watch-only version")); return true; } @@ -3681,7 +3685,7 @@ bool simple_wallet::save_watch_only(const std::vector &args /* = st if(!pwd_container) { - fail_msg_writer() << tr("failed to read wallet password"); + GULPS_PRINT_FAIL(tr("failed to read wallet password")); return true; } @@ -3689,11 +3693,11 @@ bool simple_wallet::save_watch_only(const std::vector &args /* = st { std::string new_keys_filename; m_wallet->write_watch_only_wallet(m_wallet_file, pwd_container->password(), new_keys_filename); - success_msg_writer() << tr("Watch only wallet saved as: ") << new_keys_filename; + GULPS_PRINT_OK(tr("Watch only wallet saved as: "), new_keys_filename); } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to save watch only wallet: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to save watch only wallet: "), e.what()); return true; } return true; @@ -3704,7 +3708,7 @@ bool simple_wallet::start_mining(const std::vector &args) { if(!m_trusted_daemon) { - fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); + GULPS_PRINT_FAIL(tr("this command requires a trusted daemon. Enable with --trusted-daemon")); return true; } @@ -3713,7 +3717,7 @@ bool simple_wallet::start_mining(const std::vector &args) if(!m_wallet) { - fail_msg_writer() << tr("wallet is null"); + GULPS_PRINT_FAIL(tr("wallet is null")); return true; } COMMAND_RPC_START_MINING::request req = AUTO_VAL_INIT(req); @@ -3746,9 +3750,8 @@ bool simple_wallet::start_mining(const std::vector &args) if(!ok) { - fail_msg_writer() << tr("invalid arguments. Please use start_mining [] [do_bg_mining] [ignore_battery], " - " should be from 1 to ") - << max_mining_threads_count; + GULPS_PRINT_FAIL(tr("invalid arguments. Please use start_mining [] [do_bg_mining] [ignore_battery], " + " should be from 1 to "), max_mining_threads_count); return true; } @@ -3756,9 +3759,9 @@ bool simple_wallet::start_mining(const std::vector &args) bool r = m_wallet->invoke_http_json("/start_mining", req, res); std::string err = interpret_rpc_response(r, res.status); if(err.empty()) - success_msg_writer() << tr("Mining started in daemon"); + GULPS_PRINT_OK(tr("Mining started in daemon")); else - fail_msg_writer() << tr("mining has NOT been started: ") << err; + GULPS_PRINT_FAIL(tr("mining has NOT been started: "), err); return true; } //---------------------------------------------------------------------------------------------------- @@ -3769,7 +3772,7 @@ bool simple_wallet::stop_mining(const std::vector &args) if(!m_wallet) { - fail_msg_writer() << tr("wallet is null"); + GULPS_PRINT_FAIL(tr("wallet is null")); return true; } @@ -3778,9 +3781,9 @@ bool simple_wallet::stop_mining(const std::vector &args) bool r = m_wallet->invoke_http_json("/stop_mining", req, res); std::string err = interpret_rpc_response(r, res.status); if(err.empty()) - success_msg_writer() << tr("Mining stopped in daemon"); + GULPS_PRINT_OK(tr("Mining stopped in daemon")); else - fail_msg_writer() << tr("mining has NOT been stopped: ") << err; + GULPS_PRINT_FAIL(tr("mining has NOT been stopped: "), err); return true; } //---------------------------------------------------------------------------------------------------- @@ -3790,7 +3793,7 @@ bool simple_wallet::set_daemon(const std::vector &args) if(args.size() < 1) { - fail_msg_writer() << tr("missing daemon URL argument"); + GULPS_PRINT_FAIL(tr("missing daemon URL argument")); return true; } @@ -3801,7 +3804,7 @@ bool simple_wallet::set_daemon(const std::vector &args) { if(match.length() < 4) { - fail_msg_writer() << tr("Unexpected array length - Exited simple_wallet::set_daemon()"); + GULPS_PRINT_FAIL(tr("Unexpected array length - Exited simple_wallet::set_daemon()")); return true; } // If no port has been provided, use the default from config @@ -3819,7 +3822,7 @@ bool simple_wallet::set_daemon(const std::vector &args) } else { - fail_msg_writer() << tr("This does not seem to be a valid daemon URL."); + GULPS_PRINT_FAIL(tr("This does not seem to be a valid daemon URL.")); } return true; } @@ -3831,7 +3834,7 @@ bool simple_wallet::save_bc(const std::vector &args) if(!m_wallet) { - fail_msg_writer() << tr("wallet is null"); + GULPS_PRINT_FAIL(tr("wallet is null")); return true; } COMMAND_RPC_SAVE_BC::request req; @@ -3839,9 +3842,9 @@ bool simple_wallet::save_bc(const std::vector &args) bool r = m_wallet->invoke_http_json("/save_bc", req, res); std::string err = interpret_rpc_response(r, res.status); if(err.empty()) - success_msg_writer() << tr("Blockchain saved"); + GULPS_PRINT_OK(tr("Blockchain saved")); else - fail_msg_writer() << tr("blockchain can't be saved: ") << err; + GULPS_PRINT_FAIL(tr("blockchain can't be saved: "), err); return true; } //---------------------------------------------------------------------------------------------------- @@ -3855,14 +3858,14 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, { if(m_wallet->get_refresh_from_block_height() > height) { - fail_msg_writer() << "This wallet has an incorrect start height." << - "Please recreate it from seed to avoid a case where a blockchain scan can miss a part of your balance."; + GULPS_PRINT_FAIL("This wallet has an incorrect start height. Please recreate it from seed to avoid a case where a blockchain scan can miss a part of your balance."); /* this update will not be stored in the key file but correct the balance until the user * calls again `rescan_bc` without adding a height. */ m_wallet->set_refresh_from_block_height(height); } - message_writer(console_color_green, false) << "\r" << tr("Height ") << height << ", " << tr("txid ") << txid << ", " << print_money(amount) << ", " << tr("idx ") << subaddr_index; + + GULPS_PRINT_GREEN("\r", tr("Height "), height, ", ", tr("txid "), txid, ", ", print_money(amount), ", ", tr("idx "), subaddr_index); if(m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); else @@ -3876,7 +3879,8 @@ void simple_wallet::on_unconfirmed_money_received(uint64_t height, const crypto: //---------------------------------------------------------------------------------------------------- void simple_wallet::on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction &in_tx, uint64_t amount, const cryptonote::transaction &spend_tx, const cryptonote::subaddress_index &subaddr_index) { - message_writer(console_color_magenta, false) << "\r" << tr("Height ") << height << ", " << tr("txid ") << txid << ", " << tr("spent ") << print_money(amount) << ", " << tr("idx ") << subaddr_index; + GULPS_PRINT_CLR(gulps::COLOR_MAGENTA, "\r", tr("Height "), height, ", ", tr("txid "), txid, ", ", tr("spent "), print_money(amount), ", ", tr("idx "), subaddr_index); + if(m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); else @@ -3897,11 +3901,8 @@ bool simple_wallet::refresh_main(uint64_t start_height, bool reset, bool is_init if(reset) m_wallet->rescan_blockchain(false); -#ifdef HAVE_READLINE - rdln::suspend_readline pause_readline; -#endif - - message_writer() << tr("Starting refresh..."); + PAUSE_READLINE(); + GULPS_PRINT_OK(tr("Starting refresh...")); uint64_t fetched_blocks = 0; bool ok = false; @@ -3919,9 +3920,7 @@ bool simple_wallet::refresh_main(uint64_t start_height, bool reset, bool is_init m_wallet->explicit_refresh_from_block_height(use_opt_height_old); ok = true; - // Clear line "Height xxx of xxx" - std::cout << "\r \r"; - success_msg_writer(true) << tr("Refresh done, blocks received: ") << fetched_blocks; + GULPS_PRINT_GREEN(tr("Refresh done, blocks received: "), fetched_blocks); if(is_init) print_accounts(); show_balance_unlocked(); @@ -3936,33 +3935,33 @@ bool simple_wallet::refresh_main(uint64_t start_height, bool reset, bool is_init } catch(const tools::error::wallet_rpc_error &e) { - LOG_ERROR("RPC error: " << e.to_string()); + GULPS_LOG_ERROR("RPC error: ", e.to_string()); ss << tr("RPC error: ") << e.what(); } catch(const tools::error::refresh_error &e) { - LOG_ERROR("refresh error: " << e.to_string()); + GULPS_LOG_ERROR("refresh error: ", e.to_string()); ss << tr("refresh error: ") << e.what(); } catch(const tools::error::wallet_internal_error &e) { - LOG_ERROR("internal error: " << e.to_string()); + GULPS_LOG_ERROR("internal error: ", e.to_string()); ss << tr("internal error: ") << e.what(); } catch(const std::exception &e) { - LOG_ERROR("unexpected error: " << e.what()); + GULPS_LOG_ERROR("unexpected error: ", e.what()); ss << tr("unexpected error: ") << e.what(); } catch(...) { - LOG_ERROR("unknown error"); + GULPS_LOG_ERROR("unknown error"); ss << tr("unknown error"); } if(!ok) { - fail_msg_writer() << tr("refresh failed: ") << ss.str() << ". " << tr("Blocks received: ") << fetched_blocks; + GULPS_PRINT_FAIL(tr("refresh failed: "), ss.str(), ". ", tr("Blocks received: "), fetched_blocks); } return true; @@ -3990,17 +3989,17 @@ bool simple_wallet::show_balance_unlocked(bool detailed) std::string extra; if(m_wallet->has_multisig_partial_key_images()) extra = tr(" (Some owned outputs have partial key images - import_multisig_info needed)"); - success_msg_writer() << tr("Currently selected account: [") << m_current_subaddress_account << tr("] ") << m_wallet->get_subaddress_label({m_current_subaddress_account, 0}); + GULPS_PRINT_OK(tr("Currently selected account: ["), m_current_subaddress_account, tr("] "), m_wallet->get_subaddress_label({m_current_subaddress_account, 0})); const std::string tag = m_wallet->get_account_tags().second[m_current_subaddress_account]; - success_msg_writer() << tr("Tag: ") << (tag.empty() ? std::string{tr("(No tag assigned)")} : tag); - success_msg_writer() << tr("Balance: ") << print_money(m_wallet->balance(m_current_subaddress_account)) << ", " - << tr("unlocked balance: ") << print_money(m_wallet->unlocked_balance(m_current_subaddress_account)) << extra; + GULPS_PRINT_OK(tr("Tag: "), (tag.empty() ? std::string{tr("(No tag assigned)")} : tag)); + GULPS_PRINT_OK(tr("Balance: "), print_money(m_wallet->balance(m_current_subaddress_account)), ", ", + tr("unlocked balance: "), print_money(m_wallet->unlocked_balance(m_current_subaddress_account)), extra); std::map balance_per_subaddress = m_wallet->balance_per_subaddress(m_current_subaddress_account); std::map unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account); if(!detailed || balance_per_subaddress.empty()) return true; - success_msg_writer() << tr("Balance per address:"); - success_msg_writer() << boost::format("%15s %21s %21s %7s %21s") % tr("Address") % tr("Balance") % tr("Unlocked balance") % tr("Outputs") % tr("Label"); + GULPS_PRINT_OK(tr("Balance per address:")); + GULPSF_PRINT_OK("{:>15} {:>21} {:>21} {:>7} {:>21}", tr("Address"), tr("Balance"), tr("Unlocked balance"), tr("Outputs"), tr("Label")); std::vector transfers; m_wallet->get_transfers(transfers); for(const auto &i : balance_per_subaddress) @@ -4008,7 +4007,8 @@ bool simple_wallet::show_balance_unlocked(bool detailed) cryptonote::subaddress_index subaddr_index = {m_current_subaddress_account, i.first}; std::string address_str = m_wallet->get_subaddress_as_str(subaddr_index).substr(0, 6); uint64_t num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&subaddr_index](const tools::wallet2::transfer_details &td) { return !td.m_spent && td.m_subaddr_index == subaddr_index; }); - success_msg_writer() << boost::format(tr("%8u %6s %21s %21s %7u %21s")) % i.first % address_str % print_money(i.second) % print_money(unlocked_balance_per_subaddress[i.first]) % num_unspent_outputs % m_wallet->get_subaddress_label(subaddr_index); + GULPSF_PRINT_OK("{:>8} {:>6} {:>21} {:>21} {:>7} {:>21}", i.first, address_str, print_money(i.second), + print_money(unlocked_balance_per_subaddress[i.first]), num_unspent_outputs, m_wallet->get_subaddress_label(subaddr_index)); } return true; } @@ -4017,7 +4017,7 @@ bool simple_wallet::show_balance(const std::vector &args /* = std:: { if(args.size() > 1 || (args.size() == 1 && args[0] != "detail")) { - fail_msg_writer() << tr("usage: balance [detail]"); + GULPS_PRINT_FAIL(tr("usage: balance [detail]")); return true; } LOCK_IDLE_SCOPE(); @@ -4029,7 +4029,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector &args { if(args.size() > 3) { - fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]"); + GULPS_PRINT_FAIL(tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]")); return true; } auto local_args = args; @@ -4071,7 +4071,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector &args if(local_args.size() > 0) { - fail_msg_writer() << tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]"); + GULPS_PRINT_FAIL(tr("usage: incoming_transfers [available|unavailable] [verbose] [index=]")); return true; } @@ -4089,22 +4089,31 @@ bool simple_wallet::show_incoming_transfers(const std::vector &args { std::string verbose_string; if(verbose) - verbose_string = (boost::format("%68s%68s") % tr("pubkey") % tr("key image")).str(); - message_writer() << boost::format("%21s%8s%12s%8s%16s%68s%16s%s") % tr("amount") % tr("spent") % tr("unlocked") % tr("ringct") % tr("global index") % tr("tx id") % tr("addr index") % verbose_string; + verbose_string = fmt::format("{:>68}{:>68}", tr("pubkey"), tr("key image")); + + GULPSF_PRINT_OK("{:>21}{:>8}{:>12}{:>16}{:>68}{:>16}{}", tr("amount"), tr("spent"), tr("unlocked"), + tr("global index"), tr("tx id"), tr("addr index"), verbose_string); + transfers_found = true; } + std::string verbose_string; if(verbose) - verbose_string = (boost::format("%68s%68s") % td.get_public_key() % (td.m_key_image_known ? epee::string_tools::pod_to_hex(td.m_key_image) : td.m_key_image_partial ? (epee::string_tools::pod_to_hex(td.m_key_image) + "/p") : std::string(64, '?'))).str(); - message_writer(td.m_spent ? console_color_magenta : console_color_green, false) << boost::format("%21s%8s%12s%8s%16u%68s%16u%s") % - print_money(td.amount()) % - (td.m_spent ? tr("T") : tr("F")) % - (m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked")) % - (td.is_rct() ? tr("RingCT") : tr("-")) % - td.m_global_output_index % - td.m_txid % - td.m_subaddr_index.minor % - verbose_string; + { + std::string kimg; + if(td.m_key_image_known) + kimg = epee::string_tools::pod_to_hex(td.m_key_image); + else if(td.m_key_image_partial) + kimg = epee::string_tools::pod_to_hex(td.m_key_image) + "/p"; + else + kimg = std::string(64, '?'); + + verbose_string = fmt::format("{:>3}{:>64}{}{:>68}", "<", td.get_public_key(), ">", kimg); + } + + GULPSF_PRINT_CLR(td.m_spent ? gulps::COLOR_MAGENTA : gulps::COLOR_GREEN, "{:>21}{:>8}{:>12}{:>16}{:>3}{:>64}{}{:>16}{}", + print_money(td.amount()), td.m_spent ? tr("T") : tr("F"), m_wallet->is_transfer_unlocked(td) ? tr("unlocked") : tr("locked"), + td.m_global_output_index, "<", td.m_txid, ">", td.m_subaddr_index.minor, verbose_string); } } @@ -4112,15 +4121,15 @@ bool simple_wallet::show_incoming_transfers(const std::vector &args { if(!filter) { - success_msg_writer() << tr("No incoming transfers"); + GULPS_PRINT_OK(tr("No incoming transfers")); } else if(available) { - success_msg_writer() << tr("No incoming available transfers"); + GULPS_PRINT_OK(tr("No incoming available transfers")); } else { - success_msg_writer() << tr("No incoming unavailable transfers"); + GULPS_PRINT_OK(tr("No incoming unavailable transfers")); } } @@ -4131,7 +4140,7 @@ bool simple_wallet::show_payments(const std::vector &args) { if(args.empty()) { - fail_msg_writer() << tr("expected at least one payment ID"); + GULPS_PRINT_FAIL(tr("expected at least one payment ID")); return true; } @@ -4139,8 +4148,7 @@ bool simple_wallet::show_payments(const std::vector &args) PAUSE_READLINE(); - message_writer() << boost::format("%68s%68s%12s%21s%16s%16s") % - tr("payment") % tr("transaction") % tr("height") % tr("amount") % tr("unlock time") % tr("addr index"); + GULPSF_PRINT_OK("{:>68}{:>68}{:>12}{:>21}{:>16}{:>16}", tr("payment"), tr("transaction"), tr("height"), tr("amount"), tr("unlock time"), tr("addr index")); bool payments_found = false; for(std::string arg : args) @@ -4152,7 +4160,7 @@ bool simple_wallet::show_payments(const std::vector &args) m_wallet->get_payments(payment_id, payments); if(payments.empty()) { - success_msg_writer() << tr("No payments with id ") << payment_id.payment_id; + GULPS_PRINT_OK(tr("No payments with id "), payment_id.payment_id); continue; } @@ -4162,18 +4170,18 @@ bool simple_wallet::show_payments(const std::vector &args) { payments_found = true; } - success_msg_writer(true) << boost::format("%68s%68s%12s%21s%16s%16s") % - payment_id.payment_id % - pd.m_tx_hash % - pd.m_block_height % - print_money(pd.m_amount) % - pd.m_unlock_time % - pd.m_subaddr_index.minor; + GULPSF_PRINT_CLR(gulps::COLOR_GREEN, "{}{}{}{}{}{}", + payment_id.payment_id, + pd.m_tx_hash, + pd.m_block_height, + print_money(pd.m_amount), + pd.m_unlock_time, + pd.m_subaddr_index.minor); } } else { - fail_msg_writer() << tr("payment ID has invalid format, expected 16 or 64 character hex string: ") << arg; + GULPS_PRINT_FAIL(tr("payment ID has invalid format, expected 16 or 64 character hex string: "), arg); } } @@ -4202,9 +4210,9 @@ bool simple_wallet::show_blockchain_height(const std::vector &args) std::string err; uint64_t bc_height = get_daemon_blockchain_height(err); if(err.empty()) - success_msg_writer() << bc_height; + GULPS_PRINT_OK(bc_height); else - fail_msg_writer() << tr("failed to get blockchain height: ") << err; + GULPS_PRINT_FAIL(tr("failed to get blockchain height: "), err); return true; } //---------------------------------------------------------------------------------------------------- @@ -4212,7 +4220,7 @@ bool simple_wallet::rescan_spent(const std::vector &args) { if(!m_trusted_daemon) { - fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); + GULPS_PRINT_FAIL(tr("this command requires a trusted daemon. Enable with --trusted-daemon")); return true; } @@ -4226,30 +4234,30 @@ bool simple_wallet::rescan_spent(const std::vector &args) } catch(const tools::error::daemon_busy &) { - fail_msg_writer() << tr("daemon is busy. Please try again later."); + GULPS_PRINT_FAIL(tr("daemon is busy. Please try again later.")); } catch(const tools::error::no_connection_to_daemon &) { - fail_msg_writer() << tr("no connection to daemon. Please make sure daemon is running."); + GULPS_PRINT_FAIL(tr("no connection to daemon. Please make sure daemon is running.")); } catch(const tools::error::is_key_image_spent_error &) { - fail_msg_writer() << tr("failed to get spent status"); + GULPS_PRINT_FAIL(tr("failed to get spent status")); } catch(const tools::error::wallet_rpc_error &e) { - LOG_ERROR("RPC error: " << e.to_string()); - fail_msg_writer() << tr("RPC error: ") << e.what(); + GULPS_LOG_ERROR("RPC error: ", e.to_string()); + GULPS_PRINT_FAIL(tr("RPC error: "), e.what()); } catch(const std::exception &e) { - LOG_ERROR("unexpected error: " << e.what()); - fail_msg_writer() << tr("unexpected error: ") << e.what(); + GULPS_LOG_ERROR("unexpected error: ", e.what()); + GULPS_PRINT_FAIL(tr("unexpected error: "), e.what()); } catch(...) { - LOG_ERROR("unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -4260,7 +4268,7 @@ bool simple_wallet::print_ring_members(const std::vector spent_key_height(tx.vin.size()); std::vector spent_key_txid(tx.vin.size()); @@ -4294,12 +4302,12 @@ bool simple_wallet::print_ring_members(const std::vector absolute_offsets = cryptonote::relative_output_offsets_to_absolute(in_key.key_offsets); // get block heights from which those ring member keys originated @@ -4315,7 +4323,7 @@ bool simple_wallet::print_ring_members(const std::vector= blockchain_height) { - fail_msg_writer() << tr("output key's originating block height shouldn't be higher than the blockchain height"); + GULPS_PRINT_FAIL(tr("output key's originating block height shouldn't be higher than the blockchain height")); return false; } } @@ -4359,12 +4367,11 @@ bool simple_wallet::print_ring_members(const std::vectoradjust_mixin(fake_outs_count); if(adjusted_fake_outs_count > fake_outs_count) { - fail_msg_writer() << (boost::format(tr("ring size %u is too small, minimum is %u")) % (fake_outs_count + 1) % (adjusted_fake_outs_count + 1)).str(); + GULPSF_ERROR(tr("Error: ring size {} is too small, minimum is {}"), fake_outs_count + 1, adjusted_fake_outs_count + 1); return true; } const size_t min_args = (transfer_type == TransferLocked) ? 3 : 2; if(local_args.size() < min_args) { - fail_msg_writer() << tr("wrong number of arguments"); + GULPS_PRINT_FAIL(tr("wrong number of arguments")); return true; } - + crypto::uniform_payment_id payment_id; bool expect_even = (transfer_type == TransferLocked); if((expect_even ? 0 : 1) == local_args.size() % 2) @@ -4441,12 +4448,12 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorconfirm_missing_payment_id()) - message_writer() << tr("You included a PID. Normally this would be a privacy problem, however Ryo Uniform PID's fixed this."); + GULPS_PRINT_OK(tr("You included a PID. Normally this would be a privacy problem, however Ryo Uniform PID's fixed this.")); } uint64_t locked_blocks = 0; @@ -4458,12 +4465,12 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector 1000000) { - fail_msg_writer() << tr("Locked blocks too high, max 1000000 (˜4 yrs)"); + GULPS_PRINT_FAIL(tr("Locked blocks too high, max 1000000 (˜4 yrs)")); return true; } local_args.pop_back(); @@ -4476,7 +4483,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectornettype(), info, local_args[i])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } de.addr = info.address; @@ -4486,7 +4493,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector::max()); + GULPS_PRINT_FAIL(tr("amount is wrong: "), local_args[i], ' ', local_args[i + 1], ", ", tr("expected number from 0 to "), print_money(std::numeric_limits::max())); return true; } @@ -4511,7 +4518,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorcreate_transactions_2(dsts, fake_outs_count, unlock_block, priority, payment_id.zero == 0 ? &payment_id : nullptr, + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block, priority, payment_id.zero == 0 ? &payment_id : nullptr, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); break; case TransferNew: - ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0, priority, payment_id.zero == 0 ? &payment_id : nullptr, + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0, priority, payment_id.zero == 0 ? &payment_id : nullptr, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); break; default: - fail_msg_writer() << tr("Unknown transfer method"); + GULPS_PRINT_FAIL(tr("Unknown transfer method")); return true; } if(ptx_vector.empty()) { - fail_msg_writer() << tr("No outputs found, or daemon is not ready"); + GULPS_PRINT_FAIL(tr("No outputs found, or daemon is not ready")); return true; } @@ -4575,12 +4582,12 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector m_wallet->get_confirm_backlog_threshold()) - prompt << (boost::format(tr("There is currently a %u block backlog at that fee level. Is this okay? (Y/Yes/N/No): ")) % nblocks[0].first).str(); + prompt << fmt::format(tr("There is currently a {} block backlog at that fee level. Is this okay? (Y/Yes/N/No): "), nblocks[0].first); } } catch(const std::exception &e) { - prompt << tr("Failed to check for backlog: ") << e.what() << ENDL << tr("Is this okay anyway? (Y/Yes/N/No): "); + prompt << tr("Failed to check for backlog: ") << e.what() << "\n" << tr("Is this okay anyway? (Y/Yes/N/No): "); } std::string prompt_str = prompt.str(); @@ -4591,7 +4598,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector 1) prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n"); } - prompt << boost::format(tr("Sending %s. ")) % print_money(total_sent); + prompt << fmt::format(tr("Sending {}. "), print_money(total_sent)); if(ptx_vector.size() > 1) { - prompt << boost::format(tr("Your transaction needs to be split into %llu transactions. " - "This will result in a transaction fee being applied to each transaction, for a total fee of %s")) % - ((unsigned long long)ptx_vector.size()) % print_money(total_fee); + prompt << fmt::format(tr("Your transaction needs to be split into {} transactions. " + "This will result in a transaction fee being applied to each transaction, for a total fee of {}"), ptx_vector.size(), print_money(total_fee)); } else { - prompt << boost::format(tr("The transaction fee is %s")) % print_money(total_fee); + prompt << tr("The transaction fee is ") << print_money(total_fee); } if(dust_in_fee != 0) - prompt << boost::format(tr(", of which %s is dust from change")) % print_money(dust_in_fee); + prompt << fmt::format(tr(", of which {} is dust from change"), print_money(dust_in_fee)); if(dust_not_in_fee != 0) - prompt << tr(".") << ENDL << boost::format(tr("A total of %s from dust change will be sent to dust address")) % print_money(dust_not_in_fee); + prompt << tr(".") << "\n" << fmt::format(tr("A total of {} from dust change will be sent to dust address"), print_money(dust_not_in_fee)); if(transfer_type == TransferLocked) { float days = float(locked_blocks * cryptonote::common_config::DIFFICULTY_TARGET) / (24.0f * 60.0f * 60.0f); - prompt << boost::format(tr(".\nThis transaction will unlock on block %llu, in approximately %s days")) % ((unsigned long long)unlock_block) % days; + prompt << fmt::format(tr(".\nThis transaction will unlock on block {}, in approximately {} days"), unlock_block, days); } if(m_wallet->print_ring_members()) { @@ -4672,14 +4678,14 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorsave_multisig_tx(ptx_vector, "multisig_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "multisig_ryo_tx"); } } else if(m_wallet->watch_only()) @@ -4703,11 +4709,11 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectorsave_tx(ptx_vector, "unsigned_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "unsigned_ryo_tx"); } } else @@ -4721,8 +4727,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector &a // sweep_all [index=[,,...]] []
[] if(args_.size() == 0) { - fail_msg_writer() << tr("No address given"); + GULPS_PRINT_FAIL(tr("No address given")); return true; } @@ -4782,7 +4788,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a } else if(ring_size == 0) { - fail_msg_writer() << tr("Ring size must not be 0"); + GULPS_PRINT_FAIL(tr("Ring size must not be 0")); return true; } else @@ -4794,7 +4800,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a uint64_t adjusted_fake_outs_count = m_wallet->adjust_mixin(fake_outs_count); if(adjusted_fake_outs_count > fake_outs_count) { - fail_msg_writer() << (boost::format(tr("ring size %u is too small, minimum is %u")) % (fake_outs_count + 1) % (adjusted_fake_outs_count + 1)).str(); + GULPSF_ERROR(tr("Error: ring size {} is too small, minimum is {}"), fake_outs_count + 1, adjusted_fake_outs_count + 1); return true; } @@ -4803,7 +4809,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a { if(!tools::wallet2::parse_payment_id(local_args.back(), pid) && local_args.size() == 3) { - fail_msg_writer() << tr("payment id has invalid format, expected 16 or 64 character hex string: ") << local_args.back(); + GULPS_PRINT_FAIL(tr("payment id has invalid format, expected 16 or 64 character hex string: "), local_args.back()); return true; } @@ -4814,7 +4820,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, local_args[0])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } @@ -4822,7 +4828,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a { if(pid.zero == 0) { - fail_msg_writer() << tr("a single transaction cannot use more than one payment id: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("a single transaction cannot use more than one payment id: "), local_args[0]); return true; } @@ -4837,7 +4843,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a return true; if(!command_line::is_yes(accepted)) { - fail_msg_writer() << tr("transaction cancelled."); + GULPS_PRINT_FAIL(tr("transaction cancelled.")); return true; } @@ -4848,12 +4854,12 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0, + auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0, priority, pid.zero == 0 ? &pid : nullptr, m_current_subaddress_account, subaddr_indices, m_trusted_daemon); if(ptx_vector.empty()) { - fail_msg_writer() << tr("No outputs found, or daemon is not ready"); + GULPS_PRINT_FAIL(tr("No outputs found, or daemon is not ready")); return true; } @@ -4874,7 +4880,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a for(uint32_t i : ptx_vector[n].construction_data.subaddr_indices) subaddr_indices.insert(i); for(uint32_t i : subaddr_indices) - prompt << boost::format(tr("Spending from address index %d\n")) % i; + prompt << fmt::format(tr("Spending from address index {}\n"), i); if(subaddr_indices.size() > 1) prompt << tr("WARNING: Outputs of multiple addresses are being used together, which might potentially compromise your privacy.\n"); } @@ -4882,23 +4888,20 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a return true; if(ptx_vector.size() > 1) { - prompt << boost::format(tr("Sweeping %s in %llu transactions for a total fee of %s. Is this okay? (Y/Yes/N/No): ")) % - print_money(total_sent) % - ((unsigned long long)ptx_vector.size()) % - print_money(total_fee); + prompt << fmt::format(tr("Sweeping {} in {} transactions for a total fee of {}. Is this okay? (Y/Yes/N/No): "), + print_money(total_sent), ptx_vector.size(), print_money(total_fee)); } else { - prompt << boost::format(tr("Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): ")) % - print_money(total_sent) % - print_money(total_fee); + prompt << fmt::format(tr("Sweeping {} for a total fee of {}. Is this okay? (Y/Yes/N/No): "), + print_money(total_sent), print_money(total_fee)); } std::string accepted = input_line(prompt.str()); if(std::cin.eof()) return true; if(!command_line::is_yes(accepted)) { - fail_msg_writer() << tr("transaction cancelled."); + GULPS_PRINT_FAIL(tr("transaction cancelled.")); return true; } @@ -4909,11 +4912,11 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "multisig_ryo_tx"); } } else if(m_wallet->watch_only()) @@ -4921,11 +4924,11 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a bool r = m_wallet->save_tx(ptx_vector, "unsigned_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "unsigned_ryo_tx"); } } else @@ -4939,8 +4942,8 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a } catch(...) { - LOG_ERROR("unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -4985,7 +4988,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) { if(!tools::wallet2::parse_payment_id(local_args.back(), pid)) { - fail_msg_writer() << tr("payment id has invalid format, expected 16 or 64 character hex string: ") << local_args.back(); + GULPS_PRINT_FAIL(tr("payment id has invalid format, expected 16 or 64 character hex string: "), local_args.back()); return true; } local_args.pop_back(); @@ -4993,21 +4996,21 @@ bool simple_wallet::sweep_single(const std::vector &args_) if(local_args.size() != 2) { - fail_msg_writer() << tr("usage: sweep_single [] []
[]"); + GULPS_PRINT_FAIL(tr("usage: sweep_single [] []
[]")); return true; } crypto::key_image ki; if(!epee::string_tools::hex_to_pod(local_args[0], ki)) { - fail_msg_writer() << tr("failed to parse key image"); + GULPS_PRINT_FAIL(tr("failed to parse key image")); return true; } cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, local_args[1])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } @@ -5015,7 +5018,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) { if(pid.zero == 0) { - fail_msg_writer() << tr("a single transaction cannot use more than one payment id: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("a single transaction cannot use more than one payment id: "), local_args[0]); return true; } @@ -5030,7 +5033,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) return true; if(!command_line::is_yes(accepted)) { - fail_msg_writer() << tr("transaction cancelled."); + GULPS_PRINT_FAIL(tr("transaction cancelled.")); // would like to return false, because no tx made, but everything else returns true // and I don't know what returning false might adversely affect. *sigh* @@ -5041,22 +5044,22 @@ bool simple_wallet::sweep_single(const std::vector &args_) try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0, + auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0, priority, pid.zero == 0 ? &pid : nullptr, m_trusted_daemon); if(ptx_vector.empty()) { - fail_msg_writer() << tr("No outputs found"); + GULPS_PRINT_FAIL(tr("No outputs found")); return true; } if(ptx_vector.size() > 1) { - fail_msg_writer() << tr("Multiple transactions are created, which is not supposed to happen"); + GULPS_PRINT_FAIL(tr("Multiple transactions are created, which is not supposed to happen")); return true; } if(ptx_vector[0].selected_transfers.size() != 1) { - fail_msg_writer() << tr("The transaction uses multiple or no inputs, which is not supposed to happen"); + GULPS_PRINT_FAIL(tr("The transaction uses multiple or no inputs, which is not supposed to happen")); return true; } @@ -5066,15 +5069,14 @@ bool simple_wallet::sweep_single(const std::vector &args_) std::ostringstream prompt; if(!print_ring_members(ptx_vector, prompt)) return true; - prompt << boost::format(tr("Sweeping %s for a total fee of %s. Is this okay? (Y/Yes/N/No): ")) % - print_money(total_sent) % - print_money(total_fee); + prompt << fmt::format(tr("Sweeping {} for a total fee of {}. Is this okay? (Y/Yes/N/No): "), + print_money(total_sent), print_money(total_fee)); std::string accepted = input_line(prompt.str()); if(std::cin.eof()) return true; if(!command_line::is_yes(accepted)) { - fail_msg_writer() << tr("transaction cancelled."); + GULPS_PRINT_FAIL(tr("transaction cancelled.")); return true; } @@ -5084,11 +5086,11 @@ bool simple_wallet::sweep_single(const std::vector &args_) bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "multisig_ryo_tx"); } } else if(m_wallet->watch_only()) @@ -5096,17 +5098,17 @@ bool simple_wallet::sweep_single(const std::vector &args_) bool r = m_wallet->save_tx(ptx_vector, "unsigned_ryo_tx"); if(!r) { - fail_msg_writer() << tr("Failed to write transaction(s) to file"); + GULPS_PRINT_FAIL(tr("Failed to write transaction(s) to file")); } else { - success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_ryo_tx"; + GULPS_PRINT_GREEN(tr("Unsigned transaction(s) successfully written to file: "), "unsigned_ryo_tx"); } } else { m_wallet->commit_tx(ptx_vector[0]); - success_msg_writer(true) << tr("Money successfully sent, transaction: ") << get_transaction_hash(ptx_vector[0].tx); + GULPS_PRINT_GREEN(tr("Money successfully sent, transaction: "), get_transaction_hash(ptx_vector[0].tx)); } } catch(const std::exception &e) @@ -5115,8 +5117,8 @@ bool simple_wallet::sweep_single(const std::vector &args_) } catch(...) { - LOG_ERROR("unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -5132,12 +5134,12 @@ bool simple_wallet::sweep_below(const std::vector &args_) uint64_t below = 0; if(args_.size() < 1) { - fail_msg_writer() << tr("missing threshold amount"); + GULPS_PRINT_FAIL(tr("missing threshold amount")); return true; } if(!cryptonote::parse_amount(below, args_[0])) { - fail_msg_writer() << tr("invalid amount threshold"); + GULPS_PRINT_FAIL(tr("invalid amount threshold")); return true; } return sweep_main(below, std::vector(++args_.begin(), args_.end())); @@ -5147,14 +5149,14 @@ bool simple_wallet::donate(const std::vector &args_) { if(m_wallet->nettype() != cryptonote::MAINNET) { - fail_msg_writer() << tr("donations are not enabled on the testnet or on the stagenet"); + GULPS_PRINT_FAIL(tr("donations are not enabled on the testnet or on the stagenet")); return true; } std::vector local_args = args_; if(local_args.empty() || local_args.size() > 5) { - fail_msg_writer() << tr("usage: donate [index=[,,...]] [] [] []"); + GULPS_PRINT_FAIL(tr("usage: donate [index=[,,...]] [] [] []")); return true; } std::string amount_str; @@ -5174,7 +5176,7 @@ bool simple_wallet::donate(const std::vector &args_) local_args.push_back(amount_str); if(!payment_id_str.empty()) local_args.push_back(payment_id_str); - message_writer() << tr("Donating ") << amount_str << " to The Ryo Currency Project (" << common_config::RYO_DONATION_ADDR << ")."; + GULPS_PRINT_OK(tr("Donating "), amount_str, " to The Ryo Currency Project (", common_config::RYO_DONATION_ADDR, ")."); transfer_new(local_args); return true; } @@ -5229,12 +5231,12 @@ bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, auto it = dests.find(cd.change_dts.addr); if(it == dests.end()) { - fail_msg_writer() << tr("Claimed change does not go to a paid address"); + GULPS_PRINT_FAIL(tr("Claimed change does not go to a paid address")); return false; } if(it->second.second < cd.change_dts.amount) { - fail_msg_writer() << tr("Claimed change is larger than payment to the change address"); + GULPS_PRINT_FAIL(tr("Claimed change is larger than payment to the change address")); return false; } if(cd.change_dts.amount > 0) @@ -5243,7 +5245,7 @@ bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, first_known_non_zero_change_index = n; if(memcmp(&cd.change_dts.addr, &get_tx(first_known_non_zero_change_index).change_dts.addr, sizeof(cd.change_dts.addr))) { - fail_msg_writer() << tr("Change goes to more than one address"); + GULPS_PRINT_FAIL(tr("Change goes to more than one address")); return false; } } @@ -5262,7 +5264,7 @@ bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, { if(!dest_string.empty()) dest_string += ", "; - dest_string += (boost::format(tr("sending %s to %s")) % print_money(i->second.second) % i->second.first).str(); + dest_string += fmt::format(tr("sending {} to {}"), print_money(i->second.second), i->second.first); } else ++n_dummy_outputs; @@ -5281,7 +5283,7 @@ bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, if(change > 0) { std::string address = get_public_address_as_str(m_wallet->nettype(), get_tx(0).subaddr_account > 0, get_tx(0).change_dts.addr); - change_string += (boost::format(tr("%s change to %s")) % print_money(change) % address).str(); + change_string += fmt::format(tr("{} change to {}"), print_money(change), address); } else change_string += tr("no change"); @@ -5295,7 +5297,7 @@ bool simple_wallet::accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs) { std::string extra_message; if(!txs.transfers.empty()) - extra_message = (boost::format("%u outputs to import. ") % (unsigned)txs.transfers.size()).str(); + extra_message = fmt::format(tr("{} outputs to import. "), txs.transfers.size()); return accept_loaded_tx([&txs]() { return txs.txes.size(); }, [&txs](size_t n) -> const tools::wallet2::tx_construction_data & { return txs.txes[n]; }, extra_message); } //---------------------------------------------------------------------------------------------------- @@ -5303,7 +5305,7 @@ bool simple_wallet::accept_loaded_tx(const tools::wallet2::signed_tx_set &txs) { std::string extra_message; if(!txs.key_images.empty()) - extra_message = (boost::format("%u key images to import. ") % (unsigned)txs.key_images.size()).str(); + extra_message = fmt::format(tr("{} key images to import. "), txs.key_images.size()); return accept_loaded_tx([&txs]() { return txs.ptx.size(); }, [&txs](size_t n) -> const tools::wallet2::tx_construction_data & { return txs.ptx[n].construction_data; }, extra_message); } //---------------------------------------------------------------------------------------------------- @@ -5311,22 +5313,22 @@ bool simple_wallet::sign_transfer(const std::vector &args_) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(m_wallet->multisig()) { - fail_msg_writer() << tr("This is a multisig wallet, it can only sign with sign_multisig"); + GULPS_PRINT_FAIL(tr("This is a multisig wallet, it can only sign with sign_multisig")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("This is a watch only wallet"); + GULPS_PRINT_FAIL(tr("This is a watch only wallet")); return true; } if(args_.size() > 1 || (args_.size() == 1 && args_[0] != "export")) { - fail_msg_writer() << tr("usage: sign_transfer [export]"); + GULPS_PRINT_FAIL(tr("usage: sign_transfer [export]")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -5341,13 +5343,13 @@ bool simple_wallet::sign_transfer(const std::vector &args_) bool r = m_wallet->sign_tx("unsigned_ryo_tx", "signed_ryo_tx", ptx, [&](const tools::wallet2::unsigned_tx_set &tx) { return accept_loaded_tx(tx); }, export_raw); if(!r) { - fail_msg_writer() << tr("Failed to sign transaction"); + GULPS_PRINT_FAIL(tr("Failed to sign transaction")); return true; } } catch(const std::exception &e) { - fail_msg_writer() << tr("Failed to sign transaction: ") << e.what(); + GULPS_PRINT_FAIL(tr("Failed to sign transaction: "), e.what()); return true; } @@ -5358,8 +5360,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) txids_as_text += (", "); txids_as_text += epee::string_tools::pod_to_hex(get_transaction_hash(t.tx)); } - success_msg_writer(true) << tr("Transaction successfully signed to file ") << "signed_ryo_tx" - << ", txid " << txids_as_text; + GULPS_PRINT_GREEN(tr("Transaction successfully signed to file "), "signed_ryo_tx", ", txid ", txids_as_text); if(export_raw) { std::string rawfiles_as_text; @@ -5369,7 +5370,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) rawfiles_as_text += ", "; rawfiles_as_text += "signed_ryo_tx_raw" + (ptx.size() == 1 ? "" : ("_" + std::to_string(i))); } - success_msg_writer(true) << tr("Transaction raw hex data exported to ") << rawfiles_as_text; + GULPS_PRINT_GREEN(tr("Transaction raw hex data exported to "), rawfiles_as_text); } return true; } @@ -5378,7 +5379,7 @@ bool simple_wallet::submit_transfer(const std::vector &args_) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(!try_connect_to_daemon()) @@ -5390,7 +5391,7 @@ bool simple_wallet::submit_transfer(const std::vector &args_) bool r = m_wallet->load_tx("signed_ryo_tx", ptx_vector, [&](const tools::wallet2::signed_tx_set &tx) { return accept_loaded_tx(tx); }); if(!r) { - fail_msg_writer() << tr("Failed to load transaction from file"); + GULPS_PRINT_FAIL(tr("Failed to load transaction from file")); return true; } @@ -5402,8 +5403,8 @@ bool simple_wallet::submit_transfer(const std::vector &args_) } catch(...) { - LOG_ERROR("Unknown error"); - fail_msg_writer() << tr("unknown error"); + GULPS_LOG_ERROR("Unknown error"); + GULPS_PRINT_FAIL(tr("unknown error")); } return true; @@ -5415,12 +5416,12 @@ bool simple_wallet::get_tx_key(const std::vector &args_) if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(local_args.size() != 1) { - fail_msg_writer() << tr("usage: get_tx_key "); + GULPS_PRINT_FAIL(tr("usage: get_tx_key ")); return true; } if(m_wallet->ask_password() && !get_and_verify_password()) @@ -5431,7 +5432,7 @@ bool simple_wallet::get_tx_key(const std::vector &args_) crypto::hash txid; if(!epee::string_tools::hex_to_pod(local_args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } @@ -5445,12 +5446,12 @@ bool simple_wallet::get_tx_key(const std::vector &args_) oss << epee::string_tools::pod_to_hex(tx_key); for(size_t i = 0; i < additional_tx_keys.size(); ++i) oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); - success_msg_writer() << tr("Tx key: ") << oss.str(); + GULPS_PRINT_OK(tr("Tx key: "), oss.str()); return true; } else { - fail_msg_writer() << tr("no tx keys found for this txid"); + GULPS_PRINT_FAIL(tr("no tx keys found for this txid")); return true; } } @@ -5459,26 +5460,26 @@ bool simple_wallet::get_tx_proof(const std::vector &args) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(args.size() != 2 && args.size() != 3) { - fail_msg_writer() << tr("usage: get_tx_proof
[]"); + GULPS_PRINT_FAIL(tr("usage: get_tx_proof
[]")); return true; } crypto::hash txid; if(!epee::string_tools::hex_to_pod(args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, args[1])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } @@ -5492,13 +5493,13 @@ bool simple_wallet::get_tx_proof(const std::vector &args) std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : ""); const std::string filename = "ryo_tx_proof"; if(epee::file_io_utils::save_string_to_file(filename, sig_str)) - success_msg_writer() << tr("signature file saved to: ") << filename; + GULPS_PRINT_OK(tr("signature file saved to: "), filename); else - fail_msg_writer() << tr("failed to save signature file"); + GULPS_PRINT_FAIL(tr("failed to save signature file")); } catch(const std::exception &e) { - fail_msg_writer() << tr("error: ") << e.what(); + GULPS_PRINT_FAIL(tr("error: "), e.what()); } return true; } @@ -5509,7 +5510,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) if(local_args.size() != 3) { - fail_msg_writer() << tr("usage: check_tx_key
"); + GULPS_PRINT_FAIL(tr("usage: check_tx_key
")); return true; } @@ -5518,13 +5519,13 @@ bool simple_wallet::check_tx_key(const std::vector &args_) if(!m_wallet) { - fail_msg_writer() << tr("wallet is null"); + GULPS_PRINT_FAIL(tr("wallet is null")); return true; } crypto::hash txid; if(!epee::string_tools::hex_to_pod(local_args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } @@ -5532,7 +5533,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) std::vector additional_tx_keys; if(!epee::string_tools::hex_to_pod(local_args[1].substr(0, 64), tx_key)) { - fail_msg_writer() << tr("failed to parse tx key"); + GULPS_PRINT_FAIL(tr("failed to parse tx key")); return true; } local_args[1] = local_args[1].substr(64); @@ -5541,7 +5542,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) additional_tx_keys.resize(additional_tx_keys.size() + 1); if(!epee::string_tools::hex_to_pod(local_args[1].substr(0, 64), additional_tx_keys.back())) { - fail_msg_writer() << tr("failed to parse tx key"); + GULPS_PRINT_FAIL(tr("failed to parse tx key")); return true; } local_args[1] = local_args[1].substr(64); @@ -5550,7 +5551,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, local_args[2])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } @@ -5563,31 +5564,31 @@ bool simple_wallet::check_tx_key(const std::vector &args_) if(received > 0) { - success_msg_writer() << get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; + GULPS_PRINT_OK(get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address), " ", tr("received"), " ", print_money(received), " ", tr("in txid"), " ", txid); if(in_pool) { - success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!"); + GULPS_PRINT_OK(tr("WARNING: this transaction is not yet included in the blockchain!")); } else { if(confirmations != (uint64_t)-1) { - success_msg_writer() << boost::format(tr("This transaction has %u confirmations")) % confirmations; + GULPSF_PRINT_OK(tr("This transaction has {} confirmations"), confirmations); } else { - success_msg_writer() << tr("WARNING: failed to determine number of confirmations!"); + GULPS_PRINT_OK(tr("WARNING: failed to determine number of confirmations!")); } } } else { - fail_msg_writer() << get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; + GULPS_PRINT_FAIL(get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address), " ", tr("received nothing in txid"), " ", txid); } } catch(const std::exception &e) { - fail_msg_writer() << tr("error: ") << e.what(); + GULPS_PRINT_FAIL(tr("error: "), e.what()); } return true; } @@ -5596,7 +5597,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) { if(args.size() != 3 && args.size() != 4) { - fail_msg_writer() << tr("usage: check_tx_proof
[]"); + GULPS_PRINT_FAIL(tr("usage: check_tx_proof
[]")); return true; } @@ -5607,7 +5608,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) crypto::hash txid; if(!epee::string_tools::hex_to_pod(args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } @@ -5615,7 +5616,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, args[1])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } @@ -5623,7 +5624,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) std::string sig_str; if(!epee::file_io_utils::load_file_to_string(args[2], sig_str)) { - fail_msg_writer() << tr("failed to load signature file"); + GULPS_PRINT_FAIL(tr("failed to load signature file")); return true; } @@ -5634,39 +5635,39 @@ bool simple_wallet::check_tx_proof(const std::vector &args) uint64_t confirmations; if(m_wallet->check_tx_proof(txid, info.address, info.is_subaddress, args.size() == 4 ? args[3] : "", sig_str, received, in_pool, confirmations)) { - success_msg_writer() << tr("Good signature"); + GULPS_PRINT_OK(tr("Good signature")); if(received > 0) { - success_msg_writer() << get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received") << " " << print_money(received) << " " << tr("in txid") << " " << txid; + GULPS_PRINT_OK(get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address), " ", tr("received"), " ", print_money(received), " ", tr("in txid"), " ", txid); if(in_pool) { - success_msg_writer() << tr("WARNING: this transaction is not yet included in the blockchain!"); + GULPS_PRINT_OK(tr("WARNING: this transaction is not yet included in the blockchain!")); } else { if(confirmations != (uint64_t)-1) { - success_msg_writer() << boost::format(tr("This transaction has %u confirmations")) % confirmations; + GULPSF_PRINT_OK(tr("This transaction has {} confirmations"), confirmations); } else { - success_msg_writer() << tr("WARNING: failed to determine number of confirmations!"); + GULPS_PRINT_OK(tr("WARNING: failed to determine number of confirmations!")); } } } else { - fail_msg_writer() << get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address) << " " << tr("received nothing in txid") << " " << txid; + GULPS_PRINT_FAIL(get_public_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address), " ", tr("received nothing in txid"), " ", txid); } } else { - fail_msg_writer() << tr("Bad signature"); + GULPS_PRINT_FAIL(tr("Bad signature")); } } catch(const std::exception &e) { - fail_msg_writer() << tr("error: ") << e.what(); + GULPS_PRINT_FAIL(tr("error: "), e.what()); } return true; } @@ -5675,31 +5676,31 @@ bool simple_wallet::get_spend_proof(const std::vector &args) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(args.size() != 1 && args.size() != 2) { - fail_msg_writer() << tr("usage: get_spend_proof []"); + GULPS_PRINT_FAIL(tr("usage: get_spend_proof []")); return true; } if(m_wallet->watch_only()) { - fail_msg_writer() << tr("wallet is watch-only and cannot generate the proof"); + GULPS_PRINT_FAIL(tr("wallet is watch-only and cannot generate the proof")); return true; } crypto::hash txid; if(!epee::string_tools::hex_to_pod(args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } if(!try_connect_to_daemon()) { - fail_msg_writer() << tr("failed to connect to the daemon"); + GULPS_PRINT_FAIL(tr("failed to connect to the daemon")); return true; } @@ -5713,13 +5714,13 @@ bool simple_wallet::get_spend_proof(const std::vector &args) const std::string sig_str = m_wallet->get_spend_proof(txid, args.size() == 2 ? args[1] : ""); const std::string filename = "ryo_spend_proof"; if(epee::file_io_utils::save_string_to_file(filename, sig_str)) - success_msg_writer() << tr("signature file saved to: ") << filename; + GULPS_PRINT_OK(tr("signature file saved to: "), filename); else - fail_msg_writer() << tr("failed to save signature file"); + GULPS_PRINT_FAIL(tr("failed to save signature file")); } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } return true; } @@ -5728,40 +5729,40 @@ bool simple_wallet::check_spend_proof(const std::vector &args) { if(args.size() != 2 && args.size() != 3) { - fail_msg_writer() << tr("usage: check_spend_proof []"); + GULPS_PRINT_FAIL(tr("usage: check_spend_proof []")); return true; } crypto::hash txid; if(!epee::string_tools::hex_to_pod(args[0], txid)) { - fail_msg_writer() << tr("failed to parse txid"); + GULPS_PRINT_FAIL(tr("failed to parse txid")); return true; } if(!try_connect_to_daemon()) { - fail_msg_writer() << tr("failed to connect to the daemon"); + GULPS_PRINT_FAIL(tr("failed to connect to the daemon")); return true; } std::string sig_str; if(!epee::file_io_utils::load_file_to_string(args[1], sig_str)) { - fail_msg_writer() << tr("failed to load signature file"); + GULPS_PRINT_FAIL(tr("failed to load signature file")); return true; } try { if(m_wallet->check_spend_proof(txid, args.size() == 3 ? args[2] : "", sig_str)) - success_msg_writer() << tr("Good signature"); + GULPS_PRINT_OK(tr("Good signature")); else - fail_msg_writer() << tr("Bad signature"); + GULPS_PRINT_FAIL(tr("Bad signature")); } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } return true; } @@ -5770,18 +5771,18 @@ bool simple_wallet::get_reserve_proof(const std::vector &args) { if(m_wallet->key_on_device()) { - fail_msg_writer() << tr("command not supported by HW wallet"); + GULPS_PRINT_FAIL(tr("command not supported by HW wallet")); return true; } if(args.size() != 1 && args.size() != 2) { - fail_msg_writer() << tr("usage: get_reserve_proof (all|) []"); + GULPS_PRINT_FAIL(tr("usage: get_reserve_proof (all|) []")); return true; } if(m_wallet->watch_only() || m_wallet->multisig()) { - fail_msg_writer() << tr("The reserve proof can be generated only by a full wallet"); + GULPS_PRINT_FAIL(tr("The reserve proof can be generated only by a full wallet")); return true; } @@ -5792,14 +5793,14 @@ bool simple_wallet::get_reserve_proof(const std::vector &args) account_minreserve->first = m_current_subaddress_account; if(!cryptonote::parse_amount(account_minreserve->second, args[0])) { - fail_msg_writer() << tr("amount is wrong: ") << args[0]; + GULPS_PRINT_FAIL(tr("amount is wrong: "), args[0]); return true; } } if(!try_connect_to_daemon()) { - fail_msg_writer() << tr("failed to connect to the daemon"); + GULPS_PRINT_FAIL(tr("failed to connect to the daemon")); return true; } @@ -5815,13 +5816,13 @@ bool simple_wallet::get_reserve_proof(const std::vector &args) const std::string sig_str = m_wallet->get_reserve_proof(account_minreserve, args.size() == 2 ? args[1] : ""); const std::string filename = "ryo_reserve_proof"; if(epee::file_io_utils::save_string_to_file(filename, sig_str)) - success_msg_writer() << tr("signature file saved to: ") << filename; + GULPS_PRINT_OK(tr("signature file saved to: "), filename); else - fail_msg_writer() << tr("failed to save signature file"); + GULPS_PRINT_FAIL(tr("failed to save signature file")); } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } return true; } @@ -5830,32 +5831,32 @@ bool simple_wallet::check_reserve_proof(const std::vector &args) { if(args.size() != 2 && args.size() != 3) { - fail_msg_writer() << tr("usage: check_reserve_proof
[]"); + GULPS_PRINT_FAIL(tr("usage: check_reserve_proof
[]")); return true; } if(!try_connect_to_daemon()) { - fail_msg_writer() << tr("failed to connect to the daemon"); + GULPS_PRINT_FAIL(tr("failed to connect to the daemon")); return true; } cryptonote::address_parse_info info; if(!cryptonote::get_account_address_from_str(m_wallet->nettype(), info, args[0])) { - fail_msg_writer() << tr("failed to parse address"); + GULPS_PRINT_FAIL(tr("failed to parse address")); return true; } if(info.is_subaddress) { - fail_msg_writer() << tr("Address must not be a subaddress"); + GULPS_PRINT_FAIL(tr("Address must not be a subaddress")); return true; } std::string sig_str; if(!epee::file_io_utils::load_file_to_string(args[1], sig_str)) { - fail_msg_writer() << tr("failed to load signature file"); + GULPS_PRINT_FAIL(tr("failed to load signature file")); return true; } @@ -5866,16 +5867,16 @@ bool simple_wallet::check_reserve_proof(const std::vector &args) uint64_t total, spent; if(m_wallet->check_reserve_proof(info.address, args.size() == 3 ? args[2] : "", sig_str, total, spent)) { - success_msg_writer() << boost::format(tr("Good signature -- total: %s, spent: %s, unspent: %s")) % print_money(total) % print_money(spent) % print_money(total - spent); + GULPSF_PRINT_OK(tr("Good signature -- total: {}, spent: {}, unspent: {}"), print_money(total), print_money(spent), print_money(total - spent)); } else { - fail_msg_writer() << tr("Bad signature"); + GULPS_PRINT_FAIL(tr("Bad signature")); } } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } return true; } @@ -5901,25 +5902,6 @@ static std::string get_human_readable_timestamp(uint64_t ts) return std::string(buffer); } //---------------------------------------------------------------------------------------------------- -#if 0 -// Not used anymore -static std::string get_human_readable_timespan(std::chrono::seconds seconds) -{ - uint64_t ts = seconds.count(); - if(ts < 60) - return std::to_string(ts) + tr(" seconds"); - if(ts < 3600) - return std::to_string((uint64_t)(ts / 60)) + tr(" minutes"); - if(ts < 3600 * 24) - return std::to_string((uint64_t)(ts / 3600)) + tr(" hours"); - if(ts < 3600 * 24 * 30.5) - return std::to_string((uint64_t)(ts / (3600 * 24))) + tr(" days"); - if(ts < 3600 * 24 * 365.25) - return std::to_string((uint64_t)(ts / (3600 * 24 * 365.25))) + tr(" months"); - return tr("a long time"); -} -#endif -//---------------------------------------------------------------------------------------------------- bool simple_wallet::show_transfers(const std::vector &args_) { std::vector local_args = args_; @@ -5934,7 +5916,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) if(local_args.size() > 4) { - fail_msg_writer() << tr("usage: show_transfers [in|out|all|pending|failed] [index=[,,...]] [ []]"); + GULPS_PRINT_FAIL(tr("usage: show_transfers [in|out|all|pending|failed] [index=[,,...]] [ []]")); return true; } @@ -5992,7 +5974,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("bad min_height parameter:") << " " << local_args[0]; + GULPS_PRINT_FAIL(tr("bad min_height parameter:"), " ", local_args[0]); return true; } local_args.erase(local_args.begin()); @@ -6007,7 +5989,7 @@ bool simple_wallet::show_transfers(const std::vector &args_) } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("bad max_height parameter:") << " " << local_args[0]; + GULPS_PRINT_FAIL(tr("bad max_height parameter:"), " ", local_args[0]); return true; } local_args.erase(local_args.begin()); @@ -6028,7 +6010,8 @@ bool simple_wallet::show_transfers(const std::vector &args_) if(payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0, 16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); - output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%16.16s %20.20s %s %s %d %s %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); + output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, fmt::format("{:>16} {:>20} {} {} {} - {}", + get_human_readable_timestamp(pd.m_timestamp), print_money(pd.m_amount), string_tools::pod_to_hex(pd.m_tx_hash), payment_id, pd.m_subaddr_index.minor, note)))); } } @@ -6063,15 +6046,16 @@ bool simple_wallet::show_transfers(const std::vector &args_) if(payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0, 16); std::string note = m_wallet->get_tx_note(i->first); - output.insert(std::make_pair(pd.m_block_height, std::make_pair(false, (boost::format("%16.16s %20.20s %s %s %14.14s %s %s - %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); + output.insert(std::make_pair(pd.m_block_height, std::make_pair(false, fmt::format("{:>16} {:>20} {} {} {:>14} {} {} - {}", + get_human_readable_timestamp(pd.m_timestamp), print_money(pd.m_amount_in - change - fee), string_tools::pod_to_hex(i->first), + payment_id, print_money(fee), dests, print_subaddr_indices(pd.m_subaddr_indices), note)))); } } // print in and out sorted by height for(std::map>::const_iterator i = output.begin(); i != output.end(); ++i) { - message_writer(i->second.first ? console_color_green : console_color_magenta, false) << boost::format("%8.8llu %6.6s %s") % - ((unsigned long long)i->first) % (i->second.first ? tr("in") : tr("out")) % i->second.second; + GULPSF_PRINT_CLR(i->second.first ? gulps::COLOR_GREEN : gulps::COLOR_MAGENTA, "{:>8} {:>6} {}", i->first, i->second.first ? tr("in") : tr("out"), i->second.second); } if(pool) @@ -6091,12 +6075,13 @@ bool simple_wallet::show_transfers(const std::vector &args_) std::string double_spend_note; if(i->second.m_double_spend_seen) double_spend_note = tr("[Double spend seen on the network: this transaction may or may not end up being mined] "); - message_writer() << (boost::format("%8.8s %6.6s %16.16s %20.20s %s %s %d %s %s%s") % "pool" % "in" % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note % double_spend_note).str(); + GULPSF_PRINT_OK("{:>8s} {:>6s} {:>16s} {:>20s} {} {} {} {} {}{}", "pool", "in", get_human_readable_timestamp(pd.m_timestamp), + print_money(pd.m_amount), string_tools::pod_to_hex(pd.m_tx_hash), payment_id, pd.m_subaddr_index.minor, "-", note, double_spend_note); } } catch(const std::exception &e) { - fail_msg_writer() << "Failed to get pool state:" << e.what(); + GULPS_PRINT_FAIL("Failed to get pool state:", e.what()); } } @@ -6117,7 +6102,9 @@ bool simple_wallet::show_transfers(const std::vector &args_) bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; if((failed && is_failed) || (!is_failed && pending)) { - message_writer() << (boost::format("%8.8s %6.6s %16.16s %20.20s %s %s %14.14s %s - %s") % (is_failed ? tr("failed") : tr("pending")) % tr("out") % get_human_readable_timestamp(pd.m_timestamp) % print_money(amount - pd.m_change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % print_subaddr_indices(pd.m_subaddr_indices) % note).str(); + GULPSF_PRINT_OK("{:>8s} {:>6s} {:>16s} {:>20s} {} {} {:>14s} {} - {}", (is_failed ? tr("failed") : tr("pending")), tr("out"), + get_human_readable_timestamp(pd.m_timestamp), print_money(amount - pd.m_change - fee), string_tools::pod_to_hex(i->first), + payment_id, print_money(fee), print_subaddr_indices(pd.m_subaddr_indices), note); } } } @@ -6129,7 +6116,7 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) { if(args_.size() > 3) { - fail_msg_writer() << tr("usage: unspent_outputs [index=[,,...]] [ []]"); + GULPS_PRINT_FAIL(tr("usage: unspent_outputs [index=[,,...]] [ []]")); return true; } auto local_args = args_; @@ -6148,7 +6135,7 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) { if(!cryptonote::parse_amount(min_amount, local_args[0])) { - fail_msg_writer() << tr("amount is wrong: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("amount is wrong: "), local_args[0]); return true; } local_args.erase(local_args.begin()); @@ -6156,14 +6143,14 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) { if(!cryptonote::parse_amount(max_amount, local_args[0])) { - fail_msg_writer() << tr("amount is wrong: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("amount is wrong: "), local_args[0]); return true; } local_args.erase(local_args.begin()); } if(min_amount > max_amount) { - fail_msg_writer() << tr(" should be smaller than "); + GULPS_PRINT_FAIL(tr(" should be smaller than ")); return true; } } @@ -6193,27 +6180,28 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) } if(amount_to_tds.empty()) { - success_msg_writer() << tr("There is no unspent output in the specified address"); + GULPS_PRINT_OK(tr("There is no unspent output in the specified address")); return true; } for(const auto &amount_tds : amount_to_tds) { auto &tds = amount_tds.second; - success_msg_writer() << tr("\nAmount: ") << print_money(amount_tds.first) << tr(", number of keys: ") << tds.size(); + GULPS_PRINT_OK(tr("\nAmount: "), print_money(amount_tds.first), tr(", number of keys: "), tds.size()); for(size_t i = 0; i < tds.size();) { std::ostringstream oss; for(size_t j = 0; j < 8 && i < tds.size(); ++i, ++j) oss << tds[i].m_block_height << tr(" "); - success_msg_writer() << oss.str(); + GULPS_PRINT_OK(oss.str()); } } - success_msg_writer() - << tr("\nMin block height: ") << min_height - << tr("\nMax block height: ") << max_height - << tr("\nMin amount found: ") << print_money(found_min_amount) - << tr("\nMax amount found: ") << print_money(found_max_amount) - << tr("\nTotal count: ") << count; + + GULPS_PRINT_OK(tr("\nMin block height: "), min_height, + tr("\nMax block height: "), max_height, + tr("\nMin amount found: "), print_money(found_min_amount), + tr("\nMax amount found: "), print_money(found_max_amount), + tr("\nTotal count: "), count); + const size_t histogram_height = 10; const size_t histogram_width = 50; double bin_size = (max_height - min_height + 1.0) / histogram_width; @@ -6252,9 +6240,8 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) double count_per_star = max_bin_count / (double)histogram_height; if(count_per_star < 1) count_per_star = 1; - success_msg_writer() - << tr("\nBin size: ") << bin_size - << tr("\nOutputs per *: ") << count_per_star; + GULPS_PRINT_OK(tr("\nBin size: "), bin_size, + tr("\nOutputs per *: "), count_per_star); ostringstream histogram_str; histogram_str << tr("count\n ^\n"); for(size_t y = histogram_height; y > 0; --y) @@ -6263,7 +6250,7 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) << tr(" +") << std::string(histogram_width, '-') << tr("+--> block height\n") << tr(" ^") << std::string(histogram_width - 2, ' ') << tr("^\n") << tr(" ") << min_height << std::string(histogram_width - 8, ' ') << max_height; - success_msg_writer() << histogram_str.str(); + GULPS_PRINT_OK(histogram_str.str()); return true; } //---------------------------------------------------------------------------------------------------- @@ -6272,7 +6259,7 @@ bool simple_wallet::rescan_blockchain(const std::vector &args_) uint64_t start_height = 0u; if(args_.size() >= 2u) { - fail_msg_writer() << tr("Too much arguments passed - usage: rescan_bc [start_height]"); + GULPS_PRINT_FAIL(tr("Too much arguments passed - usage: rescan_bc [start_height]")); return true; } if(args_.size() == 1u) @@ -6283,15 +6270,15 @@ bool simple_wallet::rescan_blockchain(const std::vector &args_) } catch(const boost::bad_lexical_cast &) { - fail_msg_writer() << tr("bad rescan_br parameter:") << " " << args_[0]; + GULPS_PRINT_FAIL(tr("bad rescan_br parameter:"), " ", args_[0]); return true; } } if(!args_.empty() && start_height > m_wallet->get_refresh_from_block_height()) { // a scan from a height greater than the wallets refresh_from_block_height can result into a wrong balance - fail_msg_writer() << tr("You can not start a rescan from a height after you wallet was created. 'start_height' must be lesser or equal to ") << - m_wallet->get_refresh_from_block_height(); + GULPS_PRINT_FAIL(tr("You can not start a rescan from a height after you wallet was created. 'start_height' must be lesser or equal to "), + m_wallet->get_refresh_from_block_height()); return true; } @@ -6350,7 +6337,7 @@ bool simple_wallet::run() m_auto_refresh_enabled = m_wallet->auto_refresh(); m_idle_thread = boost::thread([&] { wallet_idle_thread(); }); - message_writer(console_color_green, false) << "Background refresh thread started"; + GULPS_PRINT_GREEN(tr("Background refresh thread started")); return m_cmd_binder.run_handling([this]() { return get_prompt(); }, ""); } //---------------------------------------------------------------------------------------------------- @@ -6405,12 +6392,12 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto uint32_t index_major; if(!epee::string_tools::get_xtype_from_string(index_major, local_args[0])) { - fail_msg_writer() << tr("failed to parse index: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("failed to parse index: "), local_args[0]); return true; } if(index_major >= m_wallet->get_num_subaddress_accounts()) { - fail_msg_writer() << tr("specify an index between 0 and ") << (m_wallet->get_num_subaddress_accounts() - 1); + GULPS_PRINT_FAIL(tr("specify an index between 0 and "), (m_wallet->get_num_subaddress_accounts() - 1)); return true; } m_current_subaddress_account = index_major; @@ -6423,7 +6410,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto uint32_t index_major; if(!epee::string_tools::get_xtype_from_string(index_major, local_args[0])) { - fail_msg_writer() << tr("failed to parse index: ") << local_args[0]; + GULPS_PRINT_FAIL(tr("failed to parse index: "), local_args[0]); return true; } local_args.erase(local_args.begin()); @@ -6436,7 +6423,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } } else if(command == "tag" && local_args.size() >= 2) @@ -6448,7 +6435,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto uint32_t account_index; if(!epee::string_tools::get_xtype_from_string(account_index, local_args[i])) { - fail_msg_writer() << tr("failed to parse index: ") << local_args[i]; + GULPS_PRINT_FAIL(tr("failed to parse index: "), local_args[i]); return true; } account_indices.insert(account_index); @@ -6460,7 +6447,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } } else if(command == "untag" && local_args.size() >= 1) @@ -6471,7 +6458,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto uint32_t account_index; if(!epee::string_tools::get_xtype_from_string(account_index, local_args[i])) { - fail_msg_writer() << tr("failed to parse index: ") << local_args[i]; + GULPS_PRINT_FAIL(tr("failed to parse index: "), local_args[i]); return true; } account_indices.insert(account_index); @@ -6483,7 +6470,7 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } } else if(command == "tag_description" && local_args.size() >= 1) @@ -6502,19 +6489,19 @@ bool simple_wallet::account(const std::vector &args /* = std::vecto } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); } } else { - fail_msg_writer() << tr("usage:\n" + GULPS_PRINT_FAIL(tr("usage:\n" " account\n" " account new