From d4e25f8322b199dc8c1d519832aff1f879a7f6c6 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Fri, 1 Feb 2019 16:28:29 +0000 Subject: [PATCH 01/56] Update Ryo copyright notices --- CMakeLists.txt | 4 ++-- LICENSE | 4 ++-- src/CMakeLists.txt | 4 ++-- src/address_validator/CMakeLists.txt | 4 ++-- src/address_validator/address_validator.cpp | 4 ++-- src/address_validator/address_validator.h | 4 ++-- src/address_validator/writer.cpp | 4 ++-- src/address_validator/writer.h | 4 ++-- src/blockchain_db/CMakeLists.txt | 4 ++-- src/blockchain_db/berkeleydb/db_bdb.cpp | 4 ++-- src/blockchain_db/berkeleydb/db_bdb.h | 4 ++-- src/blockchain_db/blockchain_db.cpp | 4 ++-- src/blockchain_db/blockchain_db.h | 4 ++-- src/blockchain_db/db_types.h | 4 ++-- src/blockchain_db/lmdb/db_lmdb.cpp | 4 ++-- src/blockchain_db/lmdb/db_lmdb.h | 4 ++-- src/blockchain_utilities/CMakeLists.txt | 4 ++-- src/blockchain_utilities/blockchain_blackball.cpp | 4 ++-- src/blockchain_utilities/blockchain_export.cpp | 4 ++-- src/blockchain_utilities/blockchain_import.cpp | 4 ++-- src/blockchain_utilities/blockchain_usage.cpp | 4 ++-- src/blockchain_utilities/blockchain_utilities.h | 4 ++-- src/blockchain_utilities/blocksdat_file.cpp | 4 ++-- src/blockchain_utilities/blocksdat_file.h | 4 ++-- src/blockchain_utilities/bootstrap_file.cpp | 4 ++-- src/blockchain_utilities/bootstrap_file.h | 4 ++-- src/blockchain_utilities/bootstrap_serialization.h | 4 ++-- src/blocks/CMakeLists.txt | 4 ++-- src/checkpoints/CMakeLists.txt | 4 ++-- src/checkpoints/checkpoints.cpp | 4 ++-- src/checkpoints/checkpoints.h | 4 ++-- src/common/CMakeLists.txt | 4 ++-- src/common/apply_permutation.h | 4 ++-- src/common/base58.cpp | 4 ++-- src/common/base58.h | 4 ++-- src/common/boost_locale.cpp | 4 ++-- src/common/boost_locale.hpp | 4 ++-- src/common/boost_serialization_helper.h | 4 ++-- src/common/command_line.cpp | 4 ++-- src/common/command_line.h | 4 ++-- src/common/common_fwd.h | 4 ++-- src/common/dns_utils.cpp | 4 ++-- src/common/dns_utils.h | 4 ++-- src/common/download.cpp | 4 ++-- src/common/download.h | 4 ++-- src/common/http_connection.h | 4 ++-- src/common/i18n.cpp | 4 ++-- src/common/i18n.h | 4 ++-- src/common/int-util.h | 4 ++-- src/common/json_util.h | 4 ++-- src/common/password.cpp | 4 ++-- src/common/password.h | 4 ++-- src/common/perf_timer.cpp | 4 ++-- src/common/perf_timer.h | 4 ++-- src/common/rpc_client.h | 4 ++-- src/common/scoped_message_writer.h | 4 ++-- src/common/sfinae_helpers.h | 4 ++-- src/common/stack_trace.cpp | 4 ++-- src/common/stack_trace.h | 4 ++-- src/common/threadpool.cpp | 4 ++-- src/common/threadpool.h | 4 ++-- src/common/unordered_containers_boost_serialization.h | 4 ++-- src/common/updates.cpp | 4 ++-- src/common/updates.h | 4 ++-- src/common/util.cpp | 4 ++-- src/common/util.h | 4 ++-- src/common/varint.h | 4 ++-- src/crypto/CMakeLists.txt | 4 ++-- src/crypto/chacha.h | 4 ++-- src/crypto/crypto-ops-data.c | 4 ++-- src/crypto/crypto-ops.c | 4 ++-- src/crypto/crypto-ops.h | 4 ++-- src/crypto/crypto.cpp | 4 ++-- src/crypto/crypto.h | 4 ++-- src/crypto/crypto_ops_builder/crypto-ops-data.c | 4 ++-- src/crypto/crypto_ops_builder/crypto-ops-old.c | 4 ++-- src/crypto/crypto_ops_builder/crypto-ops.h | 4 ++-- .../ref10CommentedCombined/MakeCryptoOps.py | 2 +- .../crypto_ops_builder/ref10CommentedCombined/crypto-ops.h | 4 ++-- src/crypto/generic-ops.h | 4 ++-- src/crypto/hash-ops.h | 4 ++-- src/crypto/hash.c | 4 ++-- src/crypto/hash.h | 4 ++-- src/crypto/pow_hash/arm8_neon.hpp | 2 +- src/crypto/pow_hash/arm_vfp.hpp | 2 +- src/crypto/pow_hash/aux_hash.c | 2 +- src/crypto/pow_hash/aux_hash.h | 2 +- src/crypto/pow_hash/cn_slow_hash.hpp | 2 +- src/crypto/pow_hash/cn_slow_hash_hard_arm.cpp | 2 +- src/crypto/pow_hash/cn_slow_hash_hard_intel.cpp | 2 +- src/crypto/pow_hash/cn_slow_hash_intel_avx2.cpp | 2 +- src/crypto/pow_hash/cn_slow_hash_soft.cpp | 2 +- src/crypto/pow_hash/hw_detect.hpp | 2 +- src/crypto/random.cpp | 4 ++-- src/crypto/random.hpp | 4 ++-- src/crypto/tree-hash.c | 4 ++-- src/cryptonote_basic/CMakeLists.txt | 4 ++-- src/cryptonote_basic/account.cpp | 4 ++-- src/cryptonote_basic/account.h | 4 ++-- src/cryptonote_basic/account_boost_serialization.h | 4 ++-- src/cryptonote_basic/blobdatatype.h | 4 ++-- src/cryptonote_basic/connection_context.h | 4 ++-- src/cryptonote_basic/cryptonote_basic.h | 4 ++-- src/cryptonote_basic/cryptonote_basic_impl.cpp | 4 ++-- src/cryptonote_basic/cryptonote_basic_impl.h | 4 ++-- src/cryptonote_basic/cryptonote_boost_serialization.h | 4 ++-- src/cryptonote_basic/cryptonote_format_utils.cpp | 4 ++-- src/cryptonote_basic/cryptonote_format_utils.h | 4 ++-- src/cryptonote_basic/cryptonote_stat_info.h | 4 ++-- src/cryptonote_basic/difficulty.cpp | 2 +- src/cryptonote_basic/difficulty.h | 2 +- src/cryptonote_basic/hardfork.cpp | 4 ++-- src/cryptonote_basic/hardfork.h | 4 ++-- src/cryptonote_basic/miner.cpp | 4 ++-- src/cryptonote_basic/miner.h | 4 ++-- src/cryptonote_basic/subaddress_index.h | 4 ++-- src/cryptonote_basic/tx_extra.h | 4 ++-- src/cryptonote_basic/verification_context.h | 4 ++-- src/cryptonote_config.cpp | 4 ++-- src/cryptonote_config.h | 4 ++-- src/cryptonote_core/CMakeLists.txt | 4 ++-- src/cryptonote_core/blockchain.cpp | 4 ++-- src/cryptonote_core/blockchain.h | 4 ++-- .../blockchain_storage_boost_serialization.h | 4 ++-- src/cryptonote_core/cryptonote_core.cpp | 4 ++-- src/cryptonote_core/cryptonote_core.h | 4 ++-- src/cryptonote_core/cryptonote_tx_utils.cpp | 4 ++-- src/cryptonote_core/cryptonote_tx_utils.h | 4 ++-- src/cryptonote_core/tx_pool.cpp | 4 ++-- src/cryptonote_core/tx_pool.h | 4 ++-- src/cryptonote_protocol/CMakeLists.txt | 4 ++-- src/cryptonote_protocol/block_queue.cpp | 4 ++-- src/cryptonote_protocol/block_queue.h | 4 ++-- src/cryptonote_protocol/cryptonote_protocol_defs.h | 4 ++-- .../cryptonote_protocol_handler-base.cpp | 4 ++-- src/cryptonote_protocol/cryptonote_protocol_handler.h | 4 ++-- src/cryptonote_protocol/cryptonote_protocol_handler.inl | 4 ++-- .../cryptonote_protocol_handler_common.h | 4 ++-- src/daemon/CMakeLists.txt | 4 ++-- src/daemon/command_line_args.h | 4 ++-- src/daemon/command_parser_executor.cpp | 4 ++-- src/daemon/command_parser_executor.h | 4 ++-- src/daemon/command_server.cpp | 4 ++-- src/daemon/command_server.h | 4 ++-- src/daemon/core.h | 4 ++-- src/daemon/daemon.cpp | 4 ++-- src/daemon/daemon.h | 4 ++-- src/daemon/executor.cpp | 4 ++-- src/daemon/executor.h | 4 ++-- src/daemon/main.cpp | 4 ++-- src/daemon/p2p.h | 4 ++-- src/daemon/protocol.h | 4 ++-- src/daemon/rpc.h | 4 ++-- src/daemon/rpc_command_executor.cpp | 4 ++-- src/daemon/rpc_command_executor.h | 4 ++-- src/daemonizer/CMakeLists.txt | 4 ++-- src/daemonizer/daemonizer.h | 4 ++-- src/daemonizer/posix_daemonizer.inl | 4 ++-- src/daemonizer/posix_fork.h | 4 ++-- src/daemonizer/windows_daemonizer.inl | 4 ++-- src/daemonizer/windows_service.cpp | 4 ++-- src/daemonizer/windows_service.h | 4 ++-- src/daemonizer/windows_service_runner.h | 4 ++-- src/debug_utilities/CMakeLists.txt | 4 ++-- src/debug_utilities/cn_deserialize.cpp | 4 ++-- src/debug_utilities/object_sizes.cpp | 4 ++-- src/device/CMakeLists.txt | 4 ++-- src/device/device.cpp | 4 ++-- src/device/device.hpp | 4 ++-- src/device/device_default.cpp | 4 ++-- src/device/device_default.hpp | 4 ++-- src/device/device_ledger.cpp | 4 ++-- src/device/device_ledger.hpp | 4 ++-- src/device/log.cpp | 4 ++-- src/device/log.hpp | 4 ++-- src/gen_multisig/CMakeLists.txt | 4 ++-- src/gen_multisig/gen_multisig.cpp | 4 ++-- src/mnemonics/CMakeLists.txt | 4 ++-- src/mnemonics/dutch.h | 2 +- src/mnemonics/electrum-words.cpp | 4 ++-- src/mnemonics/electrum-words.h | 4 ++-- src/mnemonics/english.h | 2 +- src/mnemonics/esperanto.h | 2 +- src/mnemonics/french.h | 4 ++-- src/mnemonics/german.h | 2 +- src/mnemonics/italian.h | 2 +- src/mnemonics/language_base.h | 2 +- src/mnemonics/lojban.h | 2 +- src/mnemonics/russian.h | 2 +- src/mnemonics/singleton.h | 2 +- src/multisig/CMakeLists.txt | 4 ++-- src/multisig/multisig.cpp | 4 ++-- src/multisig/multisig.h | 4 ++-- src/p2p/CMakeLists.txt | 4 ++-- src/p2p/net_node.cpp | 4 ++-- src/p2p/net_node.h | 4 ++-- src/p2p/net_node.inl | 4 ++-- src/p2p/net_node_common.h | 4 ++-- src/p2p/net_peerlist.h | 4 ++-- src/p2p/net_peerlist_boost_serialization.h | 4 ++-- src/p2p/p2p_protocol_defs.h | 4 ++-- src/p2p/stdafx.h | 4 ++-- src/platform/mingw/alloca.h | 4 ++-- src/platform/msc/alloca.h | 4 ++-- src/platform/msc/inline_c.h | 4 ++-- src/platform/msc/stdbool.h | 4 ++-- src/platform/msc/sys/param.h | 4 ++-- src/ringct/CMakeLists.txt | 2 +- src/ringct/bulletproofs.cc | 4 ++-- src/ringct/bulletproofs.h | 4 ++-- src/ringct/multiexp.cc | 4 ++-- src/ringct/multiexp.h | 4 ++-- src/ringct/rctCryptoOps.c | 4 ++-- src/ringct/rctCryptoOps.h | 4 ++-- src/ringct/rctOps.cpp | 5 +++-- src/ringct/rctOps.h | 6 +++--- src/ringct/rctSigs.cpp | 5 +++-- src/ringct/rctSigs.h | 5 +++-- src/ringct/rctTypes.cpp | 5 +++-- src/ringct/rctTypes.h | 5 +++-- src/rpc/CMakeLists.txt | 4 ++-- src/rpc/core_rpc_server.cpp | 4 ++-- src/rpc/core_rpc_server.h | 4 ++-- src/rpc/core_rpc_server_commands_defs.h | 4 ++-- src/rpc/core_rpc_server_error_codes.h | 4 ++-- src/rpc/daemon_handler.cpp | 4 ++-- src/rpc/daemon_handler.h | 4 ++-- src/rpc/daemon_messages.cpp | 4 ++-- src/rpc/daemon_messages.h | 4 ++-- src/rpc/daemon_rpc_version.h | 4 ++-- src/rpc/instanciations.cpp | 4 ++-- src/rpc/message.cpp | 4 ++-- src/rpc/message.h | 4 ++-- src/rpc/message_data_structs.h | 4 ++-- src/rpc/rpc_args.cpp | 4 ++-- src/rpc/rpc_args.h | 4 ++-- src/rpc/rpc_handler.h | 4 ++-- src/rpc/zmq_server.cpp | 4 ++-- src/rpc/zmq_server.h | 4 ++-- src/serialization/CMakeLists.txt | 2 +- src/serialization/binary_archive.h | 4 ++-- src/serialization/binary_utils.h | 4 ++-- src/serialization/container.h | 4 ++-- src/serialization/crypto.h | 4 ++-- src/serialization/debug_archive.h | 4 ++-- src/serialization/deque.h | 4 ++-- src/serialization/json_archive.h | 4 ++-- src/serialization/json_object.cpp | 4 ++-- src/serialization/json_object.h | 4 ++-- src/serialization/json_utils.h | 4 ++-- src/serialization/list.h | 4 ++-- src/serialization/pair.h | 4 ++-- src/serialization/serialization.h | 4 ++-- src/serialization/set.h | 4 ++-- src/serialization/string.h | 4 ++-- src/serialization/unordered_set.h | 4 ++-- src/serialization/variant.h | 4 ++-- src/serialization/vector.h | 4 ++-- src/simplewallet/CMakeLists.txt | 4 ++-- src/simplewallet/simplewallet.cpp | 4 ++-- src/simplewallet/simplewallet.h | 4 ++-- src/wallet/CMakeLists.txt | 4 ++-- src/wallet/api/CMakeLists.txt | 4 ++-- src/wallet/api/address_book.cpp | 4 ++-- src/wallet/api/address_book.h | 4 ++-- src/wallet/api/pending_transaction.cpp | 4 ++-- src/wallet/api/pending_transaction.h | 4 ++-- src/wallet/api/subaddress.cpp | 4 ++-- src/wallet/api/subaddress.h | 4 ++-- src/wallet/api/subaddress_account.cpp | 4 ++-- src/wallet/api/subaddress_account.h | 4 ++-- src/wallet/api/transaction_history.cpp | 4 ++-- src/wallet/api/transaction_history.h | 4 ++-- src/wallet/api/transaction_info.cpp | 4 ++-- src/wallet/api/transaction_info.h | 4 ++-- src/wallet/api/unsigned_transaction.cpp | 4 ++-- src/wallet/api/unsigned_transaction.h | 4 ++-- src/wallet/api/utils.cpp | 4 ++-- src/wallet/api/wallet.cpp | 4 ++-- src/wallet/api/wallet.h | 4 ++-- src/wallet/api/wallet2_api.h | 4 ++-- src/wallet/api/wallet_manager.cpp | 4 ++-- src/wallet/api/wallet_manager.h | 4 ++-- src/wallet/node_rpc_proxy.cpp | 4 ++-- src/wallet/node_rpc_proxy.h | 4 ++-- src/wallet/ringdb.cpp | 4 ++-- src/wallet/ringdb.h | 4 ++-- src/wallet/wallet2.cpp | 4 ++-- src/wallet/wallet2.h | 4 ++-- src/wallet/wallet_args.cpp | 4 ++-- src/wallet/wallet_args.h | 4 ++-- src/wallet/wallet_errors.h | 4 ++-- src/wallet/wallet_rpc_server.cpp | 4 ++-- src/wallet/wallet_rpc_server.h | 4 ++-- src/wallet/wallet_rpc_server_commands_defs.h | 4 ++-- src/wallet/wallet_rpc_server_error_codes.h | 4 ++-- tests/crypto/main.cpp | 4 ++-- tests/unit_tests/ts_interpolation.cpp | 4 ++-- 298 files changed, 578 insertions(+), 573 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97bf2d1d..82e49066 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 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/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 0b3001fe..1629ecc7 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. @@ -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.h b/src/address_validator/address_validator.h index 79dbf9dd..75ae28e5 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 @@ -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/writer.cpp b/src/address_validator/writer.cpp index 242fefee..9da45ee4 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 @@ -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/writer.h b/src/address_validator/writer.h index 30bc70d4..dad45159 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 @@ -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/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt index c27a80e5..0f41b32a 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 diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp index 4ef1355f..3bee938f 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. @@ -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/blockchain_db/berkeleydb/db_bdb.h b/src/blockchain_db/berkeleydb/db_bdb.h index e3cde725..5540e7fb 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. @@ -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/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index b343dcc8..75ae7558 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 @@ -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/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index 33fa9b8d..eec13ec6 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 @@ -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/blockchain_db/db_types.h b/src/blockchain_db/db_types.h index e8b2f26c..36b39095 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 @@ -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/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 2fffa0da..47b921f7 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. @@ -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/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index b2935a1e..c00c2a7c 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. @@ -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/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 602f75f4..cd1508e0 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 diff --git a/src/blockchain_utilities/blockchain_blackball.cpp b/src/blockchain_utilities/blockchain_blackball.cpp index a20560fe..c4e13f83 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 @@ -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/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp index 89a5b9cc..e37a4f4f 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 @@ -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/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 1f72cab1..dbbbea27 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 @@ -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/blockchain_utilities/blockchain_usage.cpp b/src/blockchain_utilities/blockchain_usage.cpp index 4591afa1..7eb2fce7 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 @@ -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/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index d927220d..9ec3f9a7 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 @@ -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/blockchain_utilities/blocksdat_file.cpp b/src/blockchain_utilities/blocksdat_file.cpp index b5365fbd..d364633f 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 @@ -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/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h index 6ed3d2a5..168e9590 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 @@ -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/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index 12f46fe0..bc50c990 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 @@ -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/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h index 89c84261..04b48b1b 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 @@ -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/blockchain_utilities/bootstrap_serialization.h b/src/blockchain_utilities/bootstrap_serialization.h index 75cd07b1..7705c5dc 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 @@ -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/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..14dbc8c6 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 diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp index ca64385a..128af1f8 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 @@ -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/checkpoints.h b/src/checkpoints/checkpoints.h index 66f1c837..99a0362e 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 @@ -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/common/CMakeLists.txt b/src/common/CMakeLists.txt index b9b1f648..325632ec 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 diff --git a/src/common/apply_permutation.h b/src/common/apply_permutation.h index 0e616c75..a696a2f2 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 @@ -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/common/base58.cpp b/src/common/base58.cpp index 1a9be525..fa8ff018 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 @@ -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/common/base58.h b/src/common/base58.h index 595a93ca..a8a1eb46 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 @@ -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/common/boost_locale.cpp b/src/common/boost_locale.cpp index c6f9b959..0eada8b5 100644 --- a/src/common/boost_locale.cpp +++ b/src/common/boost_locale.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. @@ -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/common/boost_locale.hpp b/src/common/boost_locale.hpp index 4494a2ec..6a3eeb8e 100644 --- a/src/common/boost_locale.hpp +++ b/src/common/boost_locale.hpp @@ -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. @@ -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/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index e0907bde..3ba556cf 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.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,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/common/command_line.cpp b/src/common/command_line.cpp index d2de271f..12f58524 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 @@ -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/common/command_line.h b/src/common/command_line.h index e8d73c17..b8e41182 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 @@ -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/common/common_fwd.h b/src/common/common_fwd.h index fadce88a..4ad83636 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 @@ -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/common/dns_utils.cpp b/src/common/dns_utils.cpp index e6408e2a..e2ad88b9 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 @@ -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/common/dns_utils.h b/src/common/dns_utils.h index fde41293..9c458b11 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 @@ -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/common/download.cpp b/src/common/download.cpp index 212ebe49..4fc20619 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 @@ -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/common/download.h b/src/common/download.h index 3e9878d6..9a0ab4b5 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 @@ -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/common/http_connection.h b/src/common/http_connection.h index 1c223ed1..8423c5a4 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 @@ -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/common/i18n.cpp b/src/common/i18n.cpp index 23954395..fffbe5de 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 @@ -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/common/i18n.h b/src/common/i18n.h index bc340fb1..79ae14bf 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 @@ -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/common/int-util.h b/src/common/int-util.h index 1cf40602..a0c61ac7 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 @@ -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/common/json_util.h b/src/common/json_util.h index 002f7d75..edc43a3b 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 @@ -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/common/password.cpp b/src/common/password.cpp index 1b0f906b..ce4c2456 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 @@ -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/common/password.h b/src/common/password.h index 4e6309d0..c541766f 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 @@ -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/common/perf_timer.cpp b/src/common/perf_timer.cpp index fd91798c..535ba4de 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 @@ -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/common/perf_timer.h b/src/common/perf_timer.h index ece2ef31..bbf61a15 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 @@ -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/common/rpc_client.h b/src/common/rpc_client.h index f0d5e88c..4fe71a2d 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 @@ -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/common/scoped_message_writer.h b/src/common/scoped_message_writer.h index e1cd69d8..ce5d6b5c 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 @@ -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/common/sfinae_helpers.h b/src/common/sfinae_helpers.h index 20177b12..4a376e6c 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 @@ -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/common/stack_trace.cpp b/src/common/stack_trace.cpp index 07d063cd..9e9b1225 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 @@ -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/common/stack_trace.h b/src/common/stack_trace.h index 547478d0..792e9547 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 @@ -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/common/threadpool.cpp b/src/common/threadpool.cpp index 55b0ef88..31f6bab2 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 @@ -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/common/threadpool.h b/src/common/threadpool.h index 40bc3994..99063a00 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 @@ -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/common/unordered_containers_boost_serialization.h b/src/common/unordered_containers_boost_serialization.h index 5422d4ff..beebeeaf 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 @@ -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/common/updates.cpp b/src/common/updates.cpp index f02cf657..4663f99b 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 @@ -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/common/updates.h b/src/common/updates.h index d2eb9de6..b673e3a3 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 @@ -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/common/util.cpp b/src/common/util.cpp index 3b469e23..3f129d7c 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 @@ -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/common/util.h b/src/common/util.h index bdb6e9f6..3640dac7 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,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/common/varint.h b/src/common/varint.h index f0cef02f..495486c1 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 @@ -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/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 59c2e3d3..a92f7744 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 diff --git a/src/crypto/chacha.h b/src/crypto/chacha.h index ba3def10..f2e0bb28 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 @@ -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/crypto/crypto-ops-data.c b/src/crypto/crypto-ops-data.c index d3b709ce..202ae3d1 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 @@ -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/crypto/crypto-ops.c b/src/crypto/crypto-ops.c index 49171364..06709890 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 @@ -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/crypto/crypto-ops.h b/src/crypto/crypto-ops.h index 3f328026..4945e810 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 @@ -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/crypto/crypto.cpp b/src/crypto/crypto.cpp index c82c37f7..9375318d 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 @@ -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/crypto/crypto.h b/src/crypto/crypto.h index dd614b54..83e68d00 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 @@ -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/crypto/crypto_ops_builder/crypto-ops-data.c b/src/crypto/crypto_ops_builder/crypto-ops-data.c index f7161c05..e7de5c23 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 @@ -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/crypto/crypto_ops_builder/crypto-ops-old.c b/src/crypto/crypto_ops_builder/crypto-ops-old.c index d85f11e7..c8029e93 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 @@ -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/crypto/crypto_ops_builder/crypto-ops.h b/src/crypto/crypto_ops_builder/crypto-ops.h index 6e04d42a..1bf1e0df 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 @@ -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/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 b8e831b9..b2120d91 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 @@ -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/crypto/generic-ops.h b/src/crypto/generic-ops.h index 3983f8dd..7a21818f 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 @@ -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/crypto/hash-ops.h b/src/crypto/hash-ops.h index aad195ee..8672867f 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 @@ -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/crypto/hash.c b/src/crypto/hash.c index 041cb03a..6cffc3bf 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 @@ -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/crypto/hash.h b/src/crypto/hash.h index 38279522..00ac8002 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 @@ -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/crypto/pow_hash/arm8_neon.hpp b/src/crypto/pow_hash/arm8_neon.hpp index 4dbd0825..a9864b5f 100644 --- a/src/crypto/pow_hash/arm8_neon.hpp +++ b/src/crypto/pow_hash/arm8_neon.hpp @@ -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/crypto/pow_hash/arm_vfp.hpp b/src/crypto/pow_hash/arm_vfp.hpp index c82b01f0..ba6d6785 100644 --- a/src/crypto/pow_hash/arm_vfp.hpp +++ b/src/crypto/pow_hash/arm_vfp.hpp @@ -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/crypto/pow_hash/aux_hash.c b/src/crypto/pow_hash/aux_hash.c index c070e93d..cb8fdba6 100644 --- a/src/crypto/pow_hash/aux_hash.c +++ b/src/crypto/pow_hash/aux_hash.c @@ -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/crypto/pow_hash/aux_hash.h b/src/crypto/pow_hash/aux_hash.h index 2a5540d5..69c567b2 100644 --- a/src/crypto/pow_hash/aux_hash.h +++ b/src/crypto/pow_hash/aux_hash.h @@ -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/crypto/pow_hash/cn_slow_hash.hpp b/src/crypto/pow_hash/cn_slow_hash.hpp index b2d08311..c549d33d 100644 --- a/src/crypto/pow_hash/cn_slow_hash.hpp +++ b/src/crypto/pow_hash/cn_slow_hash.hpp @@ -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/crypto/pow_hash/cn_slow_hash_hard_arm.cpp b/src/crypto/pow_hash/cn_slow_hash_hard_arm.cpp index 6c9b7d9a..cc53858f 100644 --- a/src/crypto/pow_hash/cn_slow_hash_hard_arm.cpp +++ b/src/crypto/pow_hash/cn_slow_hash_hard_arm.cpp @@ -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/crypto/pow_hash/cn_slow_hash_hard_intel.cpp b/src/crypto/pow_hash/cn_slow_hash_hard_intel.cpp index 1c1204d3..0091befb 100644 --- a/src/crypto/pow_hash/cn_slow_hash_hard_intel.cpp +++ b/src/crypto/pow_hash/cn_slow_hash_hard_intel.cpp @@ -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/crypto/pow_hash/cn_slow_hash_intel_avx2.cpp b/src/crypto/pow_hash/cn_slow_hash_intel_avx2.cpp index 68488324..16128e56 100644 --- a/src/crypto/pow_hash/cn_slow_hash_intel_avx2.cpp +++ b/src/crypto/pow_hash/cn_slow_hash_intel_avx2.cpp @@ -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/crypto/pow_hash/cn_slow_hash_soft.cpp b/src/crypto/pow_hash/cn_slow_hash_soft.cpp index 0f22a38b..a31cc459 100644 --- a/src/crypto/pow_hash/cn_slow_hash_soft.cpp +++ b/src/crypto/pow_hash/cn_slow_hash_soft.cpp @@ -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/crypto/pow_hash/hw_detect.hpp b/src/crypto/pow_hash/hw_detect.hpp index 748e97d3..58a93f4d 100644 --- a/src/crypto/pow_hash/hw_detect.hpp +++ b/src/crypto/pow_hash/hw_detect.hpp @@ -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/crypto/random.cpp b/src/crypto/random.cpp index c2100eac..4ab054a2 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. // @@ -28,7 +28,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/crypto/random.hpp b/src/crypto/random.hpp index 6b34b8bd..59fb876c 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. // @@ -28,7 +28,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/crypto/tree-hash.c b/src/crypto/tree-hash.c index 3e3ccd54..07eb0284 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 @@ -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/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index 9ecc1cfa..8010a3cd 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 diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 2605d64b..5f28f226 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,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/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index 247f58b0..bbb514f0 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 @@ -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/cryptonote_basic/account_boost_serialization.h b/src/cryptonote_basic/account_boost_serialization.h index b67fc774..9d7990c7 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 @@ -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/cryptonote_basic/blobdatatype.h b/src/cryptonote_basic/blobdatatype.h index 4f8fde87..755eacde 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 @@ -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/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h index 57b016f0..dcb1ed9e 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 @@ -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/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 1f3a3635..8b7e08dc 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 @@ -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/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 00e07940..d85937bc 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 @@ -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/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index a2e8f0c8..e6a80653 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 @@ -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/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index a8636dfa..f59f1269 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 @@ -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/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index efe18d93..b6120493 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 @@ -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/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index baa0394a..97ac3bd5 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 @@ -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/cryptonote_basic/cryptonote_stat_info.h b/src/cryptonote_basic/cryptonote_stat_info.h index 942c9c40..632c78f2 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 @@ -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/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index 6f6a20ab..7174da02 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -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/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h index ca8a8c9f..71b62b03 100644 --- a/src/cryptonote_basic/difficulty.h +++ b/src/cryptonote_basic/difficulty.h @@ -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/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index 00454402..5c78d0ff 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 @@ -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/cryptonote_basic/hardfork.h b/src/cryptonote_basic/hardfork.h index 2570b059..dc03b0a0 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 @@ -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/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index e1f472b0..ab81954e 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 @@ -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/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h index 609885b4..a9e9099d 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 @@ -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/cryptonote_basic/subaddress_index.h b/src/cryptonote_basic/subaddress_index.h index caa39078..24da4746 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 @@ -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/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h index 41610a45..6cffe5ae 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 @@ -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/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h index 2f70c4a4..3f8e8c2f 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 @@ -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/cryptonote_config.cpp b/src/cryptonote_config.cpp index 9b20fd6b..dd9e614f 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. @@ -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/cryptonote_config.h b/src/cryptonote_config.h index b16be127..7eeb1336 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 @@ -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/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index 6d26fbb0..fcb1fa67 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 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 0b734221..00a4719b 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 @@ -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/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index ae82f494..e15d0cb6 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 @@ -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/cryptonote_core/blockchain_storage_boost_serialization.h b/src/cryptonote_core/blockchain_storage_boost_serialization.h index 7d7fdf18..7af171bd 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 @@ -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/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 87ae4c6a..68d7ce10 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 @@ -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/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index e7eb002e..348d597b 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 @@ -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/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 6656f491..c3ee4425 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 @@ -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/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index d82fa571..23630d68 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 @@ -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/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index becafd6b..fa8584bc 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 @@ -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/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 1db95142..37ea1f52 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 @@ -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/cryptonote_protocol/CMakeLists.txt b/src/cryptonote_protocol/CMakeLists.txt index 0978502d..813088da 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 diff --git a/src/cryptonote_protocol/block_queue.cpp b/src/cryptonote_protocol/block_queue.cpp index e534b3df..aeee1e9a 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 @@ -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/cryptonote_protocol/block_queue.h b/src/cryptonote_protocol/block_queue.h index ebe91e85..5da53cf5 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 @@ -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/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 1f4d6843..b1c1921a 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 @@ -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/cryptonote_protocol/cryptonote_protocol_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index 54f13b9b..7b303264 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 @@ -34,7 +34,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/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h index 808c8d84..7b0ac14a 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 @@ -34,7 +34,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/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 3c0f9ed6..8ad81014 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 @@ -34,7 +34,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/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h index 944a2afd..2deb4d66 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 @@ -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/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index b39c70e9..ec45032e 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 diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index defd6f32..962f2a25 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 @@ -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/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 81b77ab2..1c0c3204 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 @@ -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/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h index 443a0d3b..6ef2729d 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 @@ -38,7 +38,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/daemon/command_server.cpp b/src/daemon/command_server.cpp index 4478eea8..8fd66484 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 @@ -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/daemon/command_server.h b/src/daemon/command_server.h index 281555c3..ea3ed330 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 @@ -41,7 +41,7 @@ Passing RPC commands: // 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/daemon/core.h b/src/daemon/core.h index df879d23..0c54c630 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 @@ -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/daemon/daemon.cpp b/src/daemon/daemon.cpp index 526f7691..b3e645e2 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 @@ -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/daemon/daemon.h b/src/daemon/daemon.h index 7a5276ea..d1f7e25f 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 @@ -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/daemon/executor.cpp b/src/daemon/executor.cpp index 0208e1a0..cb0ad6d9 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 @@ -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/daemon/executor.h b/src/daemon/executor.h index 2fd0bb8d..8e53125d 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 @@ -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/daemon/main.cpp b/src/daemon/main.cpp index 642a6b4d..ffc846ac 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,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/daemon/p2p.h b/src/daemon/p2p.h index dccb9326..06e68234 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 @@ -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/daemon/protocol.h b/src/daemon/protocol.h index db97d39c..a5a3bcb7 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 @@ -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/daemon/rpc.h b/src/daemon/rpc.h index e08a6c5c..d722b8fc 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 @@ -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/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index f5382ddf..f153bae2 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 @@ -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/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h index 158e1510..98f0ff06 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 @@ -38,7 +38,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/daemonizer/CMakeLists.txt b/src/daemonizer/CMakeLists.txt index 622b1792..670c527c 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 diff --git a/src/daemonizer/daemonizer.h b/src/daemonizer/daemonizer.h index 0b462f66..28a21a01 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 @@ -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/daemonizer/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl index f5d33e7e..b28c9c2f 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 @@ -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/daemonizer/posix_fork.h b/src/daemonizer/posix_fork.h index da22399c..5ac594b1 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 @@ -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/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 4bf0785c..2898b3cd 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 @@ -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/daemonizer/windows_service.cpp b/src/daemonizer/windows_service.cpp index 7425d858..0ed7f608 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 @@ -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/daemonizer/windows_service.h b/src/daemonizer/windows_service.h index 08d39835..0e932155 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 @@ -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/daemonizer/windows_service_runner.h b/src/daemonizer/windows_service_runner.h index 42f8d037..979f082f 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 @@ -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/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 91245438..d45fa73c 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 @@ -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/object_sizes.cpp b/src/debug_utilities/object_sizes.cpp index 9d2cf0fa..4694dd21 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 @@ -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/device/CMakeLists.txt b/src/device/CMakeLists.txt index 9b4a93d1..427a9125 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 diff --git a/src/device/device.cpp b/src/device/device.cpp index 6da1b5ec..00462efa 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 @@ -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/device/device.hpp b/src/device/device.hpp index 598e0a16..d5284c85 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 @@ -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/device/device_default.cpp b/src/device/device_default.cpp index 05853bae..8fd9563a 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 @@ -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/device/device_default.hpp b/src/device/device_default.hpp index e26fd229..440cf53f 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 @@ -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/device/device_ledger.cpp b/src/device/device_ledger.cpp index c9c315ed..a7a4fc76 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 @@ -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/device/device_ledger.hpp b/src/device/device_ledger.hpp index 1434de84..994b0710 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 @@ -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/device/log.cpp b/src/device/log.cpp index 548d29b9..fc38a667 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 @@ -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/device/log.hpp b/src/device/log.hpp index 457eacf0..5c7537ae 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 @@ -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/gen_multisig/CMakeLists.txt b/src/gen_multisig/CMakeLists.txt index c9858181..24ff95b5 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 diff --git a/src/gen_multisig/gen_multisig.cpp b/src/gen_multisig/gen_multisig.cpp index c196e682..a790362e 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 @@ -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/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt index 3a304cdf..37b59854 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 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 28af2ff7..8db181b1 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 @@ -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/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h index 7c500685..77320b8c 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 @@ -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/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 b93c5cd2..fb832630 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 @@ -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/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..7845b3ef 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 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..bcee44c6 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 diff --git a/src/multisig/multisig.cpp b/src/multisig/multisig.cpp index de270d6d..8215994e 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 @@ -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/multisig/multisig.h b/src/multisig/multisig.h index ad6e86da..be2aa8c7 100644 --- a/src/multisig/multisig.h +++ b/src/multisig/multisig.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,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/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt index 0fa439b9..30b9d07c 100644 --- a/src/p2p/CMakeLists.txt +++ b/src/p2p/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/p2p/net_node.cpp b/src/p2p/net_node.cpp index 3cf4d56c..de5aabfb 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.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,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/p2p/net_node.h b/src/p2p/net_node.h index 31efa638..8b499b5d 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.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,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/p2p/net_node.inl b/src/p2p/net_node.inl index 757c9a8f..8a3db318 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.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 @@ -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/p2p/net_node_common.h b/src/p2p/net_node_common.h index c11c1181..3a376ee8 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 @@ -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/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 633e31b8..f3d029a8 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 @@ -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/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 081a54b8..d16deed7 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_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 @@ -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/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 9a043d08..f42f5ff8 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_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 @@ -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/p2p/stdafx.h b/src/p2p/stdafx.h index cacbc572..9c0f3eb9 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 @@ -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/platform/mingw/alloca.h b/src/platform/mingw/alloca.h index 4e9cbba0..088f14cd 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 @@ -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/platform/msc/alloca.h b/src/platform/msc/alloca.h index ed955a9b..326a2cf2 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 @@ -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/platform/msc/inline_c.h b/src/platform/msc/inline_c.h index afb532c2..3b8dd596 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 @@ -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/platform/msc/stdbool.h b/src/platform/msc/stdbool.h index e443549c..b1c122b7 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 @@ -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/platform/msc/sys/param.h b/src/platform/msc/sys/param.h index 7470d28a..700deb5a 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 @@ -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/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 3b6f8096..0e8d914a 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 diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 56d4f587..675dcd1a 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 @@ -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/ringct/bulletproofs.h b/src/ringct/bulletproofs.h index 3e11d759..ab93b133 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 @@ -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/ringct/multiexp.cc b/src/ringct/multiexp.cc index 5d1d9afc..83850901 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 @@ -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/ringct/multiexp.h b/src/ringct/multiexp.h index 2c678249..eb7316fd 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 @@ -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/ringct/rctCryptoOps.c b/src/ringct/rctCryptoOps.c index bc087fe4..3e0d024e 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 @@ -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/ringct/rctCryptoOps.h b/src/ringct/rctCryptoOps.h index 624c8cf3..cd72323f 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 @@ -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/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index f493b15f..7c04dd40 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 // @@ -31,7 +32,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/ringct/rctOps.h b/src/ringct/rctOps.h index 00f6d0a5..cf7c87e9 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 // @@ -32,7 +32,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/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index ef6fbdd4..f484cdd1 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 // @@ -31,7 +32,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/ringct/rctSigs.h b/src/ringct/rctSigs.h index 914c28e3..84f18850 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 // @@ -31,7 +32,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/ringct/rctTypes.cpp b/src/ringct/rctTypes.cpp index 333f9572..9da6d905 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 // @@ -31,7 +32,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/ringct/rctTypes.h b/src/ringct/rctTypes.h index 9fbef492..6bd6da19 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 // @@ -31,7 +32,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/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 921a19c0..2c641272 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 diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index a9bd14b0..615dc626 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 @@ -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/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index cb37ca50..4fd66aac 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,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/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 06193281..d1b8a105 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 @@ -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/rpc/core_rpc_server_error_codes.h b/src/rpc/core_rpc_server_error_codes.h index cb5e1676..600fe7de 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 @@ -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/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index bd97fb63..d3126a01 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 @@ -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/rpc/daemon_handler.h b/src/rpc/daemon_handler.h index 759670ee..83935e16 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 @@ -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/rpc/daemon_messages.cpp b/src/rpc/daemon_messages.cpp index 51ecf3d4..2bf81256 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 @@ -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/rpc/daemon_messages.h b/src/rpc/daemon_messages.h index d855a723..f2b8adb7 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 @@ -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/rpc/daemon_rpc_version.h b/src/rpc/daemon_rpc_version.h index 4055b935..c06d1054 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 @@ -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/rpc/instanciations.cpp b/src/rpc/instanciations.cpp index 74324818..635ae395 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 @@ -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/rpc/message.cpp b/src/rpc/message.cpp index 9a934e65..ce66e69f 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 @@ -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/rpc/message.h b/src/rpc/message.h index f15b3a7c..340a6fe2 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 @@ -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/rpc/message_data_structs.h b/src/rpc/message_data_structs.h index a7c5a47c..2306df0b 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 @@ -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/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index 16b7e694..a217c6e7 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 @@ -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/rpc/rpc_args.h b/src/rpc/rpc_args.h index 643b269b..50cb656c 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 @@ -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/rpc/rpc_handler.h b/src/rpc/rpc_handler.h index 879d02e2..11dd3a44 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 @@ -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/rpc/zmq_server.cpp b/src/rpc/zmq_server.cpp index aa797fe5..464053e5 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 @@ -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/rpc/zmq_server.h b/src/rpc/zmq_server.h index 67b2364f..a3fe5419 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 @@ -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/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index 626f6cc0..2e740876 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 diff --git a/src/serialization/binary_archive.h b/src/serialization/binary_archive.h index 4d2f296d..12fd1542 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 @@ -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/serialization/binary_utils.h b/src/serialization/binary_utils.h index c77bdce2..42c0f064 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 @@ -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/serialization/container.h b/src/serialization/container.h index 4a036058..c976dd66 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 @@ -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/serialization/crypto.h b/src/serialization/crypto.h index 157c434f..feaac85c 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 @@ -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/serialization/debug_archive.h b/src/serialization/debug_archive.h index b7e1c55c..9c5b0edd 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 @@ -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/serialization/deque.h b/src/serialization/deque.h index 013e47a7..28e9678f 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 @@ -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/serialization/json_archive.h b/src/serialization/json_archive.h index ec43d889..2abbc3ff 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 @@ -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/serialization/json_object.cpp b/src/serialization/json_object.cpp index d17ede0d..261027a2 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 @@ -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/serialization/json_object.h b/src/serialization/json_object.h index 2f2aa500..a5fdab78 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 @@ -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/serialization/json_utils.h b/src/serialization/json_utils.h index 11c1009a..9d2f4074 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 @@ -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/serialization/list.h b/src/serialization/list.h index 9aec0bb4..e97ba43d 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 @@ -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/serialization/pair.h b/src/serialization/pair.h index 34da4cc9..74ce48a3 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 @@ -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/serialization/serialization.h b/src/serialization/serialization.h index 56b1a8ef..a061ab6f 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 @@ -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/serialization/set.h b/src/serialization/set.h index f399a325..5154459e 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 @@ -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/serialization/string.h b/src/serialization/string.h index 2672a7f3..cd8647b2 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 @@ -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/serialization/unordered_set.h b/src/serialization/unordered_set.h index 808eff52..9793d8c9 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 @@ -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/serialization/variant.h b/src/serialization/variant.h index 764b0626..cb9dce52 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 @@ -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/serialization/vector.h b/src/serialization/vector.h index a7fc1675..840c638a 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 @@ -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/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 cae74112..cdbe61c6 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 @@ -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.h b/src/simplewallet/simplewallet.h index 95390f96..11075994 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.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,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/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt index a50357e4..d72fa55a 100644 --- a/src/wallet/CMakeLists.txt +++ b/src/wallet/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/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt index 0025238f..22b8f793 100644 --- a/src/wallet/api/CMakeLists.txt +++ b/src/wallet/api/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/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp index a8f6a54c..352c54e4 100644 --- a/src/wallet/api/address_book.cpp +++ b/src/wallet/api/address_book.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,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/wallet/api/address_book.h b/src/wallet/api/address_book.h index a7269a22..2350d697 100644 --- a/src/wallet/api/address_book.h +++ b/src/wallet/api/address_book.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,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/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index 36e382aa..38a004dd 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.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,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/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h index 9e1f5531..9aef3408 100644 --- a/src/wallet/api/pending_transaction.h +++ b/src/wallet/api/pending_transaction.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,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/wallet/api/subaddress.cpp b/src/wallet/api/subaddress.cpp index 3122c231..17ddafcc 100644 --- a/src/wallet/api/subaddress.cpp +++ b/src/wallet/api/subaddress.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,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/wallet/api/subaddress.h b/src/wallet/api/subaddress.h index 082e52cf..4f227443 100644 --- a/src/wallet/api/subaddress.h +++ b/src/wallet/api/subaddress.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,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/wallet/api/subaddress_account.cpp b/src/wallet/api/subaddress_account.cpp index 63354628..6431cc00 100644 --- a/src/wallet/api/subaddress_account.cpp +++ b/src/wallet/api/subaddress_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,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/wallet/api/subaddress_account.h b/src/wallet/api/subaddress_account.h index 22e0e015..d3cacdcf 100644 --- a/src/wallet/api/subaddress_account.h +++ b/src/wallet/api/subaddress_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 @@ -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/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp index 63859623..f48390c9 100644 --- a/src/wallet/api/transaction_history.cpp +++ b/src/wallet/api/transaction_history.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,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/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h index 0afa215e..df155661 100644 --- a/src/wallet/api/transaction_history.h +++ b/src/wallet/api/transaction_history.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,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/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp index c3215da7..84bc71d6 100644 --- a/src/wallet/api/transaction_info.cpp +++ b/src/wallet/api/transaction_info.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,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/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index c580bb85..edbf9f25 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_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 @@ -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/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp index fc0b2463..21b67a2c 100644 --- a/src/wallet/api/unsigned_transaction.cpp +++ b/src/wallet/api/unsigned_transaction.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,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/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h index 1cbb5cea..d639d936 100644 --- a/src/wallet/api/unsigned_transaction.h +++ b/src/wallet/api/unsigned_transaction.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,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/wallet/api/utils.cpp b/src/wallet/api/utils.cpp index 1766e9b2..ab869a32 100644 --- a/src/wallet/api/utils.cpp +++ b/src/wallet/api/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 @@ -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/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index d796a30c..30afec52 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.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,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/wallet/api/wallet.h b/src/wallet/api/wallet.h index a807808e..7a624fb7 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.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,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/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h index ecb864d6..715d9ade 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.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,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/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp index 4d3471a1..784c6726 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.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,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/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index ba15b512..83530dd3 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.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,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/wallet/node_rpc_proxy.cpp b/src/wallet/node_rpc_proxy.cpp index 2c1b0265..d4efde67 100644 --- a/src/wallet/node_rpc_proxy.cpp +++ b/src/wallet/node_rpc_proxy.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,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/wallet/node_rpc_proxy.h b/src/wallet/node_rpc_proxy.h index 4b9a9be2..b947943b 100644 --- a/src/wallet/node_rpc_proxy.h +++ b/src/wallet/node_rpc_proxy.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,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/wallet/ringdb.cpp b/src/wallet/ringdb.cpp index 7f07eb11..e1c67191 100644 --- a/src/wallet/ringdb.cpp +++ b/src/wallet/ringdb.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,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/wallet/ringdb.h b/src/wallet/ringdb.h index 5fbbe36f..fb0d72a8 100644 --- a/src/wallet/ringdb.h +++ b/src/wallet/ringdb.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,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/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 165127fe..bd101b05 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.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,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/wallet/wallet2.h b/src/wallet/wallet2.h index 8c5d4e13..4e8a70b3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.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,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/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index 4d3c0d8a..7ecc2488 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_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 @@ -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/wallet/wallet_args.h b/src/wallet/wallet_args.h index 33711eac..05b5c30f 100644 --- a/src/wallet/wallet_args.h +++ b/src/wallet/wallet_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 @@ -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/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index b9c02c97..bc116a2e 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.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,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/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index f1225572..a15184b0 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_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 @@ -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/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 734b9717..b2508ce8 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_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,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/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 3350dfc6..f25ab0d1 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_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 @@ -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/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index 1198a58d..21e4b686 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_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 @@ -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/tests/crypto/main.cpp b/tests/crypto/main.cpp index 9e52cc70..8fd368c7 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.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. @@ -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/tests/unit_tests/ts_interpolation.cpp b/tests/unit_tests/ts_interpolation.cpp index 837ce34e..b97b2db6 100644 --- a/tests/unit_tests/ts_interpolation.cpp +++ b/tests/unit_tests/ts_interpolation.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. @@ -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 From e7931ca065baba61bf9b7b96ce567f07669d75de Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Sat, 2 Feb 2019 10:20:53 +0000 Subject: [PATCH 02/56] Remove OptimizeCoinbase refresh --- src/simplewallet/simplewallet.cpp | 4 +- src/wallet/wallet2.cpp | 153 +++++++----------------------- src/wallet/wallet2.h | 7 +- 3 files changed, 38 insertions(+), 126 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index cdbe61c6..675832e3 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -293,10 +293,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}, }; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index bd101b05..3d753a8e 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -625,7 +625,7 @@ wallet2::wallet2(network_type nettype, bool restricted) : m_multisig_rescan_info m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), - m_refresh_type(RefreshOptimizeCoinbase), + m_refresh_type(RefreshDefault), m_auto_refresh(true), m_refresh_from_block_height(0), m_explicit_refresh_from_block_height(true), @@ -1062,11 +1062,13 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key"); } - outs.push_back(i); if(tx_scan_info.money_transfered == 0) - { tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device()); - } + + if(!tx_scan_info.money_transfered) + return; + + outs.push_back(i); tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered; tx_scan_info.amount = tx_scan_info.money_transfered; ++num_vouts_received; @@ -1096,34 +1098,27 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote LOG_PRINT_L0("Transaction extra has unsupported format: " << txid); } + tx_extra_pub_key pub_key_field; + if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field)) + { + LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid); + if(m_callback != nullptr) + m_callback->on_skip_transaction(height, txid, tx); + } + else + tx_pub_key = pub_key_field.pub_key; + // Don't try to extract tx public key if tx has no ouputs - size_t pk_index = 0; std::vector tx_scan_info(tx.vout.size()); std::deque output_found(tx.vout.size(), false); // total accumulated received amount (un-filtered) uint64_t total_received_acc = 0; - while(!tx.vout.empty()) + if(!tx.vout.empty() && tx_pub_key != null_pkey) { - // if tx.vout is not empty, we loop through all tx pubkeys - // Holy crap this loop is badly designed... It is an inf loop with two exit breaks below - // \todo scan the blockchain to see if there are any instances of pk not at pk_index 1 - // \todo remove this loop altogether and ignore non-first pk - - tx_extra_pub_key pub_key_field; - if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) - { - if(pk_index > 1) - break; - LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid); - if(0 != m_callback) - m_callback->on_skip_transaction(height, txid, tx); - break; - } - int num_vouts_received = 0; - tx_pub_key = pub_key_field.pub_key; + tools::threadpool &tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; const cryptonote::account_keys &keys = m_account.get_keys(); @@ -1140,58 +1135,26 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::vector additional_tx_pub_keys; std::vector additional_derivations; - if(pk_index == 1) - { - // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses - additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx); - for(size_t i = 0; i < additional_tx_pub_keys.size(); ++i) + // additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses + additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx); + + for(size_t i = 0; i < additional_tx_pub_keys.size(); ++i) + { + additional_derivations.push_back({}); + if(!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back())) { - additional_derivations.push_back({}); - if(!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back())) - { - MWARNING("Failed to generate key derivation from tx pubkey, skipping"); - additional_derivations.pop_back(); - } + MWARNING("Failed to generate key derivation from tx pubkey, skipping"); + additional_derivations.pop_back(); } } + hwdev_lock.unlock(); if(miner_tx && m_refresh_type == RefreshNoCoinbase) { // assume coinbase isn't for us } - else if(miner_tx && m_refresh_type == RefreshOptimizeCoinbase) - { - check_acc_out_precomp_once(tx.vout[0], derivation, additional_derivations, 0, tx_scan_info[0], output_found[0]); - THROW_WALLET_EXCEPTION_IF(tx_scan_info[0].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); - - // this assumes that the miner tx pays a single address - if(tx_scan_info[0].received) - { - // process the other outs from that tx - // the first one was already checked - for(size_t i = 1; i < tx.vout.size(); ++i) - { - tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i, - std::ref(tx_scan_info[i]), std::ref(output_found[i]))); - } - waiter.wait(); - // then scan all outputs from 0 - hwdev_lock.lock(); - hwdev.set_mode(hw::device::NONE); - for(size_t i = 0; i < tx.vout.size(); ++i) - { - THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); - if(tx_scan_info[i].received) - { - hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys, derivation, additional_derivations); - scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); - } - } - hwdev_lock.unlock(); - } - } else if(tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1) { for(size_t i = 0; i < tx.vout.size(); ++i) @@ -1266,7 +1229,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_key_image_known = !m_watch_only && !m_multisig; td.m_key_image_partial = m_multisig; td.m_amount = amount; - td.m_pk_index = pk_index - 1; + td.m_pk_index = 0; td.m_subaddr_index = tx_scan_info[o].received->index; expand_subaddresses(tx_scan_info[o].received->index); if(tx.vout[o].amount == 0) @@ -1336,7 +1299,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_tx = (const cryptonote::transaction_prefix &)tx; td.m_txid = txid; td.m_amount = amount; - td.m_pk_index = pk_index - 1; + td.m_pk_index = 0; td.m_subaddr_index = tx_scan_info[o].received->index; expand_subaddresses(tx_scan_info[o].received->index); if(tx.vout[o].amount == 0) @@ -2808,7 +2771,7 @@ bool wallet2::load_keys(const std::string &keys_file_name, const epee::wipeable_ m_refresh_type = RefreshType::RefreshDefault; if(field_refresh_type_found) { - if(field_refresh_type == RefreshFull || field_refresh_type == RefreshOptimizeCoinbase || field_refresh_type == RefreshNoCoinbase) + if(field_refresh_type == RefreshFull || field_refresh_type == RefreshNoCoinbase) m_refresh_type = (RefreshType)field_refresh_type; else LOG_PRINT_L0("Unknown refresh-type value (" << field_refresh_type << "), using default"); @@ -8449,61 +8412,13 @@ bool wallet2::verify(const std::string &data, const cryptonote::account_public_a crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const { std::vector tx_extra_fields; - if(!parse_tx_extra(td.m_tx.extra, tx_extra_fields)) - { - // Extra may only be partially parsed, it's OK if tx_extra_fields contains public key - } + parse_tx_extra(td.m_tx.extra, tx_extra_fields); - // Due to a previous bug, there might be more than one tx pubkey in extra, one being - // the result of a previously discarded signature. - // For speed, since scanning for outputs is a slow process, we check whether extra - // contains more than one pubkey. If not, the first one is returned. If yes, they're - // checked for whether they yield at least one output tx_extra_pub_key pub_key_field; - THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 0), error::wallet_internal_error, + THROW_WALLET_EXCEPTION_IF(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field), error::wallet_internal_error, "Public key wasn't found in the transaction extra"); - const crypto::public_key tx_pub_key = pub_key_field.pub_key; - bool two_found = find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, 1); - if(!two_found) - { - // easy case, just one found - return tx_pub_key; - } - - // more than one, loop and search - const cryptonote::account_keys &keys = m_account.get_keys(); - size_t pk_index = 0; - hw::device &hwdev = m_account.get_device(); - - const std::vector additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx); - std::vector additional_derivations; - for(size_t i = 0; i < additional_tx_pub_keys.size(); ++i) - { - additional_derivations.push_back({}); - bool r = hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()); - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); - } - - while(find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) - { - const crypto::public_key tx_pub_key = pub_key_field.pub_key; - crypto::key_derivation derivation; - bool r = hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation); - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation"); - - for(size_t i = 0; i < td.m_tx.vout.size(); ++i) - { - tx_scan_info_t tx_scan_info; - check_acc_out_precomp(td.m_tx.vout[i], derivation, additional_derivations, i, tx_scan_info); - if(!tx_scan_info.error && tx_scan_info.received) - return tx_pub_key; - } - } - // we found no key yielding an output - THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, - "Public key yielding at least one output wasn't found in the transaction extra"); - return crypto::null_pkey; + return pub_key_field.pub_key; } bool wallet2::export_key_images(const std::string &filename) const diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 4e8a70b3..c1b03b78 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -166,10 +166,9 @@ class wallet2 enum RefreshType { - RefreshFull, - RefreshOptimizeCoinbase, - RefreshNoCoinbase, - RefreshDefault = RefreshOptimizeCoinbase, + RefreshFull = 0, + RefreshNoCoinbase = 2, + RefreshDefault = RefreshFull, }; static const char *tr(const char *str); From 89d462ae3e4eb682ea1534be2cf610c025c144e4 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Sun, 3 Feb 2019 02:09:42 +0000 Subject: [PATCH 03/56] Ryo 0.4.0.0 - Lorentz Transform --- src/version.cpp.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/version.cpp.in b/src/version.cpp.in index 9487e7cc..4a4a04f3 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,4 +1,4 @@ -#define DEF_RYO_VERSION "0.3.2.0" +#define DEF_RYO_VERSION "0.4.0.0" //! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$ #if defined(GIT_ARCHIVE) @@ -9,7 +9,7 @@ # define DEF_RYO_BRANCH "@GIT_BRANCH@" #endif -#define DEF_RYO_RELEASE_NAME "Pie Orbital" +#define DEF_RYO_RELEASE_NAME "Lorentz Transform" #define DEF_RYO_VERSION_FULL DEF_RYO_VERSION "-" DEF_RYO_VERSION_TAG "/" DEF_RYO_BRANCH #include "version.h" From 33b2463ef764859c6b44aed3a55562d6d1d34df7 Mon Sep 17 00:00:00 2001 From: Ryo-RU <42204984+Ryo-RU@users.noreply.github.com> Date: Sun, 3 Feb 2019 13:57:24 +0000 Subject: [PATCH 04/56] README change --- README.md | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 432e4efb..d21a534e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Ryo -Copyright (c) 2018, Ryo Currency Project +Copyright (c) 2019, Ryo Currency Project Copyright (c) 2014-2017, The Monero Project @@ -18,53 +18,58 @@ Please note that code is developed on the [dev branch](https://github.com/ryo-cu ## Introduction -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. +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. 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. +from the get-go having(1) **Ring Confidential Transactions (RingCT)** (2) and hardcoding **minimum transaction _mixin_ to 25**. These settings significantly reduce the chance of being identified, traced or attacked by blockchain statistical analysis. -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. +Ryo developers implemented, **uniform transaction ID system**. The system hides the very fact that you use payment ID in your transaction, since all transactions now have uniform ID in it. This feature is first of its kind among any Cryptonote currencies and is retrofitted with old payment ID system. + +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 **interchangeable**; 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. ## 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 [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/). -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: [Dev fund explorer](https://ryo-currency.com/dev-fund/) - **Coin symbol**: **RYO** - **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) +- **Hash algorithm**: CryptoNight GPU (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/light-block-reward-by-year.png) -![](https://ryo-currency.com/img/png/dark-block-reward-by-month.png) +![](https://ryo-currency.com/img/png/light-block-reward-by-month-2.png) -![](https://ryo-currency.com/img/png/dark-emission-speed.png) +![](https://ryo-currency.com/img/png/light-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. +## 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. -## About this Project +## About this Project and 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. + +[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) -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). +The authenticity of the checksums can be verified with the [PGP-key's](docs/pgp_keys.md). ## Compiling Ryo from source From 132487b58e39bdc7202a55e8179ea1b5ac44d6ab Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Fri, 15 Feb 2019 16:56:27 +0100 Subject: [PATCH 05/56] Backport typos from Monero --- contrib/epee/include/net/levin_client_async.h | 2 +- contrib/epee/include/net/levin_protocol_handler_async.h | 2 +- src/blockchain_utilities/blockchain_import.cpp | 4 ++-- src/blockchain_utilities/bootstrap_file.cpp | 4 ++-- src/common/password.cpp | 2 +- src/cryptonote_core/blockchain.cpp | 2 +- src/daemon/command_parser_executor.cpp | 2 +- src/daemon/rpc_command_executor.cpp | 2 +- src/rpc/core_rpc_server.cpp | 2 +- src/rpc/rpc_args.cpp | 2 +- src/simplewallet/simplewallet.cpp | 4 ++-- translations/ryo.ts | 4 ++-- translations/ryo_fr.ts | 4 ++-- translations/ryo_it.ts | 4 ++-- translations/ryo_sv.ts | 4 ++-- 15 files changed, 22 insertions(+), 22 deletions(-) diff --git a/contrib/epee/include/net/levin_client_async.h b/contrib/epee/include/net/levin_client_async.h index c0502e1a..a0db5d54 100644 --- a/contrib/epee/include/net/levin_client_async.h +++ b/contrib/epee/include/net/levin_client_async.h @@ -425,7 +425,7 @@ class levin_client_async } 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) << "]"); + LOG_PRINT_L4("LEVIN_PACKET_RECEIVED. [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) << "]"); if(is_request) { diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index e008dc89..4e90a779 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -407,7 +407,7 @@ 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 + MDEBUG(m_connection_context << "LEVIN_PACKET_RECEIVED. [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 diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index dbbbea27..0a2814f1 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -408,7 +408,7 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path { std::cout << refresh_string << "block " << h - 1 << " / " << block_stop - << std::flush; + << "\r" << std::flush; std::cout << ENDL << ENDL; MINFO("Specified block number reached - stopping. block: " << h - 1 << " total blocks: " << h); quit = 1; @@ -444,7 +444,7 @@ int import_from_file(cryptonote::core &core, const std::string &import_file_path { std::cout << refresh_string << "block " << h - 1 << " / " << block_stop - << std::flush; + << "\r" << std::flush; } if(opt_verify) diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index bc50c990..ec218d1a 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -317,7 +317,7 @@ 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; + std::cout << "block " << m_cur_height << "/" << block_stop << "\r" << std::flush; } } // NOTE: use of NUM_BLOCKS_PER_CHUNK is a placeholder in case multi-block chunks are later supported. @@ -496,7 +496,7 @@ 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; + << "block height: " << h - 1 << " " << " \r" << std::flush; // std::cout << refresh_string; MDEBUG("Number bytes scanned: " << bytes_read); diff --git a/src/common/password.cpp b/src/common/password.cpp index ce4c2456..157cf9ed 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -180,7 +180,7 @@ bool read_from_tty(const bool verify, const char *message, epee::wipeable_string while(true) { if(message) - std::cout << message << ": "; + std::cout << message << ": " << std::flush; if(!read_from_tty(pass1)) return false; if(verify) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 00a4719b..edcd2c2d 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -3154,7 +3154,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"); + LOG_PRINT_L2("Using " << print_money(fee_per_kb) << "/kB fee"); //WHO THOUGHT THAT FLOATS IN CONSENSUS CODE ARE A GOOD IDEA????? float kB = (blob_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE) * 1.0f / 1024; diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index 1c0c3204..2af3a629 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -329,7 +329,7 @@ bool t_command_parser_executor::start_mining(const std::vector &arg } if(nettype != cryptonote::MAINNET) - std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << "address, make sure this is intentional!" << std::endl; + std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << " address, make sure this is intentional!" << std::endl; uint64_t threads_count = 1; bool do_background_mining = false; bool ignore_battery = false; diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index f153bae2..f8a930f0 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -562,7 +562,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u if(!first) std::cout << std::endl; std::cout - << "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty + << "height: " << header.height << ", timestamp: " << header.timestamp << ", 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 diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 615dc626..fb8b01fb 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1176,7 +1176,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"); + LOG_ERROR("Failed to get 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)); diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index a217c6e7..d1ccc500 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -113,7 +113,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")); + LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RPC server password --") << arg.rpc_login.name << tr(" cannot be empty")); return boost::none; } diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 675832e3..f38450e0 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -482,7 +482,7 @@ void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon) } 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."); + 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 transaction immediately. Alternatively, connect to another node so the original node cannot correlate information."); } bool check_file_overwrite(const std::string &filename) @@ -2153,7 +2153,7 @@ simple_wallet::simple_wallet() "refresh-type \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 " diff --git a/translations/ryo.ts b/translations/ryo.ts index 3cd0d51a..da19c8fe 100644 --- a/translations/ryo.ts +++ b/translations/ryo.ts @@ -461,7 +461,7 @@ - requires RFC server password -- + requires RPC server password -- @@ -1678,7 +1678,7 @@ If the "tag_description" argument is specified, the tag <tag_name&g refresh-type <full|optimize-coinbase|no-coinbase|default> Set the wallet's refresh behaviour. priority [0|1|2|3|4] - Set the fee too default/unimportant/normal/elevated/priority. + Set the fee to default/unimportant/normal/elevated/priority. confirm-missing-payment-id <1|0> ask-password <1|0> unit <ryo|milliRyo|micoRyo|nanoRyo> diff --git a/translations/ryo_fr.ts b/translations/ryo_fr.ts index 765fee6a..adb70ad4 100644 --- a/translations/ryo_fr.ts +++ b/translations/ryo_fr.ts @@ -461,7 +461,7 @@ - requires RFC server password -- + requires RPC server password -- nécessite le mot de passe du serveur RPC -- @@ -1699,7 +1699,7 @@ Si l'argument "tag_description" est spécifié, le texte arbitrai refresh-type <full|optimize-coinbase|no-coinbase|default> Set the wallet's refresh behaviour. priority [0|1|2|3|4] - Set the fee too default/unimportant/normal/elevated/priority. + Set the fee to default/unimportant/normal/elevated/priority. confirm-missing-payment-id <1|0> ask-password <1|0> unit <ryo|milliRyo|micoRyo|nanoRyo> diff --git a/translations/ryo_it.ts b/translations/ryo_it.ts index fd24dda4..21183390 100644 --- a/translations/ryo_it.ts +++ b/translations/ryo_it.ts @@ -461,7 +461,7 @@ - requires RFC server password -- + requires RP server password -- @@ -1582,7 +1582,7 @@ If the "tag_description" argument is specified, the tag <tag_name&g refresh-type <full|optimize-coinbase|no-coinbase|default> Set the wallet's refresh behaviour. priority [0|1|2|3|4] - Set the fee too default/unimportant/normal/elevated/priority. + Set the fee to default/unimportant/normal/elevated/priority. confirm-missing-payment-id <1|0> ask-password <1|0> unit <ryo|milliRyo|micoRyo|nanoRyo> diff --git a/translations/ryo_sv.ts b/translations/ryo_sv.ts index b746919a..9342b925 100644 --- a/translations/ryo_sv.ts +++ b/translations/ryo_sv.ts @@ -461,7 +461,7 @@ - requires RFC server password -- + requires RPC server password -- kräver lösenord till RPC-server -- @@ -1699,7 +1699,7 @@ Om argumentet "tag_description" anges, sÃ¥ tilldelas taggen <taggna refresh-type <full|optimize-coinbase|no-coinbase|default> Set the wallet's refresh behaviour. priority [0|1|2|3|4] - Set the fee too default/unimportant/normal/elevated/priority. + Set the fee to default/unimportant/normal/elevated/priority. confirm-missing-payment-id <1|0> ask-password <1|0> unit <ryo|milliRyo|micoRyo|nanoRyo> From 11964407c3ebc6ee38d51ae7f7efc9863487b7c7 Mon Sep 17 00:00:00 2001 From: psychocrypt Date: Sat, 16 Feb 2019 21:09:40 +0100 Subject: [PATCH 06/56] fix CI Stop CI as soon as compiling or something else exit with an error. --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04bd608f..02924139 100644 --- a/.travis.yml +++ b/.travis.yml @@ -187,11 +187,11 @@ script: - 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" $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 +201,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 $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'" From d12582fa40a28675561630b5c9fc506b97276e5d Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Wed, 20 Feb 2019 16:56:33 +0000 Subject: [PATCH 07/56] Fix tx serialisation --- .../cryptonote_format_utils.cpp | 17 ++----- .../cryptonote_format_utils.h | 2 +- src/cryptonote_core/cryptonote_tx_utils.cpp | 51 +++++++++---------- src/cryptonote_core/cryptonote_tx_utils.h | 2 +- 4 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index b6120493..7c99cd27 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -526,23 +526,16 @@ 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; } //--------------------------------------------------------------- diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 97ac3bd5..de0217b3 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -90,7 +90,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); diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index c3ee4425..70691819 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -158,8 +158,11 @@ bool construct_miner_tx(cryptonote::network_type nettype, size_t height, size_t 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) +{ + 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) @@ -171,7 +174,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; } @@ -380,6 +383,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std if(use_uniform_pids) { + tx_extra_uniform_payment_id pid; //Add payment id after pubkeys if(payment_id != nullptr) { @@ -389,36 +393,31 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std 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; + } - if(!hwdev.encrypt_payment_id(pid.pid, view_key_pub, tx_key)) - { - LOG_ERROR("Failed to encrypt payment id"); - return false; - } + LOG_PRINT_L2("Encrypting payment id " << 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; - } + crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr, payment_id == nullptr); + if(view_key_pub == null_pkey) + { + LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + return false; + } - LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); + if(!hwdev.encrypt_payment_id(pid.pid, view_key_pub, tx_key)) + { + LOG_ERROR("Failed to encrypt payment id"); + return false; } - else + + if(!add_payment_id_to_tx_extra(tx.extra, pid)) { - add_payment_id_to_tx_extra(tx.extra, nullptr); + LOG_ERROR("Failed to add encrypted payment id to tx extra"); + return false; } + + LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); } else if(payment_id != nullptr) { diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index 23630d68..470794f3 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -105,7 +105,7 @@ 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); From ad5cae0349d8201782c46db685776170bbd5a5f0 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Wed, 20 Feb 2019 16:57:51 +0000 Subject: [PATCH 08/56] Always use uniform pids --- src/cryptonote_core/cryptonote_tx_utils.cpp | 92 ++++++------------- src/cryptonote_core/cryptonote_tx_utils.h | 4 +- src/wallet/wallet2.cpp | 29 +++--- src/wallet/wallet2.h | 2 +- tests/performance_tests/check_tx_signature.h | 6 +- tests/performance_tests/construct_tx.h | 2 +- .../performance_tests/ge_frombytes_vartime.h | 2 +- tests/performance_tests/ge_tobytes.h | 2 +- tests/unit_tests/json_serialization.cpp | 2 +- 9 files changed, 50 insertions(+), 91 deletions(-) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 70691819..67dce350 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -183,7 +183,7 @@ 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(); @@ -381,79 +381,43 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std 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) { - tx_extra_uniform_payment_id pid; - //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; - } - - pid.pid = *payment_id; - } - - LOG_PRINT_L2("Encrypting payment id " << pid.pid.payment_id); - - crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr, payment_id == nullptr); - if(view_key_pub == null_pkey) - { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + LOG_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; - } + LOG_PRINT_L2("Encrypting payment id " << pid.pid.payment_id); - LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); - } - 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; - } + LOG_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)) + { + LOG_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)) + { + LOG_ERROR("Failed to add encrypted payment id to tx extra"); + return false; } + LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); + //check money if(summary_outs_money > summary_inputs_money) { @@ -585,7 +549,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std 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); @@ -606,7 +570,7 @@ bool construct_tx_and_get_tx_key(const account_keys &sender_account_keys, const } 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); + payment_id, tx, unlock_time, tx_key, additional_tx_keys, bulletproof, msout); hwdev.close_tx(); return r; diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index 470794f3..ac07c9f3 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -107,8 +107,8 @@ struct tx_destination_entry //--------------------------------------------------------------- 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/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 3d753a8e..69572a92 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -4773,8 +4773,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f rct::multisig_out msout; bool r = cryptonote::construct_tx_and_get_tx_key(m_account.get_keys(), m_subaddresses, sd.sources, sd.splitted_dsts, sd.change_dts.addr, - sd.payment_id.zero == 0 ? &sd.payment_id : nullptr, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, bulletproof, m_multisig ? &msout : NULL, - use_fork_rules(FORK_UNIFORM_IDS, 0)); + sd.payment_id.zero == 0 ? &sd.payment_id : nullptr, ptx.tx, sd.unlock_time, tx_key, additional_tx_keys, bulletproof, m_multisig ? &msout : NULL); THROW_WALLET_EXCEPTION_IF(!r, error::tx_not_constructed, sd.sources, sd.splitted_dsts, sd.unlock_time, m_nettype); // we don't test tx size, because we don't know the current limit, due to not having a blockchain, @@ -5157,8 +5156,7 @@ bool wallet2::sign_multisig_tx(multisig_tx_set &exported_txs, std::vector> void wallet2::transfer_selected_rct(std::vector dsts, const std::vector &selected_transfers, size_t fake_outputs_count, std::vector> &outs, uint64_t unlock_time, uint64_t fee, - const crypto::uniform_payment_id* payment_id, cryptonote::transaction &tx, pending_tx &ptx, bool bulletproof, bool uniform_pids) + const crypto::uniform_payment_id* payment_id, cryptonote::transaction &tx, pending_tx &ptx, bool bulletproof) { using namespace cryptonote; // throw if attempting a transaction with no destinations @@ -6253,7 +6251,7 @@ void wallet2::transfer_selected_rct(std::vector wallet2::create_transactions_2(std::vector test_ptx.fee) { - transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, payment_id, test_tx, test_ptx, bulletproof, uniform_pid); + transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, payment_id, test_tx, test_ptx, bulletproof); txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(fake_outs_count+1, txBlob.size(), fee_multiplier); LOG_PRINT_L2("Made an attempt at a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); @@ -6994,8 +6991,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_from(const crypton std::vector> outs; const bool bulletproof = use_fork_rules(FORK_BULLETPROOFS, 0); - bool uniform_pid = use_fork_rules(FORK_UNIFORM_IDS, 0); const uint64_t fee_multiplier = get_fee_multiplier(priority); LOG_PRINT_L2("Starting with " << unused_transfers_indices.size() << " non-dust outputs and " << unused_dust_indices.size() << " dust outputs"); @@ -7178,7 +7173,7 @@ std::vector wallet2::create_transactions_from(const crypton LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " << tx.selected_transfers.size() << " outputs"); transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, payment_id, - test_tx, test_ptx, bulletproof, uniform_pid); + test_tx, test_ptx, bulletproof); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(fake_outs_count+1, txBlob.size(), fee_multiplier); available_for_fee = test_ptx.fee + test_ptx.dests[0].amount + test_ptx.change_dts.amount; @@ -7191,7 +7186,7 @@ std::vector wallet2::create_transactions_from(const crypton LOG_PRINT_L2("We made a tx, adjusting fee and saving it"); tx.dsts[0].amount = available_for_fee - needed_fee; transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, payment_id, - test_tx, test_ptx, bulletproof, uniform_pid); + test_tx, test_ptx, bulletproof); txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(fake_outs_count+1, txBlob.size(), fee_multiplier); LOG_PRINT_L2("Made an attempt at a final " << get_size_string(txBlob) << " tx, with " << print_money(test_ptx.fee) << " fee and " << print_money(test_ptx.change_dts.amount) << " change"); @@ -7223,7 +7218,7 @@ std::vector wallet2::create_transactions_from(const crypton cryptonote::transaction test_tx; pending_tx test_ptx; transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.fee, payment_id, - test_tx, test_ptx, bulletproof, uniform_pid); + test_tx, test_ptx, bulletproof); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); tx.tx = test_tx; tx.ptx = test_ptx; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index c1b03b78..de90ffaa 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -690,7 +690,7 @@ class wallet2 uint64_t unlocked_balance_all() const; void transfer_selected_rct(std::vector dsts, const std::vector &selected_transfers, size_t fake_outputs_count, std::vector> &outs, - uint64_t unlock_time, uint64_t fee, const crypto::uniform_payment_id* payment_id, cryptonote::transaction &tx, pending_tx &ptx, bool bulletproof, bool uniform_pids); + uint64_t unlock_time, uint64_t fee, const crypto::uniform_payment_id* payment_id, cryptonote::transaction &tx, pending_tx &ptx, bool bulletproof); void commit_tx(pending_tx &ptx_vector); void commit_tx(std::vector &ptx_vector); diff --git a/tests/performance_tests/check_tx_signature.h b/tests/performance_tests/check_tx_signature.h index f3c3b376..ea15477f 100644 --- a/tests/performance_tests/check_tx_signature.h +++ b/tests/performance_tests/check_tx_signature.h @@ -69,7 +69,7 @@ class test_check_tx_signature : private multi_tx_test_base std::vector additional_tx_keys; std::unordered_map subaddresses; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0, 0}; - if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, BULLETPROOF, nullptr, true)) + if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, BULLETPROOF, nullptr)) return false; get_transaction_prefix_hash(m_tx, m_tx_prefix_hash); @@ -125,7 +125,7 @@ class test_check_tx_signature_aggregated_bulletproofs : private multi_tx_test_ba m_txes.resize(a_num_txes + (extra_outs > 0 ? 1 : 0)); for(size_t n = 0; n < a_num_txes; ++n) { - if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_txes[n], 0, tx_key, additional_tx_keys, true, nullptr, true)) + if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_txes[n], 0, tx_key, additional_tx_keys, true, nullptr)) return false; } @@ -136,7 +136,7 @@ class test_check_tx_signature_aggregated_bulletproofs : private multi_tx_test_ba for(size_t n = 1; n < extra_outs; ++n) destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); - if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_txes.back(), 0, tx_key, additional_tx_keys, true, nullptr, true)) + if(!construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_txes.back(), 0, tx_key, additional_tx_keys, true, nullptr)) return false; } diff --git a/tests/performance_tests/construct_tx.h b/tests/performance_tests/construct_tx.h index b8d57484..f6ebd946 100644 --- a/tests/performance_tests/construct_tx.h +++ b/tests/performance_tests/construct_tx.h @@ -72,7 +72,7 @@ class test_construct_tx : public multi_tx_test_base std::vector additional_tx_keys; std::unordered_map subaddresses; subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0, 0}; - return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr, true); + return cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, this->m_sources, m_destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr); } private: diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h index 9b7180bd..182af459 100644 --- a/tests/performance_tests/ge_frombytes_vartime.h +++ b/tests/performance_tests/ge_frombytes_vartime.h @@ -63,7 +63,7 @@ class test_ge_frombytes_vartime : public multi_tx_test_base<2> subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0, 0}; if(!cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, - this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr, true)) + this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr)) { return false; } diff --git a/tests/performance_tests/ge_tobytes.h b/tests/performance_tests/ge_tobytes.h index 89e50281..d3e4e27f 100644 --- a/tests/performance_tests/ge_tobytes.h +++ b/tests/performance_tests/ge_tobytes.h @@ -63,7 +63,7 @@ class test_ge_tobytes : public multi_tx_test_base<2> subaddresses[this->m_miners[this->real_source_idx].get_keys().m_account_address.m_spend_public_key] = {0, 0}; if(!cryptonote::construct_tx_and_get_tx_key(this->m_miners[this->real_source_idx].get_keys(), subaddresses, - this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr, true)) + this->m_sources, destinations, cryptonote::account_public_address{}, nullptr, m_tx, 0, tx_key, additional_tx_keys, true, nullptr)) { return false; } diff --git a/tests/unit_tests/json_serialization.cpp b/tests/unit_tests/json_serialization.cpp index dd9956ef..e7c0344d 100644 --- a/tests/unit_tests/json_serialization.cpp +++ b/tests/unit_tests/json_serialization.cpp @@ -75,7 +75,7 @@ make_transaction( std::unordered_map subaddresses; subaddresses[from.m_account_address.m_spend_public_key] = {0, 0}; - if(!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, nullptr, tx, 0, tx_key, extra_keys, bulletproof, nullptr, false)) + if(!cryptonote::construct_tx_and_get_tx_key(from, subaddresses, actual_sources, to, boost::none, nullptr, tx, 0, tx_key, extra_keys, bulletproof, nullptr)) throw std::runtime_error{"transaction construction error"}; return tx; From cf6527648d73d3b8fb8bc5bd7e66145b0177c385 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Thu, 21 Feb 2019 11:37:51 +0000 Subject: [PATCH 09/56] Increase to v0.4.0.1 --- src/version.cpp.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.cpp.in b/src/version.cpp.in index 4a4a04f3..2862fb38 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,4 +1,4 @@ -#define DEF_RYO_VERSION "0.4.0.0" +#define DEF_RYO_VERSION "0.4.0.1" //! git will put "#define GIT_ARCHIVE 1" on the next line inside archives. $Format:%n#define GIT_ARCHIVE 1$ #if defined(GIT_ARCHIVE) From 61e4a757eb0baae5743d836062e11a8ca605e0e0 Mon Sep 17 00:00:00 2001 From: psychocrypt Date: Thu, 21 Feb 2019 23:01:34 +0100 Subject: [PATCH 10/56] libunbound: fix MinGW compile derived from https://github.com/monero-project/unbound/pull/11 --- external/unbound/configure_checks.cmake | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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" From e14523752bda3bd3f921ae935076352c081d913e Mon Sep 17 00:00:00 2001 From: mosu forge Date: Fri, 22 Feb 2019 07:23:55 -0800 Subject: [PATCH 11/56] Updated Readme --- README.md | 17 ++++++++--------- doc/pgp_keys.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d21a534e..94ac6631 100644 --- a/README.md +++ b/README.md @@ -41,15 +41,11 @@ Ryo has a very high privacy setting that is suitable for all high confidential t + 1 microRyo = 0.000001 **RYO** (10-6) + 1 milliRyo = 0.001 **RYO** (10-3) - **Hash algorithm**: CryptoNight GPU (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/light-block-reward-by-year.png) +- **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/light-block-reward-by-month-2.png) -![](https://ryo-currency.com/img/png/light-emission-speed.png) - -\* The emulated algorithm of Ryo block-reward emission can be found in Python and C++ scripts at [scripts](scripts) directory. +![](https://ryo-currency.com/img/png/light-emission-speed-2.png) ## 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. @@ -69,7 +65,7 @@ This is the core implementation of Ryo. It is free to get and modify for your ow 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](docs/pgp_keys.md). +The authenticity of the checksums can be verified with the [PGP-key's](doc/pgp_keys.md). ## Compiling Ryo from source @@ -108,9 +104,12 @@ library archives (`.a`). [^] 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 -Clone recursively to pull-in needed submodule(s): +This repo does not use submodules, so simply clone this repo: `$ git clone https://github.com/ryo-currency/ryo-currency.git` @@ -129,7 +128,7 @@ invokes cmake commands as needed. * 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 + git checkout tags/0.4.0.0 make *Optional*: If your machine has several cores and enough memory, enable 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----- +``` From fb78556c310a6d552e7cb6737e1cd726c72a7006 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Mon, 25 Feb 2019 13:22:51 +0000 Subject: [PATCH 12/56] 7zip key images --- utils/burned_premine_keyimages/key_images.7z | Bin 0 -> 155729 bytes .../wallet-dev_key_images.bin | Bin 152418 -> 0 bytes .../wallet1_key_images.bin | 2 -- .../wallet2_key_images.bin | 2 -- .../wallet3_key_images.bin | 3 --- 5 files changed, 7 deletions(-) create mode 100644 utils/burned_premine_keyimages/key_images.7z delete mode 100644 utils/burned_premine_keyimages/wallet-dev_key_images.bin delete mode 100644 utils/burned_premine_keyimages/wallet1_key_images.bin delete mode 100644 utils/burned_premine_keyimages/wallet2_key_images.bin delete mode 100644 utils/burned_premine_keyimages/wallet3_key_images.bin diff --git a/utils/burned_premine_keyimages/key_images.7z b/utils/burned_premine_keyimages/key_images.7z new file mode 100644 index 0000000000000000000000000000000000000000..086125bf268321971cc9088e19bfb073a0670aaf GIT binary patch literal 155729 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®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

J>Cuza2n6dD4$MMAx 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 z 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ótÅv«ÿ•P@¡Íeg,µzfÞ&D€òîz“H¹6Ýù帊6nh˜“3[còWL²”­e}^"*@4£·€#)øžUžH1ˆT²@¦#›µ9!ÙÁbpÈu— -¨×d YS-õ8[§ch¦frÝr÷•=,D»Ñ¬¹§á…,¯G½»,¢í2( ¿ Ä ÕKàeÜýÆThº¨ûÌ›gÄg§¤D~0Y+ßpuJCf#h³Š ÙÒ¥æBX±•ûƒT„¸2Ÿò/(Jb¶o¡þ7†÷ˆ?n7aPh׊æþZTË¢‚udA…ªàWê.‘«ØÍác"¤Z \ No newline at end of file diff --git a/utils/burned_premine_keyimages/wallet2_key_images.bin b/utils/burned_premine_keyimages/wallet2_key_images.bin deleted file mode 100644 index e0507cfe..00000000 --- a/utils/burned_premine_keyimages/wallet2_key_images.bin +++ /dev/null @@ -1,2 +0,0 @@ -Sumokoin key image exportºNˆ\[n£‰ù¯±í¿—cäáÙò´ÑeNjGZÆPWv+.,Oô'4hÒbiÒ!¢½k•$G…Ç}NÛÊ%’`›{é«Ú×óvÿÕ{£@Æ*Ýö1N„Ò€ ¾ gxw £Ä“ª‰ü„\b÷®Ä’&6z»8Ë…ÉîæK@ž–¾ ìæV\ÈQPhî -Ž×ãÎ`D wßøå˜&4kÉÆÿ¯>Œ*ÆìX“à‚hŸi4|„Q'ì“òkaŸoF”‚‰Ôöƒÿ`Ó@m_S$U4|uoUHÙÝdZ3ߧ ä5#‰'¿ \ No newline at end of file diff --git a/utils/burned_premine_keyimages/wallet3_key_images.bin b/utils/burned_premine_keyimages/wallet3_key_images.bin deleted file mode 100644 index 6eafb19a..00000000 --- a/utils/burned_premine_keyimages/wallet3_key_images.bin +++ /dev/null @@ -1,3 +0,0 @@ -Sumokoin key image export: uºp)´:¹1ñbŽ6Bžñ‡:À!åa»Ñ0í›2öó¨ž{˜?'77õ"ÕXop…%¦„™¡÷3:Ñ–=²nž>M Žý©vo’«ßÈ”™ ÷˜—¯¯Ip´;úŒ[@ø³}pˆâÁ‚ÖÅCGa úHj:ŠŒÈÖ|è#!#dìò7ãúEš¤Æ5Œh”äÙ#Äî¡íãDë -òƒž>€K:U ҆иϴ›í_öüNl*‰r‡Éä $ -ÙÝó𭣓gðÑíZ울õ˜·MË›ˆDc !‡— \ No newline at end of file From db7e05fb0c751f89c6785b1b8aa87467806788bf Mon Sep 17 00:00:00 2001 From: Ryo-RU <42204984+Ryo-RU@users.noreply.github.com> Date: Mon, 25 Feb 2019 17:37:15 +0300 Subject: [PATCH 13/56] Create verify_premine_burn_instructions.md --- README.md | 2 +- .../verify_premine_burn_instructions.md | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 utils/burned_premine_keyimages/verify_premine_burn_instructions.md diff --git a/README.md b/README.md index 94ac6631..cd4266b5 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Ryo has a very high privacy setting that is suitable for all high confidential t - **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 [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/). +- 8,790,000 Ryo coins were burned to get rid of the original Sumokoin premine [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](https://github.com/ryo-currency/ryo-currency/tree/master/utils/burned_premine_keyimages/verify_premine_burn_instructions.md) instructions. - 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: [Dev fund explorer](https://ryo-currency.com/dev-fund/) diff --git a/utils/burned_premine_keyimages/verify_premine_burn_instructions.md b/utils/burned_premine_keyimages/verify_premine_burn_instructions.md new file mode 100644 index 00000000..35fb028f --- /dev/null +++ b/utils/burned_premine_keyimages/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) From 0e20734bab4f8a06e0e2d5a8421f6ce3dca949c8 Mon Sep 17 00:00:00 2001 From: psychocrypt Date: Wed, 13 Mar 2019 21:41:26 +0100 Subject: [PATCH 14/56] fix avx2 detection fix #190 AVX2 can be disabled by the OS. This can be detected by checking the osxsave bit. --- src/crypto/pow_hash/cn_slow_hash.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/crypto/pow_hash/cn_slow_hash.hpp b/src/crypto/pow_hash/cn_slow_hash.hpp index c549d33d..437d6d99 100644 --- a/src/crypto/pow_hash/cn_slow_hash.hpp +++ b/src/crypto/pow_hash/cn_slow_hash.hpp @@ -97,7 +97,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 @@ -142,7 +145,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); } From c2f9b91902682eb92dc029625dede9d1a837b48d Mon Sep 17 00:00:00 2001 From: "kylermcmaster@gmail.com" Date: Wed, 3 Apr 2019 20:43:00 -0400 Subject: [PATCH 15/56] feat(docs): Add verbage to the readme to outline the process for importing a raw blockfile --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index cd4266b5..64394342 100644 --- a/README.md +++ b/README.md @@ -487,6 +487,18 @@ 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. +### Importing blockchain data from a raw file + +To bootstrap your local node and speed up synchronization with the network, you can import a raw file containing an export of the blockchain using the following command: + + ./ryo-blockchain-import --input-file /blockchain.raw + +To verify the contents of the blockchain file during import use the `--verify 1` flag. This may affect performance and extend the length of time to import but is recommended if you are downloading your file from an unknown source. + + ./ryo-blockchain-import --verify 1 --input-file /blockchain.raw + +Note: It is important to only import the blockchain file from a trustworthy source whenever possible. + ## Using Tor While Ryo isn't made to integrate with Tor, it can be used wrapped with torsocks, by From 40c0903a1f0dd1cbb7fe53c2e1bba263e6b27e78 Mon Sep 17 00:00:00 2001 From: "kylermcmaster@gmail.com" Date: Sat, 6 Apr 2019 13:08:55 -0400 Subject: [PATCH 16/56] feat(docs): Provide link to Blockchain Utilities docs from main README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 64394342..601e2d15 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,8 @@ To verify the contents of the blockchain file during import use the `--verify 1` Note: It is important to only import the blockchain file from a trustworthy source whenever possible. +For additional information on Ryo's import and export commands as well as other included utilities, see the documentation [here](src/blockchain_utilities/README.md). + ## Using Tor While Ryo isn't made to integrate with Tor, it can be used wrapped with torsocks, by From 9021f43707c9968725f18441044dd0aec8400fe4 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Tue, 7 May 2019 18:30:56 +0100 Subject: [PATCH 17/56] boost 1.7.0 fixes --- CMakeLists.txt | 1 + contrib/epee/include/net/abstract_tcp_server2.inl | 6 +++--- contrib/epee/include/net/net_utils_base.h | 5 +++++ src/simplewallet/simplewallet.cpp | 1 + src/wallet/wallet_args.cpp | 1 + 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82e49066..00300025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -810,6 +810,7 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) + set(Boost_NO_BOOST_CMAKE ON) set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi) set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv) elseif(APPLE OR OPENBSD OR ANDROID) diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index b71607ec..3c12e172 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -204,7 +204,7 @@ bool connection::request_callback() template boost::asio::io_service &connection::get_io_service() { - return socket_.get_io_service(); + return GET_IO_SERVICE(socket_); } //--------------------------------------------------------------------------------- template @@ -367,7 +367,7 @@ bool connection::call_run_once_service_io() 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,7 +378,7 @@ 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); } diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 3c859ece..7a479173 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -363,4 +363,9 @@ inline MAKE_LOGGABLE(connection_context_base, ct, os) } } +#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/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f38450e0..472e39df 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -83,6 +83,7 @@ #include #ifdef WIN32 +#undef fmt #include #include #include diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp index 7ecc2488..05723ead 100644 --- a/src/wallet/wallet_args.cpp +++ b/src/wallet/wallet_args.cpp @@ -53,6 +53,7 @@ #include #if defined(WIN32) +#undef fmt #include #include #endif From 38be2db14ddf2fbe9a4707b9ef9a0b5fb68e974f Mon Sep 17 00:00:00 2001 From: psychocrypt Date: Thu, 9 May 2019 22:03:33 +0200 Subject: [PATCH 18/56] fix boost 1.67 linking --- CMakeLists.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00300025..de3bc34d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,17 @@ 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) + + function (die msg) if (NOT WIN32) string(ASCII 27 Esc) @@ -621,8 +632,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 From b45ca61fe524d6b4d1125bc3b7cbe5a354c786c7 Mon Sep 17 00:00:00 2001 From: psychocrypt Date: Thu, 9 May 2019 23:22:22 +0200 Subject: [PATCH 19/56] travis enforce ubuntu trusty --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 02924139..ee839f2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ cache: apt: true os: linux +dist: trusty addons: apt: From 2d2a8eb963dfc9e449f432af21e2405102acb941 Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Mon, 6 May 2019 11:00:04 +0100 Subject: [PATCH 20/56] Add save wallets tool --- utils/{symlink-wallets.sh => load-wallets.sh} | 0 utils/save-wallets.sh | 3 +++ 2 files changed, 3 insertions(+) rename utils/{symlink-wallets.sh => load-wallets.sh} (100%) create mode 100644 utils/save-wallets.sh diff --git a/utils/symlink-wallets.sh b/utils/load-wallets.sh similarity index 100% rename from utils/symlink-wallets.sh rename to utils/load-wallets.sh diff --git a/utils/save-wallets.sh b/utils/save-wallets.sh new file mode 100644 index 00000000..dd76496d --- /dev/null +++ b/utils/save-wallets.sh @@ -0,0 +1,3 @@ +#!/bin/bash +find build/release/bin -maxdepth 1 -type f -name '*' \! -name 'ryod' \! -name 'ryo-blockchain-export' \! -name 'ryo-wallet-cli' \! -name 'ryo-wallet-rpc' \! -name 'ryo-blockchain-import' \! -name 'ryo-blockchain-usage' \! -name 'ryo-address-validator' \! -name 'ryo-gen-trusted-multisig' \! -name 'ryo-blockchain-blackball' \! -name 'ryo-utils-deserialize' \! -name 'ryo-utils-object-sizes' \! -name '*.log' -exec mv -vn {} test-wallets \; +find build/debug/bin -maxdepth 1 -type f -name '*' \! -name 'ryod' \! -name 'ryo-blockchain-export' \! -name 'ryo-wallet-cli' \! -name 'ryo-wallet-rpc' \! -name 'ryo-blockchain-import' \! -name 'ryo-blockchain-usage' \! -name 'ryo-address-validator' \! -name 'ryo-gen-trusted-multisig' \! -name 'ryo-blockchain-blackball' \! -name 'ryo-utils-deserialize' \! -name 'ryo-utils-object-sizes' \! -name '*.log' -exec mv -vn {} test-wallets \; From 906b08ec186d22ac455e4be36fea5f95fd4d99ac Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Fri, 10 May 2019 18:50:23 +0100 Subject: [PATCH 21/56] libreadline fix on msys2 --- contrib/epee/src/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index c4750cea..09a7266f 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -28,7 +28,7 @@ add_library(epee STATIC hex.cpp http_auth.cpp mlog.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() @@ -59,7 +59,7 @@ target_link_libraries(epee ${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 From 0102ccbfa2262075a7897a5df924f0ad688aa4bf Mon Sep 17 00:00:00 2001 From: fireice-uk Date: Mon, 13 May 2019 10:27:04 +0100 Subject: [PATCH 22/56] gulps Co-authored-by: fireice-uk Co-authored-by: psychocrypt Co-authored-by: benqgg Co-authored-by: CryptoSeyed --- .gitignore | 3 + CMakeLists.txt | 18 +- Doxyfile | 2 +- contrib/epee/demo/demo_http_server/stdafx.h | 3 +- contrib/epee/demo/demo_levin_server/stdafx.h | 3 +- contrib/epee/include/ado_db_helper.h | 25 +- contrib/epee/include/console_handler.h | 32 +- contrib/epee/include/gzip_encoding.h | 6 +- contrib/epee/include/include_base_utils.h | 2 +- contrib/epee/include/misc_language.h | 11 +- contrib/epee/include/misc_log_ex.h | 254 - contrib/epee/include/misc_os_dependent.h | 11 +- .../epee/include/net/abstract_tcp_server.h | 35 +- .../epee/include/net/abstract_tcp_server2.h | 3 +- .../epee/include/net/abstract_tcp_server2.inl | 282 +- .../epee/include/net/abstract_tcp_server_cp.h | 16 +- .../include/net/abstract_tcp_server_cp.inl | 89 +- contrib/epee/include/net/http_auth.h | 3 +- contrib/epee/include/net/http_base.h | 3 +- contrib/epee/include/net/http_client.h | 79 +- contrib/epee/include/net/http_client_base.h | 3 +- .../include/net/http_client_via_api_helper.h | 29 +- .../epee/include/net/http_protocol_handler.h | 5 +- .../include/net/http_protocol_handler.inl | 58 +- contrib/epee/include/net/http_server_cp.h | 3 +- contrib/epee/include/net/http_server_cp2.h | 3 +- .../include/net/http_server_handlers_map2.h | 27 +- .../epee/include/net/http_server_impl_base.h | 19 +- .../include/net/jsonrpc_protocol_handler.h | 20 +- .../include/net/jsonrpc_server_handlers_map.h | 9 +- .../include/net/jsonrpc_server_impl_base.h | 17 +- contrib/epee/include/net/levin_client.inl | 14 +- contrib/epee/include/net/levin_client_async.h | 73 +- contrib/epee/include/net/levin_helper.h | 23 +- .../epee/include/net/levin_protocol_handler.h | 17 +- .../net/levin_protocol_handler_async.h | 97 +- .../include/net/munin_connection_handler.h | 16 +- contrib/epee/include/net/net_helper.h | 71 +- contrib/epee/include/net/net_parse_helpers.h | 15 +- contrib/epee/include/net/net_utils_base.h | 44 +- contrib/epee/include/net/network_throttle.hpp | 2 +- contrib/epee/include/net/protocol_switcher.h | 6 +- contrib/epee/include/net/smtp_helper.h | 14 +- contrib/epee/include/profile_tools.h | 12 +- contrib/epee/include/readline_buffer.h | 10 + contrib/epee/include/reg_utils.h | 4 +- .../serialization/keyvalue_serialization.h | 9 +- .../keyvalue_serialization_overloads.h | 14 +- contrib/epee/include/service_impl_base.h | 64 +- .../include/storages/http_abstract_invoke.h | 21 +- .../include/storages/levin_abstract_invoke2.h | 41 +- .../include/storages/parserse_base_utils.h | 19 +- .../epee/include/storages/portable_storage.h | 110 +- .../storages/portable_storage_from_bin.h | 22 +- .../storages/portable_storage_from_json.h | 52 +- .../storages/portable_storage_to_bin.h | 4 +- .../portable_storage_val_converters.h | 20 +- contrib/epee/include/zlib_helper.h | 6 +- contrib/epee/src/CMakeLists.txt | 6 +- contrib/epee/src/connection_basic.cpp | 19 +- contrib/epee/src/mlog.cpp | 387 -- contrib/epee/src/network_throttle-detail.cpp | 50 +- contrib/epee/src/wipeable_string.cpp | 2 +- contrib/epee/tests/src/misc/test_math.h | 12 +- contrib/epee/tests/src/net/test_net.h | 8 +- .../epee/tests/src/storages/storage_tests.h | 10 +- external/CMakeLists.txt | 3 - external/easylogging++/CMakeLists.txt | 58 - external/easylogging++/ea_config.h | 14 - external/easylogging++/easylogging++.cc | 3723 ------------ external/easylogging++/easylogging++.h | 5261 ----------------- src/address_validator/address_validator.cpp | 27 +- src/blockchain_db/CMakeLists.txt | 1 + src/blockchain_db/blockchain_db.cpp | 35 +- src/blockchain_db/lmdb/db_lmdb.cpp | 383 +- src/blockchain_utilities/CMakeLists.txt | 12 +- .../blockchain_blackball.cpp | 116 +- .../blockchain_export.cpp | 97 +- .../blockchain_import.cpp | 202 +- src/blockchain_utilities/blockchain_usage.cpp | 88 +- src/blockchain_utilities/blocksdat_file.cpp | 33 +- src/blockchain_utilities/bootstrap_file.cpp | 112 +- src/checkpoints/CMakeLists.txt | 1 + src/checkpoints/checkpoints.cpp | 30 +- src/checkpoints/checkpoints.h | 4 +- src/common/CMakeLists.txt | 9 +- src/common/apply_permutation.h | 7 +- src/common/boost_serialization_helper.h | 10 +- src/common/command_line.h | 21 +- src/common/dns_utils.cpp | 69 +- src/common/download.cpp | 66 +- src/common/gulps.hpp | 957 +++ src/common/i18n.cpp | 12 +- src/common/json_util.h | 5 +- src/common/password.cpp | 13 +- src/common/perf_timer.cpp | 25 +- src/common/perf_timer.h | 11 +- src/common/rpc_client.h | 18 +- src/common/scoped_message_writer.h | 47 +- src/common/stack_trace.cpp | 34 +- src/common/string.cpp | 49 + src/common/string.hpp | 54 + src/common/thdq.hpp | 120 + src/common/threadpool.cpp | 11 +- src/common/updates.cpp | 17 +- src/common/util.cpp | 26 +- src/common/util.h | 9 +- src/crypto/CMakeLists.txt | 2 + src/crypto/crypto.h | 14 + src/crypto/hash.h | 14 + src/crypto/random.cpp | 21 +- src/cryptonote_basic/CMakeLists.txt | 1 + src/cryptonote_basic/account.cpp | 19 +- .../cryptonote_basic_impl.cpp | 42 +- src/cryptonote_basic/cryptonote_basic_impl.h | 10 +- .../cryptonote_format_utils.cpp | 120 +- .../cryptonote_format_utils.h | 4 +- src/cryptonote_basic/difficulty.cpp | 16 +- src/cryptonote_basic/hardfork.cpp | 13 +- src/cryptonote_basic/miner.cpp | 119 +- src/cryptonote_core/CMakeLists.txt | 1 + src/cryptonote_core/blockchain.cpp | 684 ++- src/cryptonote_core/cryptonote_core.cpp | 183 +- src/cryptonote_core/cryptonote_tx_utils.cpp | 102 +- src/cryptonote_core/tx_pool.cpp | 136 +- src/cryptonote_protocol/CMakeLists.txt | 1 + src/cryptonote_protocol/block_queue.cpp | 20 +- src/cryptonote_protocol/block_queue.h | 3 +- .../cryptonote_protocol_handler-base.cpp | 15 +- .../cryptonote_protocol_handler.h | 11 +- .../cryptonote_protocol_handler.inl | 375 +- src/daemon/CMakeLists.txt | 3 +- src/daemon/command_line_args.h | 9 +- src/daemon/command_parser_executor.cpp | 91 +- src/daemon/command_server.cpp | 3 +- src/daemon/core.h | 18 +- src/daemon/daemon.cpp | 19 +- src/daemon/daemon.h | 3 +- src/daemon/executor.cpp | 10 +- src/daemon/executor.h | 3 +- src/daemon/main.cpp | 112 +- src/daemon/p2p.h | 21 +- src/daemon/protocol.h | 19 +- src/daemon/rpc.h | 23 +- src/daemon/rpc_command_executor.cpp | 463 +- src/daemon/rpc_command_executor.h | 3 +- src/daemonizer/CMakeLists.txt | 1 + src/daemonizer/posix_daemonizer.inl | 12 +- src/daemonizer/posix_fork.cpp | 8 +- src/daemonizer/windows_daemonizer.inl | 11 +- src/daemonizer/windows_service.cpp | 48 +- src/debug_utilities/cn_deserialize.cpp | 62 +- src/debug_utilities/object_sizes.cpp | 13 +- src/device/CMakeLists.txt | 4 +- src/device/device.cpp | 9 +- src/device/device_default.cpp | 12 +- src/device/device_ledger.cpp | 2 +- src/device/log.cpp | 5 +- src/gen_multisig/CMakeLists.txt | 3 +- src/gen_multisig/gen_multisig.cpp | 57 +- src/mnemonics/CMakeLists.txt | 2 +- src/mnemonics/electrum-words.cpp | 5 +- src/mnemonics/language_base.h | 11 +- src/multisig/CMakeLists.txt | 1 + src/multisig/multisig.cpp | 5 +- src/p2p/CMakeLists.txt | 1 + src/p2p/net_node.h | 10 +- src/p2p/net_node.inl | 313 +- src/p2p/net_peerlist.h | 32 +- src/p2p/p2p_protocol_defs.h | 11 +- src/p2p/stdafx.h | 2 +- src/ringct/CMakeLists.txt | 2 + src/ringct/bulletproofs.cc | 121 +- src/ringct/multiexp.cc | 56 +- src/ringct/multiexp.h | 6 +- src/ringct/rctOps.cpp | 17 +- src/ringct/rctSigs.cpp | 210 +- src/ringct/rctTypes.cpp | 78 +- src/rpc/CMakeLists.txt | 6 + src/rpc/core_rpc_server.cpp | 100 +- src/rpc/daemon_handler.cpp | 21 +- src/rpc/rpc_args.cpp | 14 +- src/rpc/zmq_server.cpp | 15 +- src/serialization/CMakeLists.txt | 2 + src/simplewallet/simplewallet.cpp | 1888 +++--- src/simplewallet/simplewallet.h | 8 +- src/wallet/CMakeLists.txt | 4 +- src/wallet/api/wallet.cpp | 3 +- src/wallet/api/wallet_manager.cpp | 3 +- src/wallet/node_rpc_proxy.cpp | 24 +- src/wallet/ringdb.cpp | 21 +- src/wallet/wallet2.cpp | 741 +-- src/wallet/wallet2.h | 21 - src/wallet/wallet_args.cpp | 123 +- src/wallet/wallet_args.h | 1 - src/wallet/wallet_errors.h | 33 +- src/wallet/wallet_rpc_server.cpp | 98 +- src/wallet/wallet_rpc_server.h | 3 +- src/wallet/wallet_rpc_server_commands_defs.h | 3 +- tests/core_proxy/core_proxy.cpp | 43 +- tests/core_tests/chaingen.cpp | 10 +- tests/core_tests/chaingen.h | 50 +- tests/core_tests/chaingen_main.cpp | 22 +- tests/core_tests/double_spend.cpp | 6 +- tests/core_tests/double_spend.inl | 2 +- tests/core_tests/multisig.cpp | 108 +- tests/core_tests/rct.cpp | 18 +- tests/core_tests/ring_signature_1.cpp | 2 +- tests/core_tests/transaction_tests.cpp | 15 +- tests/core_tests/tx_validation.cpp | 2 +- tests/core_tests/v2_tests.cpp | 6 +- tests/functional_tests/main.cpp | 9 +- .../transactions_flow_test.cpp | 55 +- ...ransactions_generation_from_blockchain.cpp | 9 +- tests/hash/CMakeLists.txt | 3 +- tests/libwallet_api_tests/CMakeLists.txt | 3 +- tests/libwallet_api_tests/main.cpp | 12 +- tests/net_load_tests/CMakeLists.txt | 6 +- tests/net_load_tests/clt.cpp | 52 +- tests/net_load_tests/net_load_tests.h | 8 +- tests/net_load_tests/srv.cpp | 24 +- tests/performance_tests/CMakeLists.txt | 3 +- tests/performance_tests/main.cpp | 6 +- tests/unit_tests/CMakeLists.txt | 3 +- tests/unit_tests/bulletproofs.cpp | 2 +- .../epee_levin_protocol_handler_async.cpp | 10 +- tests/unit_tests/epee_utils.cpp | 2 +- tests/unit_tests/main.cpp | 9 +- tests/unit_tests/memwipe.cpp | 6 +- tests/unit_tests/multisig.cpp | 3 +- tests/unit_tests/subaddress.cpp | 3 +- tests/unit_tests/uri.cpp | 2 +- 232 files changed, 6806 insertions(+), 14853 deletions(-) delete mode 100644 contrib/epee/include/misc_log_ex.h delete mode 100644 contrib/epee/src/mlog.cpp delete mode 100644 external/easylogging++/CMakeLists.txt delete mode 100644 external/easylogging++/ea_config.h delete mode 100644 external/easylogging++/easylogging++.cc delete mode 100644 external/easylogging++/easylogging++.h create mode 100644 src/common/gulps.hpp create mode 100644 src/common/string.cpp create mode 100644 src/common/string.hpp create mode 100644 src/common/thdq.hpp 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/CMakeLists.txt b/CMakeLists.txt index de3bc34d..7751b7d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -259,7 +259,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) @@ -380,10 +380,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 "") @@ -441,8 +437,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 @@ -457,10 +451,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}) @@ -797,6 +787,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) @@ -821,7 +816,6 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) - set(Boost_NO_BOOST_CMAKE ON) set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi) set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv) elseif(APPLE OR OPENBSD OR ANDROID) 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/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/include/ado_db_helper.h b/contrib/epee/include/ado_db_helper.h index cc23bf19..5f5e2e77 100644 --- a/contrib/epee/include/ado_db_helper.h +++ b/contrib/epee/include/ado_db_helper.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. // +#define GULPS_CAT_MAJOR "ado_db_help" #ifndef _DB_ADO_HELPER_H_ #define _DB_ADO_HELPER_H_ @@ -34,6 +35,8 @@ #include #include +#include "common/gulps.hpp" + #define BEGIN_TRY_SECTION() \ try \ { @@ -44,7 +47,7 @@ } \ catch(const std::exception &ex) \ { \ - LOG_PRINT_J("DB_ERROR: " << ex.what(), LOG_LEVEL_0); \ + GULPS_ERRORF("DB_ERROR: {}", ex.what(); \ return ret_val; \ } \ catch(const _com_error &comm_err) \ @@ -54,12 +57,12 @@ const TCHAR *pmessage = comm_err.ErrorMessage(); \ pstr = comm_err.Source(); \ 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); \ + GULPS_ERRORF("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_ERROR("..._ERROR: Unknown error."); \ return ret_val; \ } @@ -352,7 +355,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 +367,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 +959,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); + GULPS_ERRORF("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); + GULPS_PRINTF("New DB Connection added for threadid={}", ::GetCurrentThreadId()); ado_db_helper::execute_helper(conn, "set enable_seqscan=false;"); return conn; } @@ -994,7 +997,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); @@ -1067,8 +1070,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..87a9e061 100644 --- a/contrib/epee/include/console_handler.h +++ b/contrib/epee/include/console_handler.h @@ -23,10 +23,13 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "csl_hand" #pragma once -#include "misc_log_ex.h" #include "string_tools.h" #include #include @@ -41,6 +44,8 @@ #include #include +#include "common/gulps.hpp" + #ifdef HAVE_READLINE #include "readline_buffer.h" #endif @@ -322,14 +327,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_CAT_MAJOR, + "cmd_prompt", __FILE__, __LINE__, std::move(prompt), gulps::COLOR_BOLD_YELLOW, false)); } } @@ -357,11 +360,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 +381,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()); + GULPS_ERRORF("Exception at [console_handler], what={}", ex.what()); } } if(exit_handler) @@ -484,7 +486,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/misc_language.h b/contrib/epee/include/misc_language.h index 542a036c..8ea4537a 100644 --- a/contrib/epee/include/misc_language.h +++ b/contrib/epee/include/misc_language.h @@ -23,12 +23,19 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "msc_lang" #pragma once #include #include #include + +#include "common/gulps.hpp" + namespace epee { #define STD_TRY_BEGIN() \ @@ -39,12 +46,12 @@ namespace epee } \ catch(const std::exception &e) \ { \ - LOG_ERROR("EXCEPTION: " << where_ << ", mes: " << e.what()); \ + GULPS_ERRORF("EXCEPTION: {}, mes: {}", where_, e.what()); \ return ret_val; \ } \ catch(...) \ { \ - LOG_ERROR("EXCEPTION: " << where_); \ + GULPS_ERRORF("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..310374d4 100644 --- a/contrib/epee/include/misc_os_dependent.h +++ b/contrib/epee/include/misc_os_dependent.h @@ -23,6 +23,11 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "msc_os_dep" + #ifdef _WIN32 #include #endif @@ -48,6 +53,8 @@ #include #include +#include "common/gulps.hpp" + #pragma once namespace epee { @@ -92,7 +99,7 @@ inline uint64_t get_tick_count() inline int call_sys_cmd(const std::string &cmd) { - std::cout << "# " << cmd << std::endl; + GULPS_PRINT("# {}", cmd); FILE *fp; //char tstCommand[] ="ls *"; @@ -103,7 +110,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..d13518a4 100644 --- a/contrib/epee/include/net/abstract_tcp_server.h +++ b/contrib/epee/include/net/abstract_tcp_server.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "tcp_srv" #ifndef _ABSTRACT_TCP_SERVER_H_ #define _ABSTRACT_TCP_SERVER_H_ @@ -36,8 +40,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 +61,7 @@ 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_LOGF_ERROR("soket_sender: Failed to send {} bytes, Error={}", cb , sock_err); return false; } return true; @@ -121,7 +126,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); + GULPS_LOGF_L2("Handler thread STARTED with socket={}", pthread_context->m_socket); int res = 0; soket_sender sndr(pthread_context->m_socket); @@ -133,7 +138,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); + GULPS_LOGF_L3("Data in, {} bytes", res ); if(!srv.handle_recv(buff, res)) break; } @@ -141,7 +146,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); + GULPS_LOGF_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 +172,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) << "\""); + GULPS_LOGF_ERROR("Could not find a usable WinSock DLL, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -177,7 +182,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) << "\""); + GULPS_LOGF_ERROR("Failed to create socket, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } @@ -193,7 +198,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); + GULPS_LOGF_L2("Failed to Bind, err = {} \"{}\"", err, socket_errors::get_socket_error_text(err)); deinit_server(); return false; } @@ -217,7 +222,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) << "\""); + GULPS_LOGF_ERROR("Failed to closesocket(), err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); } m_listen_socket = INVALID_SOCKET; } @@ -226,7 +231,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) << "\""); + GULPS_LOGF_ERROR("Failed to WSACleanup(), err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); } m_initialized = false; @@ -247,11 +252,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) << "\""); + GULPS_LOGF_ERROR("Failed to listen, err = {} \"{}\"", err , socket_errors::get_socket_error_text(err) ); return false; } - LOG_PRINT("Listening port " << m_port << "....", LOG_LEVEL_2); + GULPS_LOGF_L2("Listening port {}....", m_port ); while(!m_stop_server) { @@ -266,7 +271,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); + GULPS_LOGF_L2("Accepted connection on socket={}", new_sock); invoke_connection(new_sock, adr_from.sin_addr.s_addr, adr_from.sin_port); } @@ -282,7 +287,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); + GULPS_PRINTF("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..e2076666 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 diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 3c12e172..8823e666 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -29,6 +29,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "tcp_serv" //#include "net_utils_base.h" #include "misc_language.h" @@ -51,8 +55,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 +88,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); + GULPS_LOGF_L1("test, connection constructor set m_connection_type={}", m_connection_type); } PRAGMA_WARNING_DISABLE_VS(4355) //--------------------------------------------------------------------------------- @@ -92,11 +97,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 +127,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 +138,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 +154,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 +180,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); +//GULPS_LOGF_L1("Set ToS flag to {}", tos); #endif boost::asio::ip::tcp::no_delay noDelayOption(false); @@ -183,21 +188,21 @@ 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(); + GULPS_LOGF_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; } //--------------------------------------------------------------------------------- @@ -210,45 +215,45 @@ boost::asio::io_service &connection::get_io_service() 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); + //GULPS_LOGF_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); + //GULPS_LOGF_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(); + GULPS_LOGF_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 +273,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); + GULPS_LOGF_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 +303,7 @@ void connection::handle_read(const boost::system::error_code { do // keep sleeping if we should sleep { - { //_scope_dbg1("CRITICAL_REGION_LOCAL"); + { //_scopeGULPS_LOGF_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 +318,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 +345,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,13 +361,13 @@ 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 @@ -384,13 +388,13 @@ bool connection::call_run_once_service_io() } 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 +410,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 +418,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); + GULPS_LOGF_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 +434,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? + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_LOGF_L1("do_send() DONE ***FAILED*** from packet={} B for ptr={}", cb , ptr); + GULPS_LOGF_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); + GULPS_LOGF_L1("do_send() DONE SPLIT from packet={} B for ptr={}", cb , ptr); - MDEBUG("do_send() m_connection_type = " << m_connection_type); + GULPS_LOGF_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 +476,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 +496,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 +514,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 + GULPS_LOGF_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); + GULPS_LOGF_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"); + GULPS_WARNF("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 +539,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()); + GULPS_LOGF_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"); + GULPS_LOGF_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); + //GULPS_LOGF_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 +601,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 +614,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 +634,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 +648,7 @@ bool connection::close() } return true; - CATCH_ENTRY_L0("connection::close", false); + GULPS_CATCH_ENTRY_L0("connection::close", false); } //--------------------------------------------------------------------------------- template @@ -657,12 +660,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 +681,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 +698,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); + //GULPS_LOGF_L2("(normal){}", size_now); } CRITICAL_REGION_END(); @@ -713,7 +715,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 +723,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 +781,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 +795,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 +805,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 +824,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); + GULPS_ERRORF("Failed to convert port no = {}", port); return false; } return this->init_server(p, address); @@ -832,12 +834,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 +848,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 +868,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); + GULPS_INFOF("Set server type to: {} from name: {}, prefix_name = {}", connection_type , m_thread_name_prefix , prefix_name); } //--------------------------------------------------------------------------------- template @@ -878,10 +880,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 +893,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 +947,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_LOGF_L1("Interrupting thread {}", m_threads[i]->native_handle()); 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 +980,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 +992,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 +1015,20 @@ void boosted_tcp_server::handle_accept(const boost::system:: } else { - _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count); + GULPS_ERRORF("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()); + GULPS_LOGF_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 +1040,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); + GULPS_ERRORF("Failed to resolve {}", adr); return false; } ////////////////////////////////////////////////////////////////////////// @@ -1091,7 +1093,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 << ")"); + GULPS_LOGF_L2("Failed to connect to {}:{}, because of timeout ({})", adr , port , conn_timeout ); return false; } } @@ -1099,13 +1101,13 @@ bool boosted_tcp_server::connect(const std::string &adr, con if(ec || !sock_.is_open()) { - _dbg3("Some problems at connect, message: " << ec.message()); + GULPS_LOGF_L2("Some problems at connect, message: {}", ec.message()); if(sock_.is_open()) sock_.close(); return false; } - _dbg3("Connected success to " << adr << ':' << port); + GULPS_LOGF_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 +1121,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); + GULPS_ERRORF("[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()); + GULPS_LOGF_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 +1151,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); + GULPS_ERRORF("Failed to resolve {}", adr); return false; } ////////////////////////////////////////////////////////////////////////// @@ -1168,7 +1170,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 << ")"); + GULPS_LOGF_L2("Failed to connect to {}:{}, because of timeout ({})", adr , port , conn_timeout ); new_connection_l->socket().close(); } }); @@ -1185,7 +1187,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()); + GULPS_LOGF_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 +1201,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); + GULPS_LOGF_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()); + GULPS_LOGF_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..dc657bd4 100644 --- a/contrib/epee/include/net/abstract_tcp_server_cp.h +++ b/contrib/epee/include/net/abstract_tcp_server_cp.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "tcp_serv" #ifndef _LEVIN_CP_SERVER_H_ #define _LEVIN_CP_SERVER_H_ @@ -33,7 +37,6 @@ #include #include -#include "misc_log_ex.h" //#include "threads_helper.h" #include "syncobj.h" #define ENABLE_PROFILING @@ -41,8 +44,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 @@ -161,7 +165,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); + GULPS_ERRORF("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 +177,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); + GULPS_ERRORF("BIG FAIL: WSASend immediatly complete? but bad results, res={} last_err={}", res, err); query_shutdown(); return false; } @@ -192,7 +196,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..7749ff6f 100644 --- a/contrib/epee/include/net/abstract_tcp_server_cp.inl +++ b/contrib/epee/include/net/abstract_tcp_server_cp.inl @@ -23,11 +23,14 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#undef GULPS_CAT_MAJOR +#define GULPS_CAT_MAJOR "tcp_serv" #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 +57,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 +67,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 +76,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); + GULPS_LOGF_L1("Failed to setsockopt(SO_REUSEADDR), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -88,7 +91,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); + GULPS_LOGF_L1("Failed to Bind, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -97,7 +100,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); + GULPS_LOGF_L1("Failed to CreateIoCompletionPort, err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); deinit_server(); return false; } @@ -123,7 +126,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 +153,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 +169,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); + GULPS_LOGF_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 +188,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); + GULPS_PRINTF("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 +202,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 +236,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 +245,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 +253,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 +267,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); + GULPS_LOGF_L3("WSARecv return immediatily 0, bytes_recvd={}", bytes_recvd); //pconnection->m_tprotocol_handler.handle_recv(pio_data->Buffer, bytes_recvd); } }*/ @@ -279,7 +282,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 +294,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); + GULPS_LOGF_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 +316,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 +324,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 +340,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); + GULPS_LOGF_L2("Socked {} closed, wait_count={}", sock , close_sock_wait_count); return true; } //------------------------------------------------------------- @@ -348,7 +351,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 +369,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); + GULPS_LOGF_L1("Numbers of worker threads started: {}", threads_count); m_stop = false; while(!m_stop) @@ -387,7 +390,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 +413,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); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_LOGF_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 +437,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); + GULPS_LOGF_L2("Connections closed OK (wait_count={})", wait_count ); - LOG_PRINT("Stopping worker threads(" << m_worker_thread_counter << ").", LOG_LEVEL_2); + GULPS_LOGF_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 +452,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); + GULPS_LOGF_L1("Net Server STOPPED, wait_count = {}", wait_count); return true; } //------------------------------------------------------------- @@ -458,7 +461,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 +469,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 +483,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); + // GULPS_LOGF_L2("Failed to CreateIoCompletionPort(associate socket and completion port), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); // return false; //} @@ -512,7 +515,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 +556,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 +565,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/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..5ff9ac62 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "http_client" #pragma once #include @@ -55,8 +59,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; @@ -278,7 +283,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 +341,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); + GULPS_LOGF_L1("Failed to connect to {}:{}", m_host_buff , m_port); return false; } } @@ -365,10 +370,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 +395,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 +432,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 +477,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 +488,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 +504,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 +524,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 +610,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 +637,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 +667,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); + GULPS_LOGF_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 +719,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); + GULPS_LOGF_ERROR("http_stream_filter::handle_chunked(): Wrong state{}", m_chunked_state); return false; } } @@ -724,7 +729,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 +745,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 +759,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 +797,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 +823,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 +839,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 +857,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 +876,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); + GULPS_LOGF_ERROR("Wrong Transfer-Encoding:{}", m_response_info.m_header_info.m_transfer_encoding); m_state = reciev_machine_state_error; return false; } @@ -884,7 +889,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); + GULPS_LOGF_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 +912,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); + GULPS_ERRORF("Undefined transfer type, consider http_body_transfer_connection_close method. header: {}", m_header_cache); return false; } return false; @@ -942,7 +947,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); + GULPS_LOGF_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..373c9370 100644 --- a/contrib/epee/include/net/http_client_via_api_helper.h +++ b/contrib/epee/include/net/http_client_via_api_helper.h @@ -23,14 +23,19 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "http_client" #pragma once #include #include #pragma comment(lib, "Wininet.lib") -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net.http" +#include "common/gulps.hpp" + + namespace epee { @@ -47,7 +52,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); + GULPS_PRINTF("Failed to call InternetOpenA, \nError: {} {}", err , log_space::get_win32_err_descr(err)); return false; } @@ -83,7 +88,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); + GULPS_PRINTF("Failed to call HttpSendRequestA, \nError: {}", log_space::get_win32_err_descr(err)); break; } @@ -96,12 +101,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); + GULPS_PRINTF("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); + GULPS_PRINTF("Wrong server response, HttpQueryInfo returned statuse code{}", code); break; } @@ -113,7 +118,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); + GULPS_PRINTF("Failed to call InternetReadFile, \nError: {}", log_space::get_win32_err_descr(err)); break; } if(readed) @@ -134,7 +139,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); + GULPS_PRINTF("Failed to call InternetCloseHandle, \nError: {}", log_space::get_win32_err_descr(err)); } break; @@ -144,7 +149,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); + GULPS_PRINTF("Failed to call InternetOpenUrlA, \nError: {}", log_space::get_win32_err_descr(err)); return false; } @@ -152,20 +157,20 @@ 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); + GULPS_PRINTF("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); + GULPS_PRINTF("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); + GULPS_PRINTF("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 @@ -96,7 +101,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)); + GULPS_LOGF_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 +121,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)); + GULPS_LOGF_ERROR("Failed to parse header:{}", std::string(it_begin, end_header_it + 2)); return false; } @@ -132,7 +137,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); + GULPS_ERRORF("Failed to match boundary in content type: {}", content_type); return false; } @@ -154,7 +159,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 +182,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 +222,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); + //GULPS_PRINTF("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 +262,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 +277,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 +291,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 +306,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); + GULPS_LOGF_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 +322,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 +357,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 +372,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); + GULPS_LOGF_ERROR("simple_http_connection_handler::handle_invoke_query_line(): Failed to match first line: {}", m_cache); return false; } @@ -391,14 +396,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)); + //GULPS_LOGF_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); + GULPS_LOGF_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 +419,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); + GULPS_LOGF_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 +453,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); + GULPS_LOGF_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 +535,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); + GULPS_LOGF_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 +560,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 +574,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); + //GULPS_PRINTF("HTTP_SEND: << \r\n{}", response_data + response.m_body); - LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" - << response_data); + GULPS_LOGF_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 +598,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 )"); + GULPS_WARNF("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 +606,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..4b5d40d2 100644 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "http_serv" #pragma once #include "http_base.h" @@ -30,15 +34,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_LOGF_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 +75,13 @@ 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_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 << "()"); \ + GULPS_ERRORF("Failed to {}()", #callback_f); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ @@ -86,7 +91,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"); \ + GULPS_LOGF_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) @@ -98,12 +103,12 @@ 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 << "()"); \ + GULPS_ERRORF("Failed to {}()", #callback_f); \ response_info.m_response_code = 500; \ response_info.m_response_comment = "Internal Server Error"; \ return true; \ @@ -113,7 +118,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"); \ + GULPS_LOGF_L1("{}() processed with {}/{}/{}ms", s_pattern, ticks1 - ticks, ticks2 - ticks1, ticks3 - ticks2); \ } #define CHAIN_URI_MAP2(callback) \ @@ -182,7 +187,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_LOGF_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..48403e3c 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "http_serv" #pragma once @@ -32,8 +36,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 { @@ -71,11 +76,11 @@ class http_server_impl_base : public net_utils::http::i_http_server_handler #include @@ -9,6 +14,8 @@ #include "storages/portable_storage.h" #include "storages/portable_storage_template_helper.h" +#include "common/gulps.hpp" + namespace epee { namespace net_utils @@ -97,8 +104,7 @@ class jsonrpc2_connection_handler virtual bool handle_recv(const void *ptr, size_t cb) { std::string buf((const char *)ptr, cb); - LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" - << buf); + GULPS_PRINTF("JSONRPC2_RECV: {}\r\n{}", ptr , buf); bool res = handle_buff_in(buf); return res; @@ -121,7 +127,7 @@ class jsonrpc2_connection_handler m_is_stop_handling = true; if(m_cache.size() > 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 +153,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); + GULPS_LOGF_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); + GULPS_LOGF_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..6a232685 100644 --- a/contrib/epee/include/net/jsonrpc_server_handlers_map.h +++ b/contrib/epee/include/net/jsonrpc_server_handlers_map.h @@ -1,6 +1,11 @@ #ifndef JSONRPC_SERVER_HANDLERS_MAP_H #define JSONRPC_SERVER_HANDLERS_MAP_H +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "jsrpc_serv" + #include "jsonrpc_protocol_handler.h" #include "jsonrpc_structs.h" #include "serialization/keyvalue_serialization.h" @@ -8,6 +13,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 +64,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_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..14c26a86 100644 --- a/contrib/epee/include/net/jsonrpc_server_impl_base.h +++ b/contrib/epee/include/net/jsonrpc_server_impl_base.h @@ -1,6 +1,11 @@ #ifndef JSONRPC_SERVER_IMPL_BASE_H #define JSONRPC_SERVER_IMPL_BASE_H +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "jsrpc_serv" + #include #include @@ -8,6 +13,8 @@ #include "net/jsonrpc_protocol_handler.h" #include "net/jsonrpc_server_handlers_map.h" +#include "common/gulps.hpp" + namespace epee { @@ -31,11 +38,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); + GULPS_PRINTF("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 +51,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); + GULPS_PRINTF("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/levin_client.inl b/contrib/epee/include/net/levin_client.inl index f5a3e3f8..61e0e18e 100644 --- a/contrib/epee/include/net/levin_client.inl +++ b/contrib/epee/include/net/levin_client.inl @@ -26,10 +26,16 @@ //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_cli" + #include "string_tools.h" -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -88,7 +94,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 +152,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 a0db5d54..65f21a0d 100644 --- a/contrib/epee/include/net/levin_client_async.h +++ b/contrib/epee/include/net/levin_client_async.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_cli" #pragma once @@ -30,8 +34,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,10 +44,10 @@ 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) ***********************************************************************/ @@ -74,8 +79,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 +153,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 +173,7 @@ class levin_client_async return false; int err = ::WSAGetLastError(); - LOG_ERROR("Failed to recv(), err = " << err << " \"" << socket_errors::get_socket_error_text(err) << "\""); + GULPS_LOGF_ERROR("Failed to recv(), err = {} '{}'", err , socket_errors::get_socket_error_text(err) ); disconnect(); //reconnect(); return false; @@ -179,7 +184,7 @@ class levin_client_async //reconnect(); return false; } - LOG_PRINT_L4("[" << m_socket << "] RECV " << res); + GULPS_LOGF_L3("[{}] RECV {}", m_socket , res); cb -= res; pbuff += res; } @@ -245,29 +250,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); + GULPS_LOGF_L3("[{}] Sending invoke data", m_socket ); CRITICAL_REGION_BEGIN(m_send_lock); - LOG_PRINT_L4("[" << m_socket << "] SEND " << sizeof(head)); + GULPS_LOGF_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) << "\""); + GULPS_LOGF_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()); + GULPS_LOGF_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) << "\""); + GULPS_LOGF_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) << "]"); + GULPS_LOGF_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 +299,7 @@ class levin_client_async } else { - LOG_PRINT("[" << m_socket << "] Timeout on waiting invoke result. ", LOG_LEVEL_0); + GULPS_PRINTF("[{}] Timeout on waiting invoke result. ", m_socket ); //disconnect(); return LEVIN_ERROR_CONNECTION_TIMEDOUT; } @@ -325,26 +330,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)); + GULPS_LOGF_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) << "\""); + GULPS_LOGF_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()); + GULPS_LOGF_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) << "\""); + GULPS_LOGF_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) << "]"); + GULPS_LOGF_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 +377,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); + GULPS_LOGF_ERROR("Filed to call select, err code = {}", err_code); disconnect(); } else @@ -401,7 +406,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 +414,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 +425,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_RECEIVED. [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) << "]"); + GULPS_LOGF_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 +459,7 @@ class levin_client_async bool reciever_thread() { - LOG_PRINT_L3("[" << m_socket << "] Socket reciever thread started.[m_threads_count=" << m_threads_count << "]"); + GULPS_LOGF_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 +480,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 +489,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 << "]"); + GULPS_LOGF_L3("[{}] Socket reciever thread stopped.[m_threads_count={}]", m_socket , m_threads_count ); return true; } @@ -517,11 +522,11 @@ class levin_client_async if(res == SOCKET_ERROR) { int err_code = ::WSAGetLastError(); - LOG_ERROR("Failed to send, err = " << err_code); + GULPS_LOGF_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) << "]"); + GULPS_LOGF_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 +539,7 @@ class levin_client_async bool handler_thread() { - LOG_PRINT_L3("[" << m_socket << "] Socket handler thread started.[m_threads_count=" << m_threads_count << "]"); + GULPS_LOGF_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 +573,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 << "]"); + GULPS_LOGF_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..f92bb744 100644 --- a/contrib/epee/include/net/levin_helper.h +++ b/contrib/epee/include/net/levin_helper.h @@ -23,14 +23,19 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_help" #pragma once #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 { @@ -79,19 +84,19 @@ bool load_levin_data_from_levin_message(std::string &levin_data, const std::stri { 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; } @@ -106,19 +111,19 @@ bool load_struct_from_levin_message(t_struct &t, const std::string &buff, int &c { 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 +132,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..450a1f58 100644 --- a/contrib/epee/include/net/levin_protocol_handler.h +++ b/contrib/epee/include/net/levin_protocol_handler.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_proto" #ifndef _LEVIN_PROTOCOL_HANDLER_H_ #define _LEVIN_PROTOCOL_HANDLER_H_ @@ -30,8 +34,9 @@ #include "levin_base.h" #include -#undef RYO_DEFAULT_LOG_CATEGORY -#define RYO_DEFAULT_LOG_CATEGORY "net" +#include "common/gulps.hpp" + + namespace epee { @@ -91,7 +96,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 +111,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 +121,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 +163,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 4e90a779..d753b37b 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_proto" #pragma once #include @@ -41,8 +45,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 @@ -165,12 +170,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 +239,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 +290,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 +308,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 +364,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 +395,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 +412,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_RECEIVED. [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 +440,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 +474,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 +492,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 +502,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 +512,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 +578,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 +635,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 +664,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 +707,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 +763,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..5fd6ad88 100644 --- a/contrib/epee/include/net/munin_connection_handler.h +++ b/contrib/epee/include/net/munin_connection_handler.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "mun_conn" #ifndef _MUNIN_CONNECTION_HANDLER_H_ #define _MUNIN_CONNECTION_HANDLER_H_ @@ -47,6 +51,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 @@ -139,9 +145,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 +173,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 +291,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()); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index c42cdd32..c306b2d0 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "net" #pragma once @@ -39,8 +43,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 +134,7 @@ class blocked_mode_client boost::asio::ip::tcp::resolver::iterator end; if(iterator == end) { - LOG_ERROR("Failed to resolve " << addr); + GULPS_LOGF_ERROR("Failed to resolve {}", addr); return false; } @@ -172,18 +177,18 @@ class blocked_mode_client } else { - MWARNING("Some problems at connect, message: " << ec.message()); + GULPS_LOGF_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()); + GULPS_LOGF_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 +210,12 @@ class blocked_mode_client catch(const boost::system::system_error & /*er*/) { - //LOG_ERROR("Some problems at disconnect, message: " << er.what()); + //GULPS_LOGF_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 +249,7 @@ class blocked_mode_client if(ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPS_LOGF_L3("Problems at write: {}", ec.message()); m_connected = false; return false; } @@ -256,12 +261,12 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at connect, message: " << er.what()); + GULPS_LOGF_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 +305,7 @@ class blocked_mode_client if(!writen || ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPS_LOGF_L3("Problems at write: {}", ec.message()); m_connected = false; return false; } @@ -312,13 +317,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at send, message: " << er.what()); + GULPS_LOGF_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 +374,21 @@ class blocked_mode_client if(ec) { - MTRACE("READ ENDS: Connection err_code " << ec.value()); + GULPS_LOGF_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()); + GULPS_LOGF_L1("Problems at read: {}", ec.message()); m_connected = false; return false; } else { - MTRACE("READ ENDS: Success. bytes_tr: " << bytes_transfered); + GULPS_LOGF_L2("READ ENDS: Success. bytes_tr: {}", bytes_transfered); m_deadline.expires_at(std::chrono::steady_clock::time_point::max()); } @@ -396,13 +401,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at read, message: " << er.what()); + GULPS_LOGF_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 +451,7 @@ class blocked_mode_client if(ec) { - LOG_PRINT_L3("Problems at read: " << ec.message()); + GULPS_LOGF_L3("Problems at read: {}", ec.message()); m_connected = false; return false; } @@ -457,7 +462,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()); + GULPS_LOGF_ERROR("Transferred mismatch with transfer_at_least value: m_bytes_transferred={} at_least value={}", bytes_transfered , buff.size()); return false; } @@ -466,13 +471,13 @@ class blocked_mode_client catch(const boost::system::system_error &er) { - LOG_ERROR("Some problems at read, message: " << er.what()); + GULPS_LOGF_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 +492,13 @@ class blocked_mode_client shutdown_ssl(); m_ssl_socket.next_layer().cancel(ec); if(ec) - MDEBUG("Problems at cancel: " << ec.message()); + GULPS_LOGF_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()); + GULPS_LOGF_L1("Problems at shutdown: {}", ec.message()); m_ssl_socket.next_layer().close(ec); if(ec) - MDEBUG("Problems at close: " << ec.message()); + GULPS_LOGF_L1("Problems at close: {}", ec.message()); boost::interprocess::ipcdetail::atomic_write32(&m_shutdowned, 1); m_connected = false; return true; @@ -524,7 +529,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 +561,7 @@ class blocked_mode_client ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) #endif ) - MDEBUG("Problems at ssl shutdown: " << ec.message()); + GULPS_LOGF_L1("Problems at ssl shutdown: {}", ec.message()); } protected: @@ -658,7 +663,7 @@ class async_blocked_mode_client : public blocked_mode_client if(!writen || ec) { - LOG_PRINT_L3("Problems at write: " << ec.message()); + GULPS_LOGF_L3("Problems at write: {}", ec.message()); return false; } else @@ -669,12 +674,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()); + GULPS_LOGF_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 +699,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..d8202006 100644 --- a/contrib/epee/include/net/net_parse_helpers.h +++ b/contrib/epee/include/net/net_parse_helpers.h @@ -23,13 +23,18 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "net" #pragma once #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 +77,7 @@ 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)) @@ -197,14 +199,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()); + GULPS_LOGF_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()); + GULPS_LOGF_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()); + GULPS_LOGF_L1("Found as template as_mutable(): {}", this_ref.str()); else { - MWARNING("Address not found"); + GULPS_WARN("Address not found"); return false; } } @@ -217,7 +219,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,32 +336,12 @@ 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) << "] "; - return os; + 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) } } 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..87171a9b 100644 --- a/contrib/epee/include/net/protocol_switcher.h +++ b/contrib/epee/include/net/protocol_switcher.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "net" #ifndef _PROTOCOL_SWITCHER_H_ #define _PROTOCOL_SWITCHER_H_ @@ -109,7 +113,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_helper.h b/contrib/epee/include/net/smtp_helper.h index 58c52140..8eea054c 100644 --- a/contrib/epee/include/net/smtp_helper.h +++ b/contrib/epee/include/net/smtp_helper.h @@ -23,6 +23,12 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "smtp" + +#include "common/gulps.hpp" #pragma once #include "smtp.h" @@ -40,7 +46,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); + GULPS_PRINTF("Reporting: Failed to connect to server {}:{}", server , port); return false; } @@ -48,7 +54,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); + GULPS_PRINTF("Reporting: Failed to auth on server {}:", server ); return false; } } @@ -64,11 +70,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); + GULPS_PRINTF("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..a1c42e45 100644 --- a/contrib/epee/include/profile_tools.h +++ b/contrib/epee/include/profile_tools.h @@ -23,12 +23,18 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "prof_tools" #ifndef _PROFILE_TOOLS_H_ #define _PROFILE_TOOLS_H_ #include "misc_os_dependent.h" +#include "common/gulps.hpp" + namespace epee { @@ -58,14 +64,14 @@ namespace epee #define WAY_POINT(name) \ { \ uint64_t delta = epee::misc_utils::get_tick_count() - _____way_point_time; \ - MDEBUG("Way point " << name << ": " << delta); \ + GULPS_LOGF_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_LOGF_L1("Way point {}: {}", name, delta); \ _____way_point_time = misc_utils::get_tick_count(); \ } @@ -88,7 +94,7 @@ 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_INFOF("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..bb15d266 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -23,15 +23,20 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "kv_ser" #pragma once #include "enableable.h" #include "keyvalue_serialization_overloads.h" -#include "misc_log_ex.h" #include #include +#include "common/gulps.hpp" + namespace epee { /************************************************************************/ @@ -59,7 +64,7 @@ namespace epee catch(const std::exception &err) \ { \ (void)(err); \ - LOG_ERROR("Exception on unserializing: " << err.what()); \ + GULPS_ERRORF("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..315dbdbb 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -32,7 +32,7 @@ #include #include #include -#include "misc_log_ex.h" +#include "common/gulps.hpp" namespace epee { @@ -65,7 +65,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 +74,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 +113,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 +160,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 +179,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..82e681d2 100644 --- a/contrib/epee/include/service_impl_base.h +++ b/contrib/epee/include/service_impl_base.h @@ -23,12 +23,15 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#define GULPS_CAT_MAJOR "srv_imp_base" #ifndef _SERVICE_IMPL_BASE_H_ #define _SERVICE_IMPL_BASE_H_ #pragma comment(lib, "advapi32.lib") +#include "common/gulps.hpp" + namespace epee { class 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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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)); + GULPS_LOGF_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..a5711526 100644 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -24,6 +24,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "h_abs_inv" #pragma once #include "net/http_base.h" @@ -33,6 +37,8 @@ #include #include +#include "common/gulps.hpp" + namespace epee { namespace net_utils @@ -50,19 +56,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); + //GULPS_LOGF_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; } @@ -79,19 +86,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; } @@ -113,7 +120,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); + GULPS_LOGF_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..7d24d97c 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lev_abs_inv2" #pragma once @@ -30,8 +34,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 { @@ -51,13 +56,13 @@ bool invoke_remote_command2(int command, const t_arg &out_struct, t_result &resu int res = transport.invoke(command, buff_to_send, buff_to_recv); if(res <= 0) { - MERROR("Failed to invoke command " << command << " return code " << res); + GULPS_LOGF_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); + GULPS_LOGF_ERROR("Failed to load_from_binary on command {}", command); return false; } return result_struct.load(stg_ret); @@ -77,7 +82,7 @@ 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_LOGF_ERROR("Failed to notify command {} return code {}", command , res); return false; } return true; @@ -95,13 +100,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); + GULPS_LOGF_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); + GULPS_LOGF_ERROR("Failed to load_from_binary on command {}", command); return false; } return result_struct.load(stg_ret); @@ -118,20 +123,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); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_LOGF_ERROR("Failed to load result struct on command {}", command); cb(LEVIN_ERROR_FORMAT, result_struct, context); return false; } @@ -141,7 +146,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); + GULPS_LOGF_L1("Failed to invoke command {} return code {}", command , res); return false; } return true; @@ -159,7 +164,7 @@ 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_LOGF_ERROR("Failed to notify command {} return code {}", command , res); return false; } return true; @@ -172,7 +177,7 @@ int buff_to_t_adapter(int command, const std::string &in_buff, std::string &buff serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) { - LOG_ERROR("Failed to load_from_binary in command " << command); + GULPS_LOGF_ERROR("Failed to load_from_binary in command {}", command); return -1; } boost::value_initialized in_struct; @@ -180,7 +185,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); + GULPS_LOGF_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 +194,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); + GULPS_LOGF_ERROR("Failed to store_to_binary in command{}", command); return -1; } @@ -202,13 +207,13 @@ int buff_to_t_adapter(t_owner *powner, int command, const std::string &in_buff, serialization::portable_storage strg; if(!strg.load_from_binary(in_buff)) { - LOG_ERROR("Failed to load_from_binary in notify " << command); + GULPS_LOGF_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); + GULPS_LOGF_ERROR("Failed to load in_struct in notify {}", command); return -1; } return cb(command, in_struct, context); @@ -306,7 +311,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_LOGF_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..4cbe0c5c 100644 --- a/contrib/epee/include/storages/parserse_base_utils.h +++ b/contrib/epee/include/storages/parserse_base_utils.h @@ -23,9 +23,16 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "pars_bs_utls" #pragma once +#include "common/gulps.hpp" + + namespace epee { namespace misc_utils @@ -132,7 +139,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 << "\""); + GULPS_PRINTF("Unknown escape sequence :\"\\{}\"", *it); } escape_mode = false; } @@ -150,7 +157,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) { @@ -187,10 +194,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) { @@ -221,10 +228,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..111dadbc 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "prt_strg" #pragma once @@ -34,6 +38,8 @@ #include "portable_storage_to_json.h" #include "portable_storage_val_converters.h" +#include "common/gulps.hpp" + namespace epee { namespace serialization @@ -105,18 +111,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 +133,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 +143,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)); + GULPS_ERRORF("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); + GULPS_ERRORF("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 +183,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 +193,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 +209,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 +219,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 +233,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 +253,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 +308,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 +322,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 +346,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 +379,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 +417,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 +431,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 +456,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..650ecb5f 100644 --- a/contrib/epee/include/storages/portable_storage_from_json.h +++ b/contrib/epee/include/storages/portable_storage_from_json.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "ptb_stg_jsn" #pragma once #include "file_io_utils.h" @@ -32,6 +36,8 @@ #define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100 +#include "common/gulps.hpp" + namespace epee { using namespace misc_utils::parse; @@ -42,18 +48,18 @@ namespace json #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 +175,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 +207,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 +215,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 +226,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 +240,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 +264,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 +301,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 +314,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 +339,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 +354,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"); } } } @@ -414,12 +420,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()); + GULPS_ERRORF("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..fd4c9247 100644 --- a/contrib/epee/include/storages/portable_storage_val_converters.h +++ b/contrib/epee/include/storages/portable_storage_val_converters.h @@ -23,6 +23,10 @@ // (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 GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "val_conv" #pragma once @@ -33,30 +37,32 @@ #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) { 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_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); } @@ -66,7 +72,7 @@ void convert_uint_to_any_int(const from_type &from, to_type &to) 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 } @@ -140,7 +146,7 @@ struct convert_to_integral { static void convert(const std::string &from, uint64_t &to) { - MTRACE("Converting std::string to uint64_t. Source: " << from); + GULPS_LOGF_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..a0728393 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -26,7 +26,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. -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) add_library(epee_readline STATIC readline_buffer.cpp) @@ -53,8 +53,8 @@ endif() target_link_libraries(epee PUBLIC - easylogging ${Boost_FILESYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) @@ -62,7 +62,7 @@ target_link_libraries(epee if (USE_READLINE AND GNU_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..e08a9868 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -31,6 +31,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* rfree: implementation for the non-template base, can be used by connection<> template class in abstract_tcp_server2 file */ +#define GULPS_CAT_MAJOR "conn_basics" #include "net/connection_basic.hpp" @@ -54,7 +55,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 +79,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 +166,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); + GULPS_LOGF_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 +181,7 @@ connection_basic::~connection_basic() noexcept(false) catch(...) { }; - _note("Destructing connection p2p#" << mI->m_peer_number << " to " << remote_addr_str); + GULPS_LOGF_L1("Destructing connection p2p#{} to {}", mI->m_peer_number, remote_addr_str); } void connection_basic::set_rate_up_limit(uint64_t limit) @@ -247,7 +248,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 +261,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 + GULPS_LOGF_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 +281,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)"); + GULPS_LOGF_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)"); + GULPS_LOGF_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..bf37d7c4 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -31,6 +31,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* rfree: implementation for throttle details */ +#define GULPS_CAT_MAJOR "net_tht_det" #include #include @@ -52,7 +53,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 +74,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 +152,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"); + GULPS_INFOF("Setting LIMIT: {} kbps", target); } network_speed_kbps network_throttle::get_target_speed() @@ -173,7 +174,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 << ")"); + GULPS_LOGF_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 +212,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); + GULPS_LOGF_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 +242,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 +316,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); + GULPS_LOGF_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/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/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/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/src/address_validator/address_validator.cpp b/src/address_validator/address_validator.cpp index 1629ecc7..c704b6dc 100644 --- a/src/address_validator/address_validator.cpp +++ b/src/address_validator/address_validator.cpp @@ -42,6 +42,9 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#define GULPS_CAT_MAJOR "addr_val" +#include "common/gulps.hpp" + #include "common/command_line.h" #include "address_validator/address_validator.h" #include "string_tools.h" @@ -99,19 +102,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; } @@ -126,7 +129,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); } @@ -135,14 +142,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); + GULPS_ERRORF("Invalid/Unknown network type {}.", m_network); return 2; } return 0; @@ -203,10 +210,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 == GULPS_CAT_MAJOR && msg.lvl == gulps::LEVEL_ERROR; }); + gulps::inst().add_output(std::move(out)); + using namespace cryptonote; address_validator validator{}; diff --git a/src/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt index 0f41b32a..be7c6368 100644 --- a/src/blockchain_db/CMakeLists.txt +++ b/src/blockchain_db/CMakeLists.txt @@ -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/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 75ae7558..92b42030 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "blockchain_db" #include #include @@ -56,6 +57,8 @@ #include "berkeleydb/db_bdb.h" #endif +#include "common/gulps.hpp" + static const char *db_types[] = { "lmdb", #ifdef BERKELEY_DB @@ -63,8 +66,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; @@ -137,7 +139,7 @@ void BlockchainDB::add_transaction(const crypto::hash &blk_hash, const transacti { // 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 { @@ -157,7 +159,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)) @@ -195,7 +197,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)) @@ -347,23 +349,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); + GULPS_LOGF_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() @@ -498,7 +485,7 @@ 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; } @@ -522,7 +509,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/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 47b921f7..fbea2a90 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -40,12 +40,12 @@ // 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. +#define GULPS_CAT_MAJOR "db_lmdb" #include "db_lmdb.h" #include #include -#include #include // memcpy #include // std::unique_ptr #include @@ -57,8 +57,9 @@ #include "ringct/rctOps.h" #include "string_tools.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "blockchain.db.lmdb" +#include "common/gulps.hpp" + + #if defined(__i386) || defined(__x86_64) #define MISALIGNED_OK 1 @@ -87,14 +88,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; } @@ -336,7 +337,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); @@ -346,7 +347,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 { @@ -356,7 +357,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); } @@ -386,7 +387,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); @@ -394,7 +395,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"); } } @@ -424,7 +425,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; @@ -440,9 +441,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"); + GULPS_GLOBALF_PRINT("LMDB Mapsize increased. Old: {}MiB, New: {}MiB", old / (1024 * 1024), new_mapsize / (1024 * 1024)); mdb_txn_safe::allow_new_txns(); } @@ -471,7 +470,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; @@ -482,14 +481,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"); + GULPS_ERRORF("!! 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; @@ -531,9 +530,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"); + GULPS_GLOBALF_PRINT("LMDB Mapsize increased. Old: {}MiB, New: {}MiB", mei.me_mapsize / (1024 * 1024), new_mapsize / (1024 * 1024)); mdb_txn_safe::allow_new_txns(); } @@ -541,7 +538,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; @@ -557,18 +554,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); + GULPS_LOGF_L1("DB map size: {}", mei.me_mapsize); + GULPS_LOGF_L1("Space used: {}", size_used); + GULPS_LOGF_L1("Space remaining: {}", mei.me_mapsize - size_used); + GULPS_LOGF_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); + GULPS_LOGF_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 @@ -581,7 +578,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; @@ -592,16 +589,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__); + GULPS_LOGF_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); + GULPS_LOGF_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. @@ -610,7 +606,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); + GULPS_LOGF_L1("increase size: {}" , increase_size); } // if threshold_size is 0 (i.e. number of blocks for batch not passed in), it @@ -618,14 +614,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 @@ -648,8 +644,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); + GULPS_LOGF_L1("[{}] m_height: {} block_start: {} block_stop: {}",__func__ , m_height, block_start, block_stop); size_t avg_block_size = 0; if(batch_bytes) { @@ -658,12 +653,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); + GULPS_LOGF_L1("average block size across recent {} blocks: {}", m_cum_count , avg_block_size); m_cum_size = 0; m_cum_count = 0; } @@ -682,12 +677,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); + GULPS_LOGF_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); + GULPS_LOGF_L1("estimated average block size for batch: {}" , avg_block_size); // bigger safety margin on smaller block sizes if(batch_fudge_factor < 5000.0) @@ -699,7 +694,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(); @@ -716,8 +711,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); + GULPS_LOGF_L3("m_height: {}", m_height); + GULPS_LOGF_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; @@ -763,7 +758,7 @@ void BlockchainLMDB::remove_block() { int result; - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); uint64_t m_height = height(); @@ -800,7 +795,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(); @@ -851,7 +846,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; @@ -876,7 +871,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); + GULPS_LOGF_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) @@ -897,7 +892,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(); @@ -955,7 +950,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) @@ -968,7 +963,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); + // GULPS_LOGF_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) @@ -977,14 +972,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")); } @@ -999,7 +994,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); @@ -1037,7 +1032,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; @@ -1055,7 +1050,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; @@ -1075,7 +1070,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")); @@ -1084,7 +1079,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); @@ -1098,14 +1093,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) @@ -1116,7 +1111,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"; @@ -1136,7 +1131,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")); @@ -1157,8 +1152,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()); + GULPS_PRINTF("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"); } @@ -1206,12 +1201,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); + GULPS_LOGF_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(); } @@ -1275,7 +1270,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); + GULPS_LOGF_L2("Setting m_height to: {}", db_stats.ms_entries); uint64_t m_height = db_stats.ms_entries; bool compatible = true; @@ -1287,7 +1282,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 @@ -1317,8 +1312,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; } @@ -1335,7 +1330,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; } } @@ -1350,10 +1345,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(); @@ -1366,7 +1361,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 @@ -1379,13 +1374,13 @@ void BlockchainLMDB::sync() void BlockchainLMDB::safesyncmode(const bool onoff) { - MINFO("switching safe mode " << (onoff ? "on" : "off")); + GULPS_INFOF("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; @@ -1429,7 +1424,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); @@ -1445,7 +1440,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"); } @@ -1453,7 +1448,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; } @@ -1461,7 +1456,7 @@ bool BlockchainLMDB::lock() // TODO: this? void BlockchainLMDB::unlock() { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); } @@ -1524,7 +1519,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; @@ -1554,7 +1549,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; @@ -1581,7 +1576,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; @@ -1626,7 +1621,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(); @@ -1642,7 +1637,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; @@ -1672,7 +1667,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(); @@ -1693,7 +1688,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(); @@ -1722,7 +1717,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(); @@ -1775,7 +1770,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; @@ -2031,7 +2026,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; @@ -2045,7 +2040,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) @@ -2058,7 +2053,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(); @@ -2073,7 +2068,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; @@ -2087,7 +2082,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; @@ -2101,7 +2096,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(); @@ -2127,7 +2122,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"); + GULPS_LOGF_L1("transaction with hash {} not found in db", epee::string_tools::pod_to_hex(h) ); return false; } @@ -2141,7 +2136,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(); @@ -2164,7 +2159,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"); + GULPS_LOGF_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())); @@ -2176,7 +2171,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(); @@ -2197,7 +2192,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(); @@ -2227,7 +2222,7 @@ bool BlockchainLMDB::get_tx_blob(const crypto::hash &h, cryptonote::blobdata &bd uint64_t BlockchainLMDB::get_tx_count() const { - LOG_PRINT_L3("BlockchainLMDB::" << __func__); + GULPS_LOG_L3("BlockchainLMDB::", __func__); check_open(); TXN_PREFIX_RDONLY(); @@ -2244,7 +2239,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; @@ -2258,7 +2253,7 @@ std::vector BlockchainLMDB::get_tx_list(const std::vector offsets; std::vector indices; offsets.push_back(index); @@ -2424,7 +2419,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(); @@ -2438,8 +2433,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())); @@ -2450,7 +2445,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; @@ -2461,7 +2456,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; @@ -2478,7 +2473,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(); @@ -2512,7 +2507,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(); @@ -2565,7 +2560,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(); @@ -2614,7 +2609,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(); @@ -2650,7 +2645,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(); @@ -2672,7 +2667,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) @@ -2747,12 +2742,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; @@ -2772,7 +2767,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) @@ -2782,7 +2777,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 { @@ -2796,12 +2791,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) @@ -2819,18 +2814,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 @@ -2869,13 +2864,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)); } @@ -2890,7 +2885,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. // @@ -2924,7 +2919,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) @@ -2948,7 +2943,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) @@ -2976,7 +2971,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(); @@ -2985,7 +2980,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(); } } @@ -3009,7 +3004,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); @@ -3029,7 +3024,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(); @@ -3056,7 +3051,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(); @@ -3075,7 +3070,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())); @@ -3101,12 +3096,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(); @@ -3136,12 +3131,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); + GULPS_LOGF_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(); @@ -3238,7 +3233,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(); @@ -3283,7 +3278,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); @@ -3300,7 +3295,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); @@ -3319,7 +3314,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(); @@ -3351,7 +3346,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(); } @@ -3368,19 +3363,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 { @@ -3392,10 +3385,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..."); + GULPS_INFOF("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; @@ -3406,7 +3399,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; } @@ -3434,10 +3427,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPS_LOGF_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3502,7 +3493,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); @@ -3512,7 +3503,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; @@ -3533,10 +3524,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPS_LOGF_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3640,7 +3629,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; @@ -3654,7 +3643,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; } @@ -3674,10 +3663,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPS_LOGF_L0("{}/{}\r",i, z); + txn.commit(); result = mdb_txn_begin(m_env, NULL, 0, txn); if(result) @@ -3729,7 +3716,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; @@ -3741,7 +3728,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(); @@ -3749,7 +3736,7 @@ void BlockchainLMDB::migrate_0_1() #define DELETE_DB(x) \ do \ { \ - LOG_PRINT_L1(" " x ":"); \ + GULPS_LOGF_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())); \ @@ -3788,7 +3775,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); @@ -3801,7 +3788,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; } @@ -3832,10 +3819,8 @@ void BlockchainLMDB::migrate_0_1() { if(i) { - LOGIF(el::Level::Info) - { - std::cout << i << " / " << z << " \r" << std::flush; - } + GULPS_LOGF_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_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index cd1508e0..f16103ba 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -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 c4e13f83..76dee4a8 100644 --- a/src/blockchain_utilities/blockchain_blackball.cpp +++ b/src/blockchain_utilities/blockchain_blackball.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "blockch_blackball" #include "cryptonote_core/blockchain.h" #include "blockchain_db/blockchain_db.h" @@ -54,8 +55,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + + namespace po = boost::program_options; using namespace epee; @@ -148,7 +150,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)) { @@ -165,6 +167,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 @@ -177,7 +181,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -191,7 +195,7 @@ int main(int argc, char *argv[]) tools::on_startup(); boost::filesystem::path output_file_path; - + po::options_description desc_cmd_only("Command line options"); po::options_description desc_cmd_sett("Command line options and settings options"); const command_line::arg_descriptor arg_blackball_db_dir = { @@ -225,27 +229,60 @@ int main(int argc, char *argv[]) po::variables_map vm; bool r = command_line::handle_error_helper(desc_options, [&]() { auto parser = po::command_line_parser(argc, argv).options(desc_options).positional(positional_options); - po::store(parser.run(), vm); + po::store(parser.run(), vm); po::notify(vm); return true; }); 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())) + { + GULPS_ERRORF("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); @@ -256,7 +293,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; } @@ -271,11 +308,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()); @@ -288,15 +325,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 << " ..."); + GULPS_PRINTF("Loading blockchain from folder {} ..." , filename); try { @@ -304,13 +341,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()); @@ -318,7 +355,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; } } @@ -326,12 +363,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; @@ -343,7 +380,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) { @@ -363,17 +400,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"); + GULPS_INFOF("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; @@ -384,19 +422,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"); + GULPS_INFOF("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); @@ -412,7 +450,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"); + GULPS_PRINTF("Secondary pass due to {} newly found spent outputs" , newly_spent.size()); std::unordered_set work_spent = std::move(newly_spent); newly_spent.clear(); @@ -434,7 +472,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"); + GULPS_INFOF("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)); @@ -443,8 +481,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 e37a4f4f..e3b1e8c1 100644 --- a/src/blockchain_utilities/blockchain_export.cpp +++ b/src/blockchain_utilities/blockchain_export.cpp @@ -42,6 +42,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#define GULPS_CAT_MAJOR "blockch_export" + #include "blockchain_db/blockchain_db.h" #include "blockchain_db/db_types.h" #include "blocksdat_file.h" @@ -51,12 +53,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" + + namespace po = boost::program_options; using namespace epee; +gulps_log_level log_scr; + int main(int argc, char *argv[]) { #ifdef WIN32 @@ -69,7 +74,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -111,34 +116,68 @@ int main(int argc, char *argv[]) po::variables_map vm; bool r = command_line::handle_error_helper(desc_options, [&]() { - po::store(po::parse_command_line(argc, argv, desc_options), vm); + po::store(po::parse_command_line(argc, argv, desc_options), vm); po::notify(vm); return true; }); if(!r) return 1; - - if(command_line::get_arg(vm, command_line::arg_help)) + + 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)); + + if(!command_line::is_arg_defaulted(vm, arg_log_level)) { - std::cout << "Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")" << ENDL << ENDL; - std::cout << desc_options << std::endl; - return 0; + 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; + } } - - 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()); 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())) + { + GULPS_ERRORF("Failed to parse filter string {}", log_level); + return 1; + } + } + block_stop = command_line::get_arg(vm, arg_block_stop); + + 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)) + { + GULPS_PRINTF("Ryo '{}' ({})\n", RYO_RELEASE_NAME, RYO_VERSION_FULL); + GULPS_PRINT(desc_options); + return 0; + } - 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); 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); @@ -150,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; } @@ -158,7 +197,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. @@ -171,7 +210,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); @@ -179,30 +218,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 << " ..."); + GULPS_PRINTF("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) { @@ -214,9 +253,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 0a2814f1..c9bd4137 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -42,6 +42,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#define GULPS_CAT_MAJOR "blockch_import" + #include #include #include @@ -53,14 +55,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" + + namespace { @@ -118,7 +120,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; } @@ -194,8 +196,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; } @@ -214,8 +216,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; } @@ -229,14 +231,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; } @@ -260,7 +262,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; } @@ -273,16 +275,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); + GULPS_INFOF("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); @@ -291,7 +291,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; } @@ -316,12 +316,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; @@ -356,8 +355,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; } @@ -368,20 +367,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); + GULPS_LOGF_L1("chunk_size: {}" , chunk_size); if(chunk_size > BUFFER_SIZE) { - MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE); + GULPS_WARNF("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); + GULPS_INFOF("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); @@ -389,28 +388,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); + GULPS_ERRORF("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); + GULPS_LOGF_L1("Total bytes read: {}" , bytes_read); if(h > block_stop) { - std::cout << refresh_string << "block " << h - 1 - << " / " << block_stop - << "\r" << std::flush; - std::cout << ENDL << ENDL; - MINFO("Specified block number reached - stopping. block: " << h - 1 << " total blocks: " << h); + GULPS_PRINTF(refresh_string, "block {} / {}\n\n", h - 1, block_stop); + GULPS_INFOF("Specified block number reached - stopping. block: {} total blocks: {}", h - 1, h); quit = 1; break; } @@ -430,21 +426,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); + GULPS_LOGF_L1("loading block number {}" , h - 1); } else { - MDEBUG("loading block number " << h - 1); + GULPS_LOGF_L1("loading block number {}" , h - 1); } b = bp.block; - MDEBUG("block prev_id: " << b.prev_id << ENDL); + GULPS_LOGF_L1("block prev_id: {}", b.prev_id); if((h - 1) % progress_interval == 0) { - std::cout << refresh_string << "block " << h - 1 - << " / " << block_stop - << "\r" << std::flush; + GULPS_PRINTF("{}block {} / {}\r", refresh_string, h - 1, block_stop); } if(opt_verify) @@ -501,8 +495,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; } @@ -513,15 +507,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; + GULPS_PRINTF("\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(); } } @@ -531,8 +525,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); + GULPS_ERRORF("exception while reading from file, height={}: {}", h, e.what()); return 2; } } // while @@ -561,15 +555,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); + GULPS_INFOF("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); + GULPS_INFOF("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 @@ -582,7 +578,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -654,21 +650,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())) + { + GULPS_ERRORF("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)) @@ -683,24 +721,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; @@ -724,33 +753,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); + GULPS_INFOF("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); @@ -761,7 +789,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); @@ -769,15 +797,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()); + GULPS_INFOF("height: {}" , core.get_blockchain_storage().get_current_blockchain_height()); pop_blocks(core, num_blocks); - MINFO("height: " << core.get_blockchain_storage().get_current_blockchain_height()); + GULPS_INFOF("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; @@ -793,12 +821,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 7eb2fce7..8e7e0e4b 100644 --- a/src/blockchain_utilities/blockchain_usage.cpp +++ b/src/blockchain_utilities/blockchain_usage.cpp @@ -42,6 +42,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#define GULPS_CAT_MAJOR "blockch_usage" + #include "cryptonote_core/blockchain.h" #include "blockchain_db/blockchain_db.h" #include "blockchain_db/db_types.h" @@ -53,8 +55,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + + namespace po = boost::program_options; using namespace epee; @@ -97,6 +100,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 @@ -109,7 +114,7 @@ int main(int argc, char *argv[]) } #endif - TRY_ENTRY(); + GULPS_TRY_ENTRY(); epee::string_tools::set_module_name_and_folder(argv[0]); @@ -155,21 +160,54 @@ 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())) + { + GULPS_ERRORF("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); @@ -179,7 +217,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; } @@ -194,7 +232,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); @@ -202,13 +240,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 { @@ -216,21 +254,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); @@ -274,11 +312,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 << "%)"); + GULPS_INFOF("{} 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/blocksdat_file.cpp b/src/blockchain_utilities/blocksdat_file.cpp index d364633f..2a985f61 100644 --- a/src/blockchain_utilities/blocksdat_file.cpp +++ b/src/blockchain_utilities/blocksdat_file.cpp @@ -42,10 +42,13 @@ // 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. +#define GULPS_CAT_MAJOR "blocksdat_file" + #include "blocksdat_file.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + + namespace po = boost::program_options; @@ -66,7 +69,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; } } @@ -74,7 +77,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; } } @@ -82,7 +85,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()) @@ -145,21 +148,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); + GULPS_INFOF("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); + GULPS_INFOF("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); + GULPS_INFOF("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) @@ -173,15 +176,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); + GULPS_PRINTF("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); + GULPS_PRINTF("block {}/{}", m_cur_height - 1, block_stop); - MINFO("Number of blocks exported: " << num_blocks_written); + GULPS_INFOF("Number of blocks exported: {}" , num_blocks_written); return BlocksdatFile::close(); } diff --git a/src/blockchain_utilities/bootstrap_file.cpp b/src/blockchain_utilities/bootstrap_file.cpp index ec218d1a..a668ac28 100644 --- a/src/blockchain_utilities/bootstrap_file.cpp +++ b/src/blockchain_utilities/bootstrap_file.cpp @@ -42,14 +42,17 @@ // 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. +#define GULPS_CAT_MAJOR "bootstr_file" + #include "bootstrap_serialization.h" #include "serialization/binary_utils.h" // dump_binary(), parse_binary() #include "serialization/json_utils.h" // dump_json() #include "bootstrap_file.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "bcutil" +#include "common/gulps.hpp" + + namespace po = boost::program_options; @@ -75,7 +78,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; } } @@ -83,7 +86,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; } } @@ -96,14 +99,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); + GULPS_LOGF_L1("appending to existing file with height: {} total blocks: {}", num_blocks - 1, num_blocks); } m_height = num_blocks; @@ -152,7 +155,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()); + GULPS_LOGF_L1("bootstrap::file_info size: {}", bd.size()); bd_size = bd.size(); if(!::serialization::dump_binary(bd_size, blob)) @@ -163,7 +166,7 @@ bool BootstrapFile::initialize_file() output_stream_header << bd; bd = t_serializable_object_to_blob(bbi); - MDEBUG("bootstrap::blocks_info size: " << bd.size()); + GULPS_LOGF_L1("bootstrap::blocks_info size: {}", bd.size()); bd_size = bd.size(); if(!::serialization::dump_binary(bd_size, blob)) @@ -189,7 +192,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); + GULPS_WARNF("WARNING: chunk_size {} > BUFFER_SIZE {}", chunk_size, BUFFER_SIZE); } std::string blob; @@ -210,14 +213,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); + GULPS_ERRORF("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); + GULPS_LOGF_L1("flushed chunk: chunk_size: {}", chunk_size); } void BootstrapFile::write_block(block &block) @@ -279,10 +282,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; @@ -292,16 +295,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); + GULPS_INFOF("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); + GULPS_INFOF("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); + GULPS_INFOF("Using block height of source blockchain: {}", block_stop); } for(m_cur_height = block_start; m_cur_height <= block_stop; ++m_cur_height) { @@ -316,8 +319,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 << "\r" << std::flush; + GULPS_PRINT(refresh_string); + GULPS_PRINTF("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. @@ -326,12 +329,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); + GULPS_PRINTF( "block {}/{}" , m_cur_height - 1, block_stop ); - MINFO("Number of blocks exported: " << num_blocks_written); + GULPS_INFOF("Number of blocks exported: {}", num_blocks_written); if(num_blocks_written > 0) - MINFO("Largest chunk: " << m_max_chunk << " bytes"); + GULPS_INFOF("Largest chunk: {} bytes", m_max_chunk); return BootstrapFile::close(); } @@ -352,11 +355,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; @@ -366,7 +369,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); + GULPS_INFOF("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"); @@ -377,9 +380,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); + GULPS_INFOF("bootstrap file v {}.{}", unsigned(bfi.major_version), unsigned(bfi.minor_version)); + GULPS_INFOF("bootstrap magic size: {}", sizeof(file_magic)); + GULPS_INFOF("bootstrap header size: {}", bfi.header_size); uint64_t full_header_size = sizeof(file_magic) + bfi.header_size; import_file.seekg(full_header_size); @@ -399,8 +402,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; } @@ -408,35 +411,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); + GULPS_LOGF_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); + GULPS_WARNF("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); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_ERRORF("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; @@ -463,7 +462,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; @@ -473,14 +472,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; @@ -495,22 +494,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 << " " << " \r" << std::flush; + GULPS_PRINTF("\rblock height: {} \r", h - 1); - // std::cout << refresh_string; - MDEBUG("Number bytes scanned: " << bytes_read); + // GULPS_PRINT( refresh_string); + GULPS_LOGF_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"); + GULPS_PRINTF( "Full header length: {} bytes", full_header_size); + GULPS_PRINTF( "Scanned for blocks: {} bytes", bytes_read); + GULPS_PRINTF( "Total: {} bytes", full_header_size + bytes_read); + GULPS_PRINTF("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/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt index 14dbc8c6..c35bd529 100644 --- a/src/checkpoints/CMakeLists.txt +++ b/src/checkpoints/CMakeLists.txt @@ -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 128af1f8..1cba2b3d 100644 --- a/src/checkpoints/checkpoints.cpp +++ b/src/checkpoints/checkpoints.cpp @@ -43,11 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "checkpoints" #include "include_base_utils.h" -using namespace epee; - #include "checkpoints.h" #include "common/dns_utils.h" @@ -56,8 +55,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" + + namespace cryptonote { @@ -94,12 +94,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; @@ -119,12 +119,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); + GULPS_INFOF("CHECKPOINT PASSED FOR HEIGHT {} {}", height, h); return true; } else { - MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h); + GULPS_WARNF("CHECKPOINT FAILED FOR HEIGHT {}. EXPECTED HASH: {}, FETCHED HASH: {}", height, it->second, h); return false; } } @@ -171,7 +171,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; @@ -221,18 +221,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); + GULPS_LOGF_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();) @@ -241,12 +241,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); + GULPS_LOGF_L1("ignoring checkpoint height {}", height); } else { std::string blockhash = it->hash; - LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); + GULPS_LOGF_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 99a0362e..33abfb02 100644 --- a/src/checkpoints/checkpoints.h +++ b/src/checkpoints/checkpoints.h @@ -47,11 +47,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 325632ec..c902e813 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -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 a696a2f2..e08e3ef5 100644 --- a/src/common/apply_permutation.h +++ b/src/common/apply_permutation.h @@ -47,8 +47,7 @@ // https://blogs.msdn.microsoft.com/oldnewthing/20170109-00/?p=95145 #pragma once - -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include #include @@ -60,7 +59,7 @@ 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) { @@ -79,7 +78,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/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index 3ba556cf..d3fb238a 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.h @@ -50,14 +50,14 @@ #include #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_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); @@ -105,13 +105,13 @@ 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_TRY_ENTRY(); std::ifstream data_file; data_file.open(file_path, std::ios_base::binary | std::ios_base::in); @@ -135,6 +135,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.h b/src/common/command_line.h index b8e41182..1ca71eff 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -43,6 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "cmd_line" #pragma once @@ -57,6 +61,9 @@ #include #include +#include "common/gulps.hpp" + + namespace command_line { @@ -206,7 +213,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; } @@ -218,7 +225,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; } @@ -230,7 +237,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; } @@ -259,14 +266,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; + GULPS_ERRORF("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/dns_utils.cpp b/src/common/dns_utils.cpp index e2ad88b9..d7231106 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "dns_utils" #include "common/dns_utils.h" // check local first (in the event of static or in-source compilation of libunbound) @@ -53,11 +54,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" + + static const char *DEFAULT_DNS_PUBLIC_ADDR[] = { @@ -88,27 +89,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-----" ; } */ @@ -236,12 +237,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)"); + GULPS_INFOF("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"); } } @@ -265,7 +266,7 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData()) const char * const *ds = ::get_builtin_ds(); while (*ds) { - MINFO("adding trust anchor: " << *ds); + GULPS_INFOF("adding trust anchor: {}", *ds); ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++)); } } @@ -426,12 +427,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."); + GULPS_LOGF_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."); + GULPS_LOGF_L2("DNSSEC validation failed for checkpoint update at URL: {}, skipping.", url); } cur_index++; @@ -453,7 +454,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; } @@ -477,7 +478,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; } @@ -494,13 +495,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)"); + GULPS_LOGF_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"); + GULPS_ERRORF("Invalid IP: {}, using default", s); } else { @@ -509,7 +510,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/download.cpp b/src/common/download.cpp index 4fc20619..3eae05fc 100644 --- a/src/common/download.cpp +++ b/src/common/download.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "download" #include "download.h" #include "cryptonote_config.h" @@ -53,8 +54,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "net.dl" +#include "common/gulps.hpp" + + namespace tools { @@ -82,7 +84,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 { @@ -98,19 +100,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); + GULPS_INFOF("Resuming downloading {} to {} from {}", control->uri , control->path , existing_size); mode |= std::ios_base::app; } else { - MINFO("Downloading " << control->uri << " to " << control->path); + GULPS_INFOF("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); + GULPS_ERRORF("Failed to open file {}", control->path); control->result_cb(control->path, control->uri, control->success); return; } @@ -122,18 +124,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); + GULPS_LOGF_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); + GULPS_INFOF("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)"); + GULPS_ERRORF("Not enough space to download {} kB to {} ({} kB available)", needed, path.string(), avail); return false; } } @@ -152,7 +154,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); } @@ -174,7 +176,7 @@ static void download_thread(download_async_handle control) } catch(const std::exception &e) { - MERROR("Error writing data: " << e.what()); + GULPS_ERRORF("Error writing data: {}", e.what()); return false; } } @@ -189,13 +191,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); + GULPS_ERRORF("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); + GULPS_ERRORF("Failed to determine address from URL {}", control->uri); control->result_cb(control->path, control->uri, control->success); return; } @@ -204,28 +206,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); + GULPS_LOGF_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); + GULPS_ERRORF("Failed to connect to {}", control->uri); control->result_cb(control->path, control->uri, control->success); return; } - MDEBUG("GETting " << u_c.uri); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_ERRORF("Failed to connect to {}", control->uri); client.disconnect(); control->result_cb(control->path, control->uri, control->success); return; @@ -233,7 +235,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; @@ -241,28 +243,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"); + GULPS_ERRORF("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); + GULPS_LOGF_L1("response code: {}", info->m_response_code); + GULPS_LOGF_L1("response length: {}", info->m_header_info.m_content_length); + GULPS_LOGF_L1("response comment: {}", info->m_response_comment); + GULPS_LOGF_L1("response body: {}", info->m_body); for(const auto &f : info->m_additional_fields) - MDEBUG("additional field: " << f.first << ": " << f.second); + GULPS_LOGF_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); + GULPS_ERRORF("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); @@ -270,7 +272,7 @@ static void download_thread(download_async_handle control) } catch(const std::exception &e) { - MERROR("Exception in download thread: " << e.what()); + GULPS_ERRORF("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); @@ -294,21 +296,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) @@ -320,7 +322,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/gulps.hpp b/src/common/gulps.hpp new file mode 100644 index 00000000..a1c5d207 --- /dev/null +++ b/src/common/gulps.hpp @@ -0,0 +1,957 @@ +// 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() + { + while(msg_q.wait_for_pop()) + { + message msg = msg_q.pop(); + 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); + + 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.emplace_back(std::move(vcat[0]), level); + else + wildcard_level = level; + } + + 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; + }; +}; + +#ifndef GULPS_CAT_MAJOR +#define GULPS_CAT_MAJOR "default" +#endif + +#ifndef GULPS_CAT_MINOR +#define GULPS_CAT_MINOR "" +#endif + +#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_CAT_MAJOR, "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_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_PRINT_CLR(clr, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, clr, __VA_ARGS__) +#define GULPS_ERROR(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_WARN(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_INFO(...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_INFO_CLR(clr, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, clr, __VA_ARGS__) + + +#define GULPS_DEBUG_PRINT(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_ERROR(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_WARN(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L0(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L1(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L2(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOG_L3(...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPS_PRINTF(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_PRINTF_CLR(clr, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, clr, __VA_ARGS__) +#define GULPS_ERRORF(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_WARNF(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_INFOF(...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_INFOF_CLR(clr, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, clr, __VA_ARGS__) + + +#define GULPS_DEBUG_PRINTF(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_ERROR(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_WARN(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_L0(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_L1(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_L2(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_LOGF_L3(...) GULPS_OUTPUTF(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPS_CAT_PRINT(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_PRINT_CLR(clr, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, min, clr, __VA_ARGS__) +#define GULPS_CAT_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, min, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_CAT_WARN(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, min, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_CAT_INFO(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_INFO_CLR(clr, min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, min, clr, __VA_ARGS__) + +#define GULPS_CAT_DEBUG_PRINT(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_WARN(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L0(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L1(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L2(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CAT_LOG_L3(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_TRACE2, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) + +#define GULPS_CATF_PRINT(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CATF_PRINT_CLR(clr, min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, min, clr, __VA_ARGS__) +#define GULPS_CATF_ERROR(min, ...) GULPS_OUTPUT(gulps::OUT_USER_0, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, min, gulps::COLOR_BOLD_RED, __VA_ARGS__) +#define GULPS_CATF_WARN(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_WARN, GULPS_CAT_MAJOR, min, gulps::COLOR_BOLD_YELLOW, __VA_ARGS__) +#define GULPS_CATF_INFO(min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, min, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_CATF_INFO_CLR(clr, min, ...) GULPS_OUTPUTF(gulps::OUT_USER_0, gulps::LEVEL_INFO, GULPS_CAT_MAJOR, min, clr, __VA_ARGS__) + +#define GULPS_CATF_LOG_L1(min, ...) GULPS_OUTPUT(gulps::OUT_LOG_0, gulps::LEVEL_DEBUG, GULPS_CAT_MAJOR, 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 GULPS_CAT2F_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 GULPS_VERIFYF_ERR_TX(...) GULPS_CAT2F_LOG_ERROR("verify", "tx", __VA_ARGS__) +#define GULPS_VERIFYF_ERR_BLK(...) GULPS_CAT2F_LOG_ERROR("verify", "block", __VA_ARGS__) + +#define GULPS_GLOBAL_PRINT(...) GULPS_CAT_PRINT_CLR(gulps::COLOR_CYAN, "global", __VA_ARGS__) +#define GULPS_GLOBALF_PRINT(...) GULPS_CATF_PRINT_CLR(gulps::COLOR_CYAN, "global", __VA_ARGS__) + +#define GULPS_GLOBAL_PRINT_CLR(clr, ...) GULPS_CAT_PRINT_CLR(clr, "global", __VA_ARGS__) +#define GULPS_GLOBALF_PRINT_CLR(clr, ...) GULPS_CATF_PRINT_CLR(clr, "global", __VA_ARGS__) + +/* +#define GULPS_ERROR(...) GULPS_OUTPUT(gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::red, __VA_ARGS__) +#define GULPS_WARN(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_WARN, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::orange, fstr, __VA_ARGS__) +#define GULPS_INFO(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_INFO, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG0(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_LOG_0, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG1(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_DEBUG_1, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_DEBUG2(fstr, ...) GULPS_OUTPUT(gulps::LEVEL_DEBUG_2, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, fmt::color::white, fstr, __VA_ARGS__) +#define GULPS_PRINT(clr, fstr, ...) GULPS_OUTPUT(gulps::LEVEL_OUTPUT_0, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, 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/i18n.cpp b/src/common/i18n.cpp index fffbe5de..82232c91 100644 --- a/src/common/i18n.cpp +++ b/src/common/i18n.cpp @@ -41,6 +41,11 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "i18n" + #include "common/i18n.h" #include "common/util.h" @@ -53,8 +58,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "i18n" +#include "common/gulps.hpp" + + static const unsigned char qm_magic[16] = {0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95, 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd}; @@ -62,7 +68,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 { GULPS_LOGF_0("{}:{}:{}", __FILE__, __LINE__, x); } while(0) #define i18n_log(x) ((void)0) std::string i18n_get_language() diff --git a/src/common/json_util.h b/src/common/json_util.h index edc43a3b..684c0547 100644 --- a/src/common/json_util.h +++ b/src/common/json_util.h @@ -41,7 +41,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) \ @@ -58,13 +57,13 @@ } \ else \ { \ - LOG_ERROR("Field " << #name << " found in JSON, but not " << #jtype); \ + GULPS_LOGF_ERROR("Field {} found in JSON, but not {}", #name, #jtype); \ return false; \ } \ } \ else if(mandatory) \ { \ - LOG_ERROR("Field " << #name << " not found in JSON"); \ + GULPS_LOGF_ERROR("Field {} not found in JSON", #name); \ return false; \ } \ while(0) diff --git a/src/common/password.cpp b/src/common/password.cpp index 157cf9ed..dc0304f9 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "password" #include "password.h" @@ -60,6 +61,8 @@ #include "memwipe.h" +#include "common/gulps.hpp" + #define EOT 0x4 namespace @@ -95,7 +98,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) @@ -154,7 +157,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) @@ -180,17 +183,17 @@ bool read_from_tty(const bool verify, const char *message, epee::wipeable_string while(true) { if(message) - std::cout << message << ": " << std::flush; + 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/perf_timer.cpp b/src/common/perf_timer.cpp index 535ba4de..23a8ad36 100644 --- a/src/common/perf_timer.cpp +++ b/src/common/perf_timer.cpp @@ -41,13 +41,14 @@ // 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. +#define GULPS_CAT_MAJOR "perf_timer" + #include "perf_timer.h" #include "misc_os_dependent.h" #include -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "perf" +#include "common/gulps.hpp" namespace tools { @@ -99,16 +100,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; + GULPS_ERRORF("Wrong log level: {}, using Debug", gulps::level_to_str(level)); + level = gulps::LEVEL_DEBUG; } performance_timer_log_level = level; } @@ -121,11 +122,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 } @@ -138,7 +140,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; } } @@ -161,7 +163,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 bbf61a15..6a0e9e09 100644 --- a/src/common/perf_timer.h +++ b/src/common/perf_timer.h @@ -44,7 +44,7 @@ #pragma once -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include #include #include @@ -54,7 +54,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(); @@ -79,23 +79,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 4fe71a2d..d046cd56 100644 --- a/src/common/rpc_client.h +++ b/src/common/rpc_client.h @@ -41,6 +41,10 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "perf_timer" #pragma once @@ -54,6 +58,8 @@ #include "storages/http_abstract_invoke.h" #include "string_tools.h" +#include "common/gulps.hpp" + namespace tools { class t_rpc_client final @@ -79,13 +85,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(); + GULPS_ERRORF("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 @@ -103,13 +109,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(); + GULPS_ERRORF("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; + GULPS_ERRORF("{} -- json_rpc_request: ", fail_msg, res.status); return false; } else @@ -127,13 +133,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(); + GULPS_ERRORF("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; + GULPS_ERRORF("{}-- 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 ce5d6b5c..e6c12c39 100644 --- a/src/common/scoped_message_writer.h +++ b/src/common/scoped_message_writer.h @@ -41,19 +41,17 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "scpd_msg_wrt" #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 { @@ -66,14 +64,13 @@ class scoped_message_writer 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; } @@ -111,37 +108,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_CAT_MAJOR, "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/stack_trace.cpp b/src/common/stack_trace.cpp index 9e9b1225..26ba5548 100644 --- a/src/common/stack_trace.cpp +++ b/src/common/stack_trace.cpp @@ -41,13 +41,14 @@ // 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. +#define GULPS_CAT_MAJOR "stk_trace" + #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 @@ -59,13 +60,10 @@ #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 // from http://stackoverflow.com/questions/11665829/how-can-i-print-stack-trace-for-caught-exceptions-in-c-code-injection-in-c @@ -136,18 +134,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) @@ -155,34 +153,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); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_LOGF_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/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..1b7a61f6 --- /dev/null +++ b/src/common/thdq.hpp @@ -0,0 +1,120 @@ +// 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: + thdq() : lck_(mutex_, std::defer_lock) {} + + bool pop(T& item) + { + std::unique_lock mlock(mutex_); + while (queue_.empty() && !finish) { cond_.wait(mlock); } + bool ret = false; + if(!queue_.empty()) + { + item = std::move(queue_.front()); + queue_.pop(); + ret = true; + } + return ret; + } + + bool wait_for_pop() + { + lck_.lock(); + while (queue_.empty() && !finish) { cond_.wait(lck_); } + bool has_pop = !queue_.empty(); + if(!has_pop) lck_.unlock(); + return has_pop; + } + + T pop() + { + T item = std::move(queue_.front()); + queue_.pop(); + lck_.unlock(); + 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_one(); + } + +private: + std::queue queue_; + std::mutex mutex_; + std::condition_variable cond_; + std::unique_lock lck_; + bool finish = false; +}; diff --git a/src/common/threadpool.cpp b/src/common/threadpool.cpp index 31f6bab2..bd1ea617 100644 --- a/src/common/threadpool.cpp +++ b/src/common/threadpool.cpp @@ -41,8 +41,13 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "thdpool" + + #include "common/threadpool.h" -#include "misc_log_ex.h" #include #include @@ -51,6 +56,8 @@ #include "common/util.h" #include "cryptonote_config.h" +#include "common/gulps.hpp" + static __thread int depth = 0; namespace tools @@ -112,7 +119,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/updates.cpp b/src/common/updates.cpp index 4663f99b..08c87d61 100644 --- a/src/common/updates.cpp +++ b/src/common/updates.cpp @@ -41,15 +41,16 @@ // 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. +#define GULPS_CAT_MAJOR "updates" #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" + + namespace tools { @@ -60,7 +61,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); + GULPS_LOGF_L0("Checking updates for {} {}", buildtag, software); // All four MoneroPulse domains have DNSSEC on and valid static const std::vector dns_urls = { @@ -79,7 +80,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; } @@ -92,7 +93,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; } @@ -103,13 +104,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); + GULPS_WARNF("Two matches found for {} verion {} on {}", software, version, buildtag); } version = fields[2]; hash = fields[3]; - MINFO("Found new version " << version << " with hash " << hash); + GULPS_INFOF("Found new version {} with has {}", version, hash); found = true; } return found; diff --git a/src/common/util.cpp b/src/common/util.cpp index 3f129d7c..8cd89ed5 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -78,6 +78,7 @@ using namespace epee; #include #include + namespace tools { std::function signal_handler::m_handler; @@ -432,7 +433,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; } } @@ -469,7 +470,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 @@ -512,11 +513,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()); + GULPS_LOGF_L2("Can't create directory: {}, err {}", path, ec.message()); } return res; @@ -559,7 +560,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"); + GULPS_LOGF_L0("libunbound was built {} threads", (with_threads ? "with" : "without") ); return with_threads; } @@ -625,8 +626,6 @@ static void setup_crash_dump() bool on_startup() { - mlog_configure("", true); - setup_crash_dump(); sanitize_locale(); @@ -634,7 +633,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) @@ -644,8 +643,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) @@ -687,12 +685,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"); + GULPS_WARNF("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"); + GULPS_WARNF("Failed to determine whether address '{}' is local, assuming not", address ); return false; } @@ -706,13 +704,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"); + GULPS_LOGF_L0("Address '{}' is local", address ); return true; } ++i; } - MDEBUG("Address '" << address << "' is not local"); + GULPS_LOGF_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 3640dac7..b1136de0 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -43,6 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "cmn_util" #pragma once @@ -56,12 +60,13 @@ #include #ifdef _WIN32 -#include "misc_log_ex.h" #include "windows.h" #endif #include "crypto/hash.h" +#include "common/gulps.hpp" + /*! \brief Various Tools * * @@ -194,7 +199,7 @@ class signal_handler } else { - MGINFO_RED("Got control signal " << type << ". Exiting without saving..."); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_RED, "Got control signal {}. Exiting without saving...", type); return FALSE; } return TRUE; diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index a92f7744..c633d959 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -90,6 +90,7 @@ target_link_libraries(cncrypto PUBLIC epee ${Boost_SYSTEM_LIBRARY} + fmt::fmt-header-only PRIVATE ${EXTRA_LIBRARIES}) @@ -104,6 +105,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/crypto.h b/src/crypto/crypto.h index 83e68d00..c0e78ccc 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -55,6 +55,7 @@ #include #include +#include "fmt/format.h" #include "common/util.h" #include "generic-ops.h" #include "hash.h" @@ -370,6 +371,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/hash.h b/src/crypto/hash.h index 00ac8002..5a51eb53 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -46,12 +46,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 @@ -111,5 +113,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/random.cpp b/src/crypto/random.cpp index 4ab054a2..46ecd96a 100644 --- a/src/crypto/random.cpp +++ b/src/crypto/random.cpp @@ -39,6 +39,7 @@ // 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. +#define GULPS_CAT_MAJOR "random" #include #include @@ -64,6 +65,8 @@ #endif +#include "common/gulps.hpp" + extern "C" void* memwipe(void *src, size_t n); struct prng_handle @@ -86,13 +89,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 @@ -104,18 +107,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 @@ -124,7 +127,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(); } } @@ -175,7 +178,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 @@ -190,13 +193,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 diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index 8010a3cd..279e51c7 100644 --- a/src/cryptonote_basic/CMakeLists.txt +++ b/src/cryptonote_basic/CMakeLists.txt @@ -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 5f28f226..fc233619 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -43,6 +43,11 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "crybas_account" + #include @@ -56,8 +61,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" + + + using namespace std; @@ -75,7 +82,7 @@ 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()); } //----------------------------------------------------------------- @@ -170,7 +177,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); @@ -217,7 +224,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"); } } //----------------------------------------------------------------- @@ -232,7 +239,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/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index d85937bc..3aed37c1 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -43,9 +43,14 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "basic_util" + #include "include_base_utils.h" -using namespace epee; +#include "common/gulps.hpp" #include "common/base58.h" #include "common/dns_utils.h" @@ -59,8 +64,9 @@ 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" + + namespace cryptonote { @@ -177,7 +183,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); + GULPS_ERRORF("Block cumulative size is too big: {}, expected less than {}", current_block_size, 2 * median_size); return false; } @@ -284,14 +290,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; } @@ -321,8 +326,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; } @@ -331,8 +335,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; @@ -343,8 +346,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; } @@ -355,25 +357,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) @@ -394,7 +394,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; + GULPS_ERRORF("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 e6a80653..d8204739 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -178,18 +178,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_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 7c99cd27..6b53f41e 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -43,10 +43,12 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "formt_utils" #include "include_base_utils.h" -using namespace epee; - #include "crypto/pow_hash/cn_slow_hash.hpp" #include "crypto/crypto.h" #include "crypto/hash.h" @@ -59,13 +61,15 @@ 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[] = { @@ -83,7 +87,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, @@ -97,12 +101,14 @@ 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()); \ } \ } @@ -162,7 +168,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; } @@ -173,25 +179,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) @@ -206,8 +212,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; } @@ -218,8 +224,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; } //--------------------------------------------------------------- @@ -229,8 +235,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 @@ -243,19 +249,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); } @@ -292,22 +298,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"); } @@ -391,7 +397,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 @@ -510,7 +516,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); @@ -518,7 +524,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()); @@ -535,7 +541,7 @@ bool add_payment_id_to_tx_extra(std::vector &tx_extra, const tx_extra_u 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; } //--------------------------------------------------------------- @@ -600,7 +606,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; } @@ -609,9 +615,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; } @@ -620,9 +626,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; @@ -671,7 +677,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; @@ -681,20 +687,20 @@ 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; @@ -711,7 +717,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()) @@ -731,12 +737,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); @@ -763,7 +769,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); } } //--------------------------------------------------------------- @@ -787,7 +793,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)); } } //--------------------------------------------------------------- @@ -848,7 +854,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]); } @@ -865,7 +871,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]); } @@ -884,7 +890,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) @@ -939,7 +945,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; @@ -965,7 +971,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); @@ -1012,7 +1018,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 de0217b3..44430d76 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -191,7 +191,7 @@ 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_CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); return ss.str(); } //--------------------------------------------------------------- @@ -206,6 +206,6 @@ 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); #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/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp index 7174da02..507d6bff 100644 --- a/src/cryptonote_basic/difficulty.cpp +++ b/src/cryptonote_basic/difficulty.cpp @@ -44,6 +44,9 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "crybas_diff" +#include "common/gulps.hpp" + #include #include #include @@ -239,14 +242,15 @@ difficulty_type next_difficulty_v2(std::vector timestamps, std::v time_span = 1; } 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 << ")"); + + GULPS_LOGF_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); + GULPS_LOGF_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) @@ -272,8 +276,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); - + GULPS_LOGF_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; } @@ -316,8 +319,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); - + GULPS_LOGF_L2("diff sum: {} L {} sizes {} {} next_D {}",(cumulative_difficulties[N] - cumulative_difficulties[0]), L, timestamps.size(), cumulative_difficulties.size(), next_D); return next_D; } diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp index 5c78d0ff..fc05a371 100644 --- a/src/cryptonote_basic/hardfork.cpp +++ b/src/cryptonote_basic/hardfork.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "crybas_hfork" #include #include @@ -49,8 +50,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" + + using namespace cryptonote; @@ -212,10 +215,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); + GULPS_LOGF_L1("reorganizing from {}", height); if(populate) { reorganize_from_chain_height(height); @@ -226,7 +229,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/miner.cpp b/src/cryptonote_basic/miner.cpp index ab81954e..79e7a629 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "crybas_miner" #include "boost/logic/tribool.hpp" #include "common/command_line.h" @@ -86,12 +87,12 @@ #include #endif -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "miner" + using namespace epee; #include "miner.h" +#include "common/gulps.hpp" namespace cryptonote { @@ -170,7 +171,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); @@ -212,7 +213,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; + GULPS_PRINTF("hashrate: {:.{}f}", hr, precision); } } m_last_hr_merge_time = misc_utils::get_tick_count(); @@ -238,7 +239,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()); @@ -254,7 +255,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); + GULPS_INFOF("Loaded {} extra messages, current index {}", m_extra_messages.size(), m_config.current_extra_message_index); } if(command_line::has_arg(vm, arg_start_mining)) @@ -262,13 +263,13 @@ 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"); + GULPS_LOGF_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); + GULPS_LOGF_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; } @@ -320,13 +321,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; } @@ -340,14 +341,14 @@ bool miner::start(const account_public_address &adr, size_t threads_count, const for(size_t i = 0; i != threads_count; i++) { 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!"); + GULPS_PRINTF("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; @@ -372,11 +373,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; } @@ -395,7 +396,7 @@ bool miner::stop() m_background_mining_thread.interrupt(); m_background_mining_thread.join(); - MINFO("Mining has been stopped, " << m_threads.size() << " finished"); + GULPS_INFOF("Mining has been stopped, {} finished", m_threads.size()); m_threads.clear(); return true; } @@ -432,31 +433,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)); + GULPS_LOGF_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)); + GULPS_LOGF_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) + "]"); + GULPS_PRINTF("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; @@ -475,7 +476,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) @@ -498,7 +499,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; } @@ -511,7 +512,7 @@ bool miner::worker_thread() { //we lucky! ++m_config.current_extra_message_index; - MGINFO_GREEN("Found block for difficulty: " << local_diff); + GULPS_PRINTF_CLR(gulps::COLOR_GREEN, "Found block for difficulty: {}", local_diff); if(!m_phandler->handle_block_found(b)) { --m_config.current_extra_message_index; @@ -526,7 +527,7 @@ bool miner::worker_thread() nonce += m_threads_total; ++m_hashes; } - MGINFO("Miner thread stopped [" << th_local_index << "]"); + GULPS_PRINTF("Miner thread stopped [{}]", th_local_index); return true; } //----------------------------------------------------------------------------------------------------- @@ -612,7 +613,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; } @@ -638,7 +639,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 ); } @@ -653,7 +654,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 .. } @@ -676,13 +677,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; } @@ -692,10 +693,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); + GULPS_PRINTF("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!"); + GULPS_PRINTF("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 @@ -713,7 +714,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); + GULPS_LOGF_L1("m_miner_extra_sleep {}", m_miner_extra_sleep); } prev_total_time = current_total_time; @@ -725,7 +726,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; } @@ -733,10 +734,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)); + GULPS_PRINTF("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!"); + GULPS_PRINTF("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(); @@ -747,7 +748,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!"); } } @@ -782,14 +783,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"); + GULPS_LOGF_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 << "'"); + GULPS_ERRORF("failed to open '{}'", STAT_FILE_PATH ); return false; } @@ -800,7 +801,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 << "'"); + GULPS_LOGF_ERROR("failed to read '{}'", STAT_FILE_PATH ); return false; } @@ -832,14 +833,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)); + GULPS_LOGF_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."); + GULPS_LOGF_ERROR("sysctlbyname(\"kern.cp_time\") output is unexpectedly {} bytes instead of the expected {} bytes.", n, sizeof(s.cp_time)); return false; } @@ -932,7 +931,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; } @@ -948,7 +947,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; } @@ -966,7 +965,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; } @@ -992,7 +991,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); + GULPS_LOGF_ERROR("couldn't query power status from {}", power_supply_class_path); } return on_battery; @@ -1003,8 +1002,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); } @@ -1014,8 +1012,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)); + GULPS_LOGF_ERROR("Cannot query battery status: open(): {}: {}", dev_apm, strerror(errno)); return boost::logic::tribool(boost::logic::indeterminate); } @@ -1023,8 +1020,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)); + GULPS_LOGF_FERROR("Cannot query battery status: ioctl({}, APMIO_GETINFO): {}", dev_apm, strerror(errno)); return boost::logic::tribool(boost::logic::indeterminate); } @@ -1049,22 +1045,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 << ")."); + GULPS_LOGF_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."); + GULPS_LOGF_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_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index fcb1fa67..9045438a 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -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 edcd2c2d..6c5a1c51 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -43,6 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "blockchain" #include #include @@ -75,8 +79,9 @@ #include "blocks/blocks.h" #endif -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "blockchain" +#include "common/gulps.hpp" + + #define FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE (100 * 1024 * 1024) // 100 MB @@ -95,8 +100,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)) @@ -156,12 +159,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 @@ -171,7 +174,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 @@ -185,7 +188,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); @@ -220,13 +223,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!"); + GULPS_VERIFYF_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } catch(...) { - MERROR_VER("Output does not exist!"); + GULPS_VERIFYF_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } @@ -235,7 +238,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()); + GULPS_LOGF_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++) @@ -245,13 +248,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!"); + GULPS_VERIFYF_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } } catch(...) { - MERROR_VER("Output does not exist!"); + GULPS_VERIFYF_ERR_TX("Output does not exist! amount = {}", tx_in_to_key.amount); return false; } outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end()); @@ -275,13 +278,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); + GULPS_VERIFYF_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); + GULPS_VERIFYF_ERR_TX("Output does not exist! amount = {}, absolute_offset = {}", tx_in_to_key.amount , i); return false; } @@ -298,12 +301,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; } } @@ -313,7 +316,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 @@ -325,16 +328,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; } @@ -342,18 +345,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; } @@ -401,7 +404,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) @@ -417,7 +420,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. @@ -451,7 +454,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()); + GULPS_INFOF("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; @@ -464,15 +467,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); + GULPS_GLOBALF_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); + GULPS_GLOBALF_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); + GULPS_GLOBALF_PRINT("Popping blocks... {}", top_height); ++num_popped_blocks; block popped_block; std::vector popped_txs; @@ -484,12 +487,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()); + GULPS_ERRORF("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; } } @@ -517,7 +520,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); @@ -530,26 +533,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!"); + GULPS_ERRORF("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"); + GULPS_INFOF("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(); @@ -567,15 +570,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()); + GULPS_LOGF_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; @@ -590,7 +593,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; @@ -606,12 +609,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()); + GULPS_LOGF_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; } @@ -630,7 +633,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"); } } } @@ -648,7 +651,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(); @@ -663,7 +666,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(); @@ -671,7 +674,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 @@ -693,7 +696,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; @@ -736,7 +739,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 @@ -750,12 +753,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()); + GULPS_ERRORF("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; @@ -763,7 +766,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 @@ -788,12 +791,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; } @@ -806,7 +809,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; @@ -883,7 +886,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 @@ -908,15 +911,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."); + GULPS_LOGF_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; } @@ -942,18 +945,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; } @@ -979,12 +982,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); + GULPS_LOGF_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); + GULPS_LOGF_L1("Poisson check triggered by reorg size of {}", alt_chain_size); uint64_t failed_checks = 0, i = 1; constexpr crypto::hash zero_hash = {{0}}; @@ -1000,7 +1002,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."); + GULPS_LOGF_L1("Skipping check at depth {} due to tampered timestamp on main chain.", i ); failed_checks++; continue; } @@ -1008,17 +1010,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); + GULPS_LOGF_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; } } @@ -1047,7 +1049,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)); + GULPS_LOGF_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();) @@ -1080,7 +1082,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()); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_GREEN, "REORGANIZE SUCCESS! on height: {}, new blockchain size: {}", split_height , m_db->height()); return true; } //------------------------------------------------------------------ @@ -1103,7 +1105,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; @@ -1143,8 +1145,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) { @@ -1188,18 +1190,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); + GULPS_WARNF("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 @@ -1207,7 +1209,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)); + GULPS_ERRORF("miner transaction has money overflow in block {}", get_block_hash(b)); return false; } @@ -1217,13 +1219,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; } @@ -1235,9 +1237,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; @@ -1252,13 +1254,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"); + GULPS_VERIFYF_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) << ")"); + GULPS_VERIFYF_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; } @@ -1267,14 +1269,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)); + GULPS_VERIFYF_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; @@ -1284,7 +1286,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) @@ -1296,19 +1298,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"); + GULPS_VERIFYF_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) << ")"); + GULPS_VERIFYF_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; @@ -1319,7 +1321,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(); @@ -1339,13 +1341,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; } //------------------------------------------------------------------ @@ -1362,7 +1364,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; @@ -1381,7 +1383,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); @@ -1403,7 +1405,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; @@ -1411,24 +1413,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); + GULPS_LOGF_L1("Creating block template: height {}, median size {}, already generated coins {}, transaction size {}, fee {}", height, median_size, already_generated_coins, txs_size, fee); #endif /* @@ -1437,22 +1439,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); + GULPS_LOGF_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"); + GULPS_LOGF_L1("Creating block template: miner tx size {}, cumulative size {} is greater than before", coinbase_blob_size , cumulative_size ); #endif continue; } @@ -1461,31 +1463,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"); + GULPS_LOGF_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); + GULPS_LOGF_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); + GULPS_LOGF_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"); + GULPS_LOGF_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"); + GULPS_LOGF_ERROR("Failed to create_block_template with {}, tries", 10); return false; } //------------------------------------------------------------------ @@ -1493,7 +1495,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; @@ -1502,8 +1504,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) { @@ -1521,13 +1523,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."); + GULPS_VERIFYF_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; } @@ -1537,9 +1539,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()); + GULPS_VERIFYF_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; } @@ -1547,8 +1548,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); + GULPS_LOGF_L1("Block with id: {}\nhas old version for height {}", id , block_height); bvc.m_verifivation_failed = true; return false; } @@ -1577,19 +1577,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 @@ -1597,7 +1597,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); } @@ -1606,8 +1606,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); + GULPS_VERIFYF_ERR_BLK("Block with id: {}\n for alternative chain, has invalid timestamp: {}", id, b.timestamp); bvc.m_verifivation_failed = true; return false; } @@ -1620,28 +1619,26 @@ bool Blockchain::handle_alternative_block(const block &b, const crypto::hash &id 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); + GULPS_VERIFYF_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."); + GULPS_VERIFYF_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; } @@ -1664,14 +1661,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); + GULPS_GLOBALF_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); @@ -1685,8 +1682,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); + GULPS_GLOBALF_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) @@ -1697,10 +1693,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); + GULPS_GLOBALF_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; } } @@ -1708,9 +1701,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() << ")"); + GULPS_VERIFYF_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; @@ -1718,7 +1712,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; @@ -1732,7 +1726,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; @@ -1740,7 +1734,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; @@ -1750,7 +1744,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; } } @@ -1766,7 +1760,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(); @@ -1784,9 +1778,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); + GULPS_LOGF_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 @@ -1817,7 +1809,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) @@ -1829,7 +1821,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(); } @@ -1838,7 +1830,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()); @@ -1945,7 +1937,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 @@ -1973,7 +1965,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()); @@ -1990,7 +1982,7 @@ void Blockchain::add_out_to_get_rct_random_outs(std::list random outputs @@ -2073,7 +2065,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"); + GULPS_PRINTF("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); @@ -2104,7 +2096,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(); @@ -2147,14 +2139,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"); + GULPS_CATF_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; } @@ -2164,10 +2156,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"); + GULPS_CATF_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; } @@ -2185,7 +2175,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); + GULPS_WARNF("Non-critical error trying to find block by hash in BlockchainDB, hash: {}", *bl_it); m_db->block_txn_abort(); return false; } @@ -2196,7 +2186,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; } @@ -2207,7 +2197,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 @@ -2218,7 +2208,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; } @@ -2228,7 +2218,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) @@ -2238,7 +2228,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; } } @@ -2259,7 +2249,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) @@ -2283,7 +2273,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) @@ -2296,7 +2286,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; } } @@ -2316,7 +2306,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 @@ -2339,7 +2329,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); @@ -2355,7 +2345,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 @@ -2384,10 +2374,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(); @@ -2398,7 +2388,7 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons //------------------------------------------------------------------ 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); @@ -2406,35 +2396,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"); + GULPS_INFOF("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; } @@ -2443,14 +2432,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 @@ -2466,7 +2455,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 { @@ -2515,7 +2504,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; } } @@ -2525,12 +2514,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); + GULPS_VERIFYF_ERR_TX("get_tx_outputs_gindexs failed to find transaction with id = {}", tx_id); return false; } @@ -2541,10 +2530,10 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vectorget_tx(tx_id); - if(tx.vout.size() == 1 && m_db->is_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"); + if(tx.vout.size() == 1 && m_db->is_vout_bad(tx.vout[0])) + indexs.insert(indexs.begin(), uint64_t(-1)); //This vout is unspendable so give it an invalid index + else + 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; @@ -2562,9 +2551,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); + GULPS_INFOF("HASH: - I/M/O: {}/{}/{} H: {} chcktx: {}", tx.vin.size() , ring_size , tx.vout.size() , 0 ,a); } } #endif @@ -2580,7 +2567,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) @@ -2599,19 +2586,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)); + GULPS_INFOF("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) @@ -2639,21 +2626,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; } @@ -2663,7 +2650,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); @@ -2675,7 +2662,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; @@ -2685,13 +2672,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]); @@ -2700,7 +2687,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) { @@ -2713,7 +2700,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 @@ -2726,7 +2713,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); @@ -2735,7 +2722,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 @@ -2751,7 +2738,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; @@ -2776,7 +2763,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; } @@ -2785,7 +2772,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) << ")"); + GULPS_VERIFYF_ERR_TX("Tx {} has too low ring size ({})", get_transaction_hash(tx) , (lowest_mixin + 1) ); tvc.m_low_mixin = true; return false; } @@ -2793,7 +2780,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); + GULPS_VERIFYF_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; } @@ -2814,7 +2801,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; } @@ -2824,16 +2811,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; } @@ -2842,7 +2829,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; } @@ -2852,14 +2839,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; } @@ -2873,7 +2860,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; } @@ -2886,7 +2873,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); + GULPS_VERIFYF_ERR_TX("transaction version {} is higher than max accepted version {}", (unsigned)tx.version , max_tx_version); tvc.m_verifivation_failed = true; return false; } @@ -2894,7 +2881,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); + GULPS_VERIFYF_ERR_TX("transaction version {} is lower than min accepted version {}", (unsigned)tx.version , min_tx_version); tvc.m_verifivation_failed = true; return false; } @@ -2915,15 +2902,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; } @@ -2933,10 +2920,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); + GULPS_VERIFYF_ERR_TX(" *pmax_used_block_height: {}", *pmax_used_block_height); } return false; @@ -2946,7 +2933,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; } @@ -2959,7 +2946,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: @@ -2969,14 +2956,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; } } @@ -2987,12 +2974,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); + GULPS_VERIFYF_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); + GULPS_VERIFYF_ERR_TX("Failed to check ringct signatures: mismatched commitment at vin {}, index {}", n , m); return false; } } @@ -3001,21 +2988,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; @@ -3031,7 +3018,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; } @@ -3041,12 +3028,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); + GULPS_VERIFYF_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); + GULPS_VERIFYF_ERR_TX("Failed to check ringct signatures: mismatched commitment at vin {}, index {}", n , m); return false; } } @@ -3055,32 +3042,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); + GULPS_VERIFYF_ERR_TX("Unsupported rct type: {}", rv.type); return false; } @@ -3154,7 +3141,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_per_kb) << "/kB fee"); + GULPS_LOGF_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; @@ -3162,14 +3149,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)); + GULPS_VERIFYF_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)); + GULPS_VERIFYF_ERR_TX("transaction fee is not enough: {}, minimum fee: {}", print_money(fee), print_money(needed_fee)); return false; } return true; @@ -3180,7 +3167,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; @@ -3191,7 +3178,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. @@ -3209,7 +3196,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); + GULPS_VERIFYF_ERR_TX("One of outputs for one of inputs has wrong tx.unlock_time = {}", unlock_time); return false; } @@ -3229,18 +3216,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()); + GULPS_VERIFYF_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()); + GULPS_VERIFYF_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; @@ -3249,7 +3236,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); } @@ -3257,12 +3244,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); + GULPS_VERIFYF_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; } @@ -3278,7 +3265,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; @@ -3292,7 +3279,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"); + GULPS_VERIFYF_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; } @@ -3328,7 +3315,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"); + GULPS_ERRORF("Failed to return taken transaction with hash: {} to tx_pool", get_transaction_hash(tx) ); } } } @@ -3344,10 +3331,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"); + GULPS_INFOF("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"); + GULPS_ERRORF("Failed to remove txid {} from the pool", txid ); res = false; } } @@ -3359,7 +3346,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); @@ -3370,9 +3357,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()); + GULPS_VERIFYF_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; @@ -3382,20 +3367,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()); + GULPS_VERIFYF_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; } @@ -3407,8 +3389,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); + GULPS_VERIFYF_ERR_BLK("Block with id: {}\nhas invalid timestamp: {}", id, bl.timestamp); bvc.m_verifivation_failed = true; goto leave; } @@ -3423,7 +3404,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); @@ -3451,7 +3432,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); + GULPS_VERIFYF_ERR_BLK("Block with id is INVALID: {}", id); bvc.m_verifivation_failed = true; goto leave; } @@ -3459,7 +3440,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"); + GULPS_CATF_PRINT("verify", "No pre-validated hash at height {}, verifying fully", m_db->height()); } } else @@ -3479,9 +3460,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); + GULPS_VERIFYF_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; } @@ -3493,7 +3472,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; } @@ -3508,7 +3487,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"); + GULPS_VERIFYF_ERR_BLK("Block with id: {} failed to pass prevalidation", id ); bvc.m_verifivation_failed = true; goto leave; } @@ -3543,7 +3522,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); + GULPS_ERRORF("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; @@ -3556,7 +3535,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); + GULPS_VERIFYF_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; @@ -3578,7 +3557,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); + // GULPS_VERIFYF_ERR_BLK("Double spend detected in transaction (id: " , tx_id); // bvc.m_verifivation_failed = true; // break; // } @@ -3595,11 +3574,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."); + GULPS_VERIFYF_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"); + GULPS_VERIFYF_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; @@ -3612,10 +3591,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."); + GULPS_VERIFYF_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"); + GULPS_VERIFYF_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; @@ -3637,7 +3616,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"); + GULPS_VERIFYF_ERR_BLK("Block with id: {} has incorrect miner transaction", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3647,7 +3626,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"); + GULPS_VERIFYF_ERR_BLK("Block with id: {} has incorrect miner transaction", id ); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); goto leave; @@ -3684,7 +3663,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()); + GULPS_LOGF_ERROR("Error adding block with hash: {} to blockchain, what = {}", id , e.what()); bvc.m_verifivation_failed = true; return_tx_to_pool(txs); return false; @@ -3692,14 +3671,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()); + GULPS_LOGF_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); @@ -3707,18 +3686,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"); + GULPS_INFOF("+++++ 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"); + GULPS_INFOF("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; @@ -3734,7 +3712,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); @@ -3749,7 +3727,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); @@ -3758,7 +3736,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"); + GULPS_LOGF_L3("block with id = {} already exists", id ); bvc.m_already_exists = true; m_db->block_txn_stop(); m_blocks_txs_check.clear(); @@ -3803,13 +3781,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"); } } } @@ -3846,7 +3824,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!"); } } @@ -3883,7 +3861,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); @@ -3894,7 +3872,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync) } catch(const std::exception &e) { - MERROR("Exception in cleanup_handle_incoming_blocks: " << e.what()); + GULPS_ERRORF("Exception in cleanup_handle_incoming_blocks: {}", e.what()); } if(success && m_sync_counter > 0) @@ -3932,7 +3910,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()); + GULPS_INFOF("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(); } @@ -3953,7 +3931,7 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector::max() / 2, 0, "usable is negative"); + GULPS_LOGF_L1("usable: {} / {}", usable , hashes.size()); + GULPS_CHECK_AND_ASSERT_MES(usable < std::numeric_limits::max() / 2, 0, "usable is negative"); return usable; } @@ -4065,7 +4043,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; @@ -4123,7 +4101,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); + GULPS_LOGF_L1("block_batches: {}", batches); std::vector> maps(threads); std::vector> blocks(threads); auto it = blocks_entry.begin(); @@ -4146,7 +4124,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; } } @@ -4210,7 +4188,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list 1 && threads > 1 && m_show_time_stats) - MDEBUG("Prepare blocks took: " << prepare << " ms"); + GULPS_LOGF_L1("Prepare blocks took: {} ms", prepare ); TIME_MEASURE_START(scantable); @@ -4238,7 +4216,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list 0) { - MINFO("Loading precomputed blocks (" << get_blocks_dat_size(testnet, stagenet) << " bytes)"); + GULPS_INFOF("Loading precomputed blocks ({} bytes)", get_blocks_dat_size(testnet, stagenet) ); if(m_nettype == MAINNET) { @@ -4545,20 +4523,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); + GULPS_INFOF("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; } } @@ -4569,7 +4547,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); @@ -4585,7 +4563,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"); + GULPS_INFOF("{} 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/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 68d7ce10..1908c1aa 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "crtnte_core" #include @@ -71,12 +72,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) + +DISABLE_VS_WARNINGS(4355) #define BAD_SEMANTICS_TXES_MAX_SIZE 100 @@ -269,7 +270,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"); + GULPS_WARNF("{} is obsolete, it is now default", arg_fluffy_blocks.name); if(command_line::get_arg(vm, arg_test_drop_download) == true) test_drop_download(); @@ -362,18 +363,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() << " ..."); + GULPS_GLOBALF_PRINT("Loading blockchain from folder {} ...", folder.string()); const std::string filename = folder.string(); // default to fast:async:1 @@ -390,7 +391,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); + GULPS_LOGF_L1("option: {}", option); // default to fast:async:1 uint64_t DEFAULT_FLAGS = DBF_FAST; @@ -450,7 +451,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()); + GULPS_LOGF_ERROR("Error opening database: {}", e.what()); return false; } @@ -460,7 +461,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 @@ -468,15 +469,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") @@ -489,12 +490,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(); } @@ -550,7 +551,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"); + GULPS_LOGF_L1("WRONG TRANSACTION BLOB, too big size {}, rejected", tx_blob.size() ); tvc.m_verifivation_failed = true; tvc.m_too_big = true; return false; @@ -561,7 +562,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; } @@ -573,7 +574,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; } @@ -583,14 +584,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; } @@ -602,18 +603,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"); + GULPS_LOGF_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"); + GULPS_LOGF_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); @@ -631,7 +632,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 { @@ -656,7 +657,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()); + GULPS_VERIFYF_ERR_TX("Exception in handle_incoming_tx_pre: {}", e.what()); results[i].res = false; } }); @@ -669,11 +670,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"); + GULPS_LOGF_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"); + GULPS_LOGF_L2("tx {} already have transaction in blockchain", results[i].hash ); } else { @@ -684,7 +685,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()); + GULPS_VERIFYF_ERR_TX("Exception in handle_incoming_tx_post: {}", e.what()); results[i].res = false; } }); @@ -705,19 +706,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); + GULPS_VERIFYF_ERR_TX("Transaction verification failed: {}", results[i].hash); } else if(tvc[i].m_verifivation_impossible) { - MERROR_VER("Transaction verification impossible: " << results[i].hash); + GULPS_VERIFYF_ERR_TX("Transaction verification impossible: {}", results[i].hash); } if(tvc[i].m_added_to_pool) - MDEBUG("tx added: " << results[i].hash); + GULPS_LOGF_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) @@ -745,31 +746,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)); + GULPS_VERIFYF_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)); + GULPS_VERIFYF_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)); + GULPS_VERIFYF_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)); + GULPS_VERIFYF_ERR_TX("tx has money overflow, rejected for tx id= {}", get_transaction_hash(tx)); return false; } @@ -777,26 +778,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); + GULPS_VERIFYF_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; } @@ -805,7 +806,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: @@ -813,19 +814,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; } @@ -956,13 +957,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"); + GULPS_LOGF_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"); + GULPS_LOGF_L2("tx {} already have transaction in blockchain", tx_hash ); return true; } @@ -995,7 +996,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))); @@ -1059,7 +1060,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; @@ -1086,7 +1087,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(); @@ -1097,11 +1098,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 @@ -1154,16 +1155,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"); + GULPS_LOGF_L1("WRONG BLOCK BLOB, too big size {}, rejected", block_blob.size() ); bvc.m_verifivation_failed = true; return false; } @@ -1171,7 +1172,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; } @@ -1180,7 +1181,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 @@ -1189,7 +1190,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"); + GULPS_LOGF_L1("WRONG BLOCK BLOB, too big size {}, rejected", block_blob.size() ); return false; } return true; @@ -1303,15 +1304,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; } @@ -1327,19 +1326,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; @@ -1381,7 +1379,7 @@ bool core::check_updates() return true; std::string version, hash; - MCDEBUG("updates", "Checking for a new " << software << " version for " << buildtag); + GULPS_CATF_LOG_L1("updates", "Checking for a new {} version for {}", software, buildtag); if (!tools::check_updates(software, buildtag, version, hash)) return false; @@ -1389,7 +1387,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); + GULPS_GLOBALF_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; @@ -1408,18 +1406,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) { @@ -1429,20 +1427,20 @@ bool core::check_updates() crypto::hash file_hash; if (!tools::sha256sum(tmppath, file_hash)) { - MCERROR("updates", "Failed to hash " << tmppath); + GULPS_CATF_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"); + GULPS_CATF_ERROR("updates", "Download from {} does not match the expected hash", uri ); remove = true; good = false; } } else { - MCERROR("updates", "Failed to download " << uri); + GULPS_CATF_ERROR("updates", "Failed to download {}", uri); good = false; } boost::unique_lock lock(m_update_mutex); @@ -1452,7 +1450,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; } } @@ -1460,24 +1458,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()); + GULPS_CATF_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")); + GULPS_CATF_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"); + GULPS_CATF_LOG_L1("updates", "We already have {} with expected hash", path); } lock.unlock(); @@ -1485,7 +1483,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; } @@ -1495,8 +1493,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); + GULPS_CATF_WARN("Free space is below 1 GB on {}", m_config_folder); } return true; } diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 67dce350..59eeb961 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "crtnte_tx_utils" #include "include_base_utils.h" #include "string_tools.h" @@ -59,6 +60,8 @@ using namespace epee; #include "multisig/multisig.h" #include "ringct/rctSigs.h" +#include "common/gulps.hpp" + using namespace crypto; namespace cryptonote @@ -87,7 +90,7 @@ void classify_addresses(const std::vector &destinations, c } } } - LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses"); + GULPS_LOGF_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) @@ -105,12 +108,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); + GULPS_LOGF_L1("Creating block template: reward {}, fee {}", block_reward , fee); #endif block_reward += fee; @@ -118,27 +121,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); } @@ -153,16 +156,16 @@ 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, bool allow_any_key) -{ +{ 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) @@ -189,7 +192,7 @@ bool construct_tx_with_tx_key(const account_keys &sender_account_keys, const std if(sources.empty()) { - LOG_ERROR("Empty sources"); + GULPS_LOG_ERROR("Empty sources"); return false; } @@ -205,13 +208,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; } @@ -232,7 +235,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()); + GULPS_LOGF_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; @@ -244,18 +247,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); + GULPS_LOGF_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)); + GULPS_LOGF_ERROR("amount {}, rct {}", src_entr.amount, src_entr.rct); + GULPS_LOGF_ERROR("tx pubkey {}, real_output_in_tx_index {}", src_entr.real_out_tx_key, src_entr.real_output_in_tx_index); return false; } @@ -311,14 +313,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; @@ -338,13 +340,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) @@ -357,7 +359,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); @@ -370,58 +372,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); } - + tx_extra_uniform_payment_id pid; //Add payment id after pubkeys if(payment_id != nullptr) { if(payment_id->zero != 0) { - LOG_ERROR("Internal error. Invalid payment id."); + GULPS_ERROR("Internal error. Invalid payment id."); return false; } pid.pid = *payment_id; } - LOG_PRINT_L2("Encrypting payment id " << pid.pid.payment_id); + GULPS_LOGF_L2("Encrypting payment id {}", pid.pid.payment_id); crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr, payment_id == nullptr); if(view_key_pub == null_pkey) { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + GULPS_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); return false; } if(!hwdev.encrypt_payment_id(pid.pid, view_key_pub, tx_key)) { - LOG_ERROR("Failed to encrypt payment id"); + GULPS_ERROR("Failed to encrypt payment id"); return false; } if(!add_payment_id_to_tx_extra(tx.extra, pid)) { - LOG_ERROR("Failed to add encrypted payment id to tx extra"); + GULPS_ERROR("Failed to add encrypted payment id to tx extra"); return false; } - LOG_PRINT_L1("Encrypted payment ID: " << pid.pid.payment_id); + GULPS_LOGF_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 << ")"); + GULPS_LOGF_ERROR("Transaction inputs money ({}) less than outputs money ({})", summary_inputs_money, summary_outs_money); return false; } @@ -431,7 +433,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 @@ -447,7 +449,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; } } @@ -457,7 +459,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; } } @@ -540,9 +542,9 @@ 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(); @@ -569,7 +571,7 @@ 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, + 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(); @@ -588,16 +590,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/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index fa8584bc..0c174269 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "tx_pool" #include #include @@ -62,8 +63,9 @@ #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 @@ -118,7 +120,7 @@ class LockedTXN } catch(const std::exception &e) { - MWARNING("LockedTXN dtor filtering exception: " << e.what()); + GULPS_WARN("LockedTXN dtor filtering exception: ", e.what()); } } @@ -142,7 +144,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; } @@ -179,7 +181,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); + GULPS_LOGF_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; @@ -193,7 +195,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"); + GULPS_LOGF_L1("Transaction with id= {} used already spent key images", id ); tvc.m_verifivation_failed = true; tvc.m_double_spend = true; return false; @@ -202,7 +204,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"); + GULPS_LOGF_L1("Transaction with id= {} has at least one invalid output", id ); tvc.m_verifivation_failed = true; tvc.m_invalid_output = true; return false; @@ -247,7 +249,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()); + GULPS_ERRORF("transaction already exists at inserting in memory pool: {}" , e.what()); return false; } tvc.m_verifivation_impossible = true; @@ -255,7 +257,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; @@ -290,7 +292,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()); + GULPS_ERRORF("internal error: transaction already exists at inserting in memory pool: {}" , e.what()); return false; } tvc.m_added_to_pool = true; @@ -302,7 +304,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)); + GULPS_INFOF("Transaction added to pool: txid {} bytes: {} fee/byte: {}", id , blob_size , (fee / (double)blob_size)); prune(m_txpool_max_size); @@ -350,7 +352,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 @@ -363,25 +365,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); + GULPS_INFOF("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); + GULPS_INFOF("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()); + GULPS_ERRORF("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); + GULPS_INFOF("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) @@ -391,11 +393,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; } @@ -414,15 +415,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()) { @@ -448,13 +449,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; @@ -470,7 +471,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()); + GULPS_ERRORF("Failed to remove tx from txpool: {}" , e.what()); return false; } @@ -502,11 +503,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); + GULPS_LOGF_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!"); + GULPS_LOGF_L1("Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid ); } else { @@ -530,7 +531,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 @@ -543,7 +544,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 } } @@ -574,7 +575,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; } @@ -751,7 +752,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; } @@ -790,7 +791,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) @@ -799,7 +800,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()); + GULPS_ERRORF("Failed to get tx meta from txpool: {}" , e.what()); return false; } } @@ -822,7 +823,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; } @@ -999,7 +1000,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; } @@ -1020,13 +1021,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 { @@ -1034,7 +1035,7 @@ void tx_memory_pool::mark_double_spend(const transaction &tx) } catch(const std::exception &e) { - MERROR("Failed to update tx meta: " << e.what()); + GULPS_ERRORF("Failed to update tx meta: {}" , e.what()); // continue, not fatal } } @@ -1055,7 +1056,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; @@ -1095,7 +1096,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"); + GULPS_LOGF_L2("Filling block template, median size {}, {} txes in the pool", median_size, m_txs_by_fee_and_receive_time.size()); LockedTXN lock(m_blockchain); @@ -1104,15 +1105,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)); + GULPS_LOGF_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; } @@ -1121,13 +1122,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; } @@ -1135,7 +1136,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; } @@ -1152,18 +1153,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()); + GULPS_ERRORF("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; } @@ -1172,13 +1173,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)); + GULPS_LOGF_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)"); + GULPS_LOGF_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; } //--------------------------------------------------------------------------------- @@ -1194,12 +1194,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"); + GULPS_LOGF_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"); + GULPS_LOGF_L1("Transaction {} is in the blockchain, removing it from pool", txid ); remove.insert(txid); } return true; @@ -1218,7 +1218,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 @@ -1228,7 +1228,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!"); + GULPS_LOGF_L1("Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid ); } else { @@ -1238,7 +1238,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 } } @@ -1268,12 +1268,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); @@ -1295,7 +1295,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_protocol/CMakeLists.txt b/src/cryptonote_protocol/CMakeLists.txt index 813088da..2610fb24 100644 --- a/src/cryptonote_protocol/CMakeLists.txt +++ b/src/cryptonote_protocol/CMakeLists.txt @@ -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 aeee1e9a..073028dc 100644 --- a/src/cryptonote_protocol/block_queue.cpp +++ b/src/cryptonote_protocol/block_queue.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "blk_queue" #include "block_queue.h" #include "cryptonote_protocol_defs.h" @@ -51,8 +52,9 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "cn.block_queue" +#include "common/gulps.hpp" + + namespace std { @@ -82,7 +84,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)); } @@ -162,9 +164,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"); + GULPS_LOGF_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)"); + GULPS_LOGF_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 @@ -198,7 +200,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); + GULPS_LOGF_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); } @@ -219,7 +221,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); + GULPS_LOGF_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); @@ -245,7 +247,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); + GULPS_LOGF_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); } @@ -419,7 +421,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); + GULPS_LOGF_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 5da53cf5..9f0a1cc9 100644 --- a/src/cryptonote_protocol/block_queue.h +++ b/src/cryptonote_protocol/block_queue.h @@ -53,8 +53,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_handler-base.cpp b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp index 7b303264..3461e0e5 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp +++ b/src/cryptonote_protocol/cryptonote_protocol_handler-base.cpp @@ -45,6 +45,7 @@ // 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. +#define GULPS_CAT_MAJOR "cnt_pct_hand_base" #include #include @@ -66,7 +67,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 @@ -89,8 +89,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" + + // ################################################################################################ // ################################################################################################ @@ -151,16 +152,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); + GULPS_LOGF_L1("Packet size: {}", packet_size); do { // rate limiting //XXX /*if (::cryptonote::core::get_is_stopping()) { - MDEBUG("We are stopping - so abort sleep"); + GULPS_LOG_L1("We are stopping - so abort sleep"); return; }*/ /*if (m_was_shutdown) { - MDEBUG("m_was_shutdown - so abort sleep"); + GULPS_LOG_L1("m_was_shutdown - so abort sleep"); return; }*/ @@ -175,7 +176,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 + GULPS_LOGF_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 7b0ac14a..5475ee23 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.h +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h @@ -47,6 +47,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "cn_pcl_hand" #pragma once @@ -63,6 +67,9 @@ #include "warnings.h" #include +#include "common/gulps.hpp" + + PUSH_WARNINGS DISABLE_VS_WARNINGS(4355) @@ -169,7 +176,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() << " -->"); + GULPS_LOGF_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 @@ -179,7 +186,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() << " -->"); + GULPS_LOGF_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 8ad81014..9d688d55 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -50,7 +50,12 @@ // (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 +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "cn_pcl_hand" +//IGNORE #include #include #include @@ -60,10 +65,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_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) #define BLOCK_QUEUE_NBLOCKS_THRESHOLD 10 // chunks of N blocks #define BLOCK_QUEUE_SIZE_THRESHOLD (100 * 1024 * 1024) // MB @@ -111,15 +119,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()); + GULPS_LOGF_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) @@ -158,7 +166,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(); @@ -175,7 +183,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) { @@ -188,14 +196,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 @@ -284,7 +292,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"); + GULPS_CATF_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; } } @@ -314,17 +322,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) + GULPS_GLOBALF_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 + GULPS_GLOBALF_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); + GULPS_INFOF("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; @@ -352,12 +365,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(); @@ -370,7 +383,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(); @@ -382,14 +395,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; } @@ -403,7 +416,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()); + GULPS_LOGF_L1("{} -->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()={}", context_str, r.block_ids.size()); post_notify(r, context); } @@ -413,12 +426,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; } @@ -434,12 +447,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"); + GULPS_LOGF_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(); @@ -468,9 +479,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(); @@ -479,10 +488,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(); @@ -501,10 +507,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"); + GULPS_LOGF_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(); @@ -518,11 +521,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"); + GULPS_LOGF_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; @@ -538,10 +541,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"); + GULPS_LOGF_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(); @@ -555,11 +555,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"); + GULPS_LOGF_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(); @@ -588,14 +585,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"); + GULPS_LOGF_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"); + GULPS_LOGF_L1("Tx {} not found in pool", tx_hash ); need_tx_indices.push_back(tx_idx); } } @@ -606,9 +603,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"); + GULPS_LOGF_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]); + GULPS_LOGF_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; @@ -619,7 +616,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; @@ -633,7 +630,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; } @@ -641,7 +638,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; } @@ -658,17 +655,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()); + GULPS_LOGF_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"); + GULPS_LOGF_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); @@ -682,7 +677,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; @@ -690,7 +685,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"); + GULPS_LOGF_ERROR("{} failed to find block: {}, dropping connection", context_str, arg.block_hash ); drop_connection(context, false, false); return 1; } @@ -703,17 +698,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]); + GULPS_LOGF_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"); + GULPS_LOGF_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; @@ -724,16 +716,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"); + GULPS_LOGF_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; } @@ -743,10 +732,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); + GULPS_LOGF_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; @@ -755,7 +741,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; @@ -764,7 +750,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; } @@ -774,7 +760,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; } @@ -796,16 +782,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()); + GULPS_LOGF_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); @@ -819,7 +804,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; @@ -831,7 +816,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; @@ -855,7 +840,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"); + GULPS_LOGF_L1("{} downloaded {} bytes worth of blocks", context_str, size); /*using namespace boost::chrono; auto point = steady_clock::now(); @@ -866,8 +851,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"); + GULPS_LOGF_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; } @@ -890,15 +875,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"); + GULPS_LOGF_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"); + GULPS_LOGF_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; } @@ -909,15 +892,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"); + GULPS_LOGF_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"); + GULPS_LOGF_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; } @@ -928,8 +912,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"); + GULPS_LOGF_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; } @@ -939,19 +922,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()); + GULPS_LOGF_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_CAT_MAJOR, GULPS_CAT_MINOR, 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"); + GULPS_LOGF_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; @@ -979,10 +962,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(); @@ -997,15 +980,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); + GULPS_LOGF_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; } @@ -1013,7 +995,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; } @@ -1030,7 +1012,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; @@ -1038,7 +1020,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; } @@ -1064,7 +1046,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(); @@ -1073,16 +1055,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"); + GULPS_LOGF_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 @@ -1103,15 +1084,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; } @@ -1122,15 +1103,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; } @@ -1144,11 +1125,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"); + GULPS_CATF_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; } @@ -1157,13 +1139,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); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_BOLD_YELLOW, "{} Synced {}/{}", context_str, m_core.get_current_blockchain_height(), m_core.get_target_blockchain_height()); + GULPS_CATF_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()); } } } @@ -1179,7 +1158,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; } @@ -1196,7 +1175,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) @@ -1207,7 +1186,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); } } @@ -1226,15 +1205,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()); + GULPS_LOGF_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; } @@ -1250,7 +1229,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; } @@ -1266,7 +1245,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; @@ -1277,7 +1256,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); + GULPS_LOGF_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: @@ -1285,18 +1264,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; @@ -1326,7 +1305,7 @@ bool t_cryptonote_protocol_handler::request_missing_objects(cryptonote_c { if(!first) { - LOG_DEBUG_CC(context, "Block queue is " << nblocks << " and " << size << ", resuming"); + GULPS_LOGF_L1("{} Block queue is {} and {}, resuming", context_str, nblocks , size ); } break; } @@ -1336,20 +1315,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"); + GULPS_LOGF_L1("{} Block queue is {} and {}, pausing", context_str, nblocks , size ); first = false; context.m_state = cryptonote_connection_context::state_standby; } @@ -1358,7 +1337,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; @@ -1374,7 +1353,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()); + GULPS_LOGF_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 @@ -1384,7 +1363,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) { @@ -1392,17 +1371,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); + GULPS_LOGF_L1("{} gap found, span: {} - {} ({})", context_str, span.first , span.first + span.second - 1 , last_block_height_needed ); + GULPS_LOGF_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) @@ -1426,10 +1405,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()); + GULPS_LOGF_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; @@ -1445,11 +1424,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); + GULPS_LOGF_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; @@ -1469,7 +1448,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) << ")"); + GULPS_LOGF_L1("{} span: {}/{} ({} - {})", context_str, span.first , span.second , span.first , (span.first + span.second - 1) ); if(span.second > 0) { if(!is_next) @@ -1478,14 +1457,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; } @@ -1501,8 +1480,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()); + GULPS_INFOF("{} -->>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); @@ -1517,7 +1495,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) { @@ -1531,33 +1509,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); + GULPS_INFOF("{} -->>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; @@ -1569,11 +1547,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); @@ -1595,18 +1572,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; } @@ -1615,9 +1591,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()); + GULPS_LOGF_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; } @@ -1625,7 +1602,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; } @@ -1641,7 +1618,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; } @@ -1673,12 +1650,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); } } @@ -1723,7 +1700,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); + GULPS_INFOF("Target height decreasing from {} to {}", previous_target , target); m_core.set_target_blockchain_height(target); } diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt index ec45032e..c5a8b195 100644 --- a/src/daemon/CMakeLists.txt +++ b/src/daemon/CMakeLists.txt @@ -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 962f2a25..0d1d794f 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -71,10 +71,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 = { @@ -93,6 +93,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 2af3a629..021d398b 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -41,13 +41,15 @@ // 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. +#define GULPS_CAT_MAJOR "cmd_pars_exe" #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 { @@ -126,19 +128,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; } @@ -149,7 +151,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; } @@ -163,7 +165,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); @@ -186,17 +188,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)) @@ -204,7 +203,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; } @@ -222,13 +232,13 @@ bool t_command_parser_executor::print_transaction(const std::vector include_json = true; else { - std::cout << "unexpected argument: " << args[i] << std::endl; + GULPS_PRINTF("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; } @@ -246,7 +256,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector" << std::endl; + GULPS_PRINT("expected: is_key_image_spent "); return true; } @@ -290,7 +300,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; } @@ -302,7 +312,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 @@ -322,14 +332,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; + + GULPS_PRINTF("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; @@ -398,7 +409,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; } @@ -420,7 +431,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; } @@ -442,7 +453,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; } @@ -462,7 +473,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; } @@ -482,7 +493,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; } @@ -566,7 +577,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]; @@ -599,7 +610,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; } } @@ -610,19 +621,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; } @@ -633,7 +644,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; } @@ -644,14 +655,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; } @@ -662,7 +673,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; } @@ -678,7 +689,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]; @@ -695,7 +706,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; + GULPS_PRINTF("Ryo '{}' ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); return true; } diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 8fd66484..f636e706 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -48,8 +48,7 @@ #include "version.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { diff --git a/src/daemon/core.h b/src/daemon/core.h index 0c54c630..3719563b 100644 --- a/src/daemon/core.h +++ b/src/daemon/core.h @@ -41,15 +41,19 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "daemon_core" #pragma once #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 { @@ -98,13 +102,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; } @@ -115,7 +119,7 @@ class t_core final ~t_core() { - MGINFO("Deinitializing core..."); + GULPS_GLOBAL_PRINT("Deinitializing core..."); try { m_core.deinit(); @@ -123,7 +127,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 b3e645e2..6d1395cf 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -43,9 +43,9 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "daemon" #include "daemon/daemon.h" -#include "misc_log_ex.h" #include "rpc/daemon_handler.h" #include "rpc/zmq_server.h" #include @@ -63,13 +63,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 { @@ -173,7 +172,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"); + GULPS_ERRORF("Failed to add TCP Socket ({}:{}) to ZMQ RPC Server", zmq_rpc_bind_address, zmq_rpc_bind_port); if(rpc_commands) rpc_commands->stop_handling(); @@ -184,10 +183,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 + "."); + GULPS_INFOF("ZMQ server started at {}:{}.", zmq_rpc_bind_address, zmq_rpc_bind_port); mp_internals->p2p.run(); // blocks until p2p goes down @@ -199,17 +198,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()); + GULPS_ERRORF("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 d1f7e25f..716189e3 100644 --- a/src/daemon/daemon.h +++ b/src/daemon/daemon.h @@ -45,8 +45,7 @@ #pragma once #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp index cb0ad6d9..aa2b6c74 100644 --- a/src/daemon/executor.cpp +++ b/src/daemon/executor.cpp @@ -41,8 +41,7 @@ // 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 "misc_log_ex.h" +#define GULPS_CAT_MAJOR "daemon_exe" #include "daemon/executor.h" @@ -51,8 +50,9 @@ #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { @@ -72,7 +72,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 8e53125d..336ef8f8 100644 --- a/src/daemon/executor.h +++ b/src/daemon/executor.h @@ -49,8 +49,7 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" + namespace daemonize { diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp index ffc846ac..fdec513d 100644 --- a/src/daemon/main.cpp +++ b/src/daemon/main.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "main_daemon" #include "blockchain_db/db_types.h" #include "common/command_line.h" @@ -56,7 +57,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" @@ -66,12 +66,15 @@ #include "common/stack_trace.h" #endif // STACK_TRACE -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace po = boost::program_options; namespace bf = boost::filesystem; +gulps_log_level log_scr, log_dsk; + int main(int argc, char* argv[]) { #ifdef WIN32 @@ -84,6 +87,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 @@ -108,11 +118,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); @@ -145,24 +156,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; + GULPS_PRINTF("Ryo '{}' ({})\n", RYO_RELEASE_NAME , RYO_VERSION_FULL ); + GULPS_PRINTF("\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; + GULPS_PRINTF("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; } @@ -178,13 +188,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; + GULPS_ERRORF("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; } @@ -192,7 +202,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; } @@ -201,7 +211,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; + GULPS_PRINTF("Invalid database type ({}), available types are: {}", db_type, cryptonote::blockchain_db_types(", ")); return 0; } @@ -229,16 +239,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 { @@ -254,12 +276,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; } @@ -275,7 +297,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; } } @@ -287,7 +309,7 @@ int main(int argc, char* argv[]) } else { - std::cerr << "Unknown command: " << command.front() << std::endl; + GULPS_ERRORF("Unknown command: {}", command.front()); return 1; } } @@ -300,20 +322,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)); - // logging is now set up - MGINFO("Ryo '" << RYO_RELEASE_NAME << "' (" << RYO_VERSION_FULL << ")"); + 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); - MINFO("Moving from main() into the daemonize now."); + // logging is now set up + GULPS_GLOBALF_PRINT("Ryo '{}' ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); + + 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()); + GULPS_LOGF_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 06e68234..3597e46c 100644 --- a/src/daemon/p2p.h +++ b/src/daemon/p2p.h @@ -43,6 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "daemon_p2p" #pragma once @@ -50,8 +54,9 @@ #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 { @@ -77,12 +82,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() @@ -92,9 +97,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() @@ -104,14 +109,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 a5a3bcb7..4922ce8b 100644 --- a/src/daemon/protocol.h +++ b/src/daemon/protocol.h @@ -43,11 +43,16 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "daemon_proto" #pragma once -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { @@ -65,12 +70,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() @@ -86,16 +91,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 d722b8fc..a900209e 100644 --- a/src/daemon/rpc.h +++ b/src/daemon/rpc.h @@ -43,13 +43,18 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "daemon_rpc" #pragma once #include "rpc/core_rpc_server.h" -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + namespace daemonize { @@ -71,28 +76,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..."); + GULPS_GLOBALF_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()); + GULPS_GLOBALF_PRINT("{} RPC server initialized OK on port: {}", m_description, m_server.get_binded_port()); } void run() { - MGINFO("Starting " << m_description << " RPC server..."); + GULPS_GLOBALF_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"); + GULPS_GLOBALF_PRINT("{} RPC server started ok", m_description); } void stop() { - MGINFO("Stopping " << m_description << " RPC server..."); + GULPS_GLOBALF_PRINT("Stopping {} RPC server...", m_description); m_server.send_stop_signal(); m_server.timed_wait_server_stop(5000); } @@ -104,14 +109,14 @@ class t_rpc final ~t_rpc() { - MGINFO("Deinitializing " << m_description << " RPC server..."); + GULPS_GLOBALF_PRINT("Deinitializing {} RPC server...", m_description); try { m_server.deinit(); } catch(...) { - MERROR("Failed to deinitialize " << m_description << " RPC server..."); + GULPS_ERRORF("Failed to deinitialize {} RPC server...", m_description); } } }; diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index f8a930f0..86e95b65 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -44,6 +44,8 @@ // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "rpc_cmd_exe" + #include "daemon/rpc_command_executor.h" #include "common/password.h" #include "common/scoped_message_writer.h" @@ -56,8 +58,15 @@ #include #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "daemon" +#include "common/gulps.hpp" + + + +#define GULPS_PRINT_FAIL(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_ERROR, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_RED, "Error: ", __VA_ARGS__) +#define GULPS_PRINT_SUCCESS(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_GREEN, __VA_ARGS__) +#define GULPS_PRINTF_SUCCESS(...) GULPS_OUTPUTF(gulps::OUT_USER_1, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_BOLD_GREEN, __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) +#define GULPS_PRINTF_OK(...) GULPS_OUTPUTF(gulps::OUT_USER_1, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, GULPS_CAT_MINOR, gulps::COLOR_WHITE, __VA_ARGS__) namespace daemonize { @@ -79,21 +88,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; + GULPS_PRINTF_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) @@ -181,7 +190,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; } } @@ -216,14 +225,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 << "%)"; + GULPS_PRINTF_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; } @@ -246,12 +254,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; } @@ -275,11 +283,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; } @@ -303,12 +311,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; } @@ -331,15 +339,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"; + GULPS_PRINTF_SUCCESS("BH: {}, TH: {}, DIFF: {}, HR: {} H/s", res.height, + res.top_block_hash, + res.difficulty, + res.difficulty / res.target); return true; } @@ -347,12 +355,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) @@ -366,11 +374,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 ""; @@ -421,17 +429,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; } @@ -441,7 +449,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; } } @@ -454,7 +462,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 { @@ -462,7 +470,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); + GULPS_PRINTF_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; } @@ -486,44 +510,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; +GULPS_PRINTF_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() + GULPS_PRINTF_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]" : "")); + //GULPS_PRINTF_OK("{}-25s peer_id: {}-25s {}", address, info.peer_id, in_out); } return true; @@ -551,7 +575,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; } } @@ -560,13 +584,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 - << ", 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; + + GULPS_PRINTF_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; } @@ -592,12 +613,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); + GULPS_PRINTF_SUCCESS("Log level is now {}", level); return true; } @@ -621,12 +642,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; + GULPS_PRINTF_SUCCESS("Log categories are now {}", res.categories); return true; } @@ -649,12 +670,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; } @@ -680,13 +701,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; } @@ -712,13 +733,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; } @@ -746,7 +767,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; } } @@ -757,15 +778,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; + GULPS_PRINTF_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) @@ -775,21 +796,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; + GULPS_PRINTF_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; @@ -814,19 +835,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; @@ -850,68 +871,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; + GULPS_PRINTF_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; + GULPS_PRINTF_OK("key image: {}", kinfo.id_hash); if(kinfo.txs_hashes.size() == 1) { - tools::msg_writer() << " tx: " << kinfo.txs_hashes[0]; + GULPS_PRINTF_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(); + GULPS_PRINTF_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; + GULPS_PRINTF_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"); } } @@ -936,33 +957,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; + GULPS_PRINTF_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); } } @@ -994,12 +1017,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; } } @@ -1017,13 +1040,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; + GULPS_PRINTF_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()) { @@ -1046,13 +1070,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; + GULPS_PRINTF_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; } @@ -1072,14 +1095,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; } } @@ -1105,12 +1128,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; } @@ -1146,12 +1169,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; } @@ -1160,7 +1183,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; } @@ -1168,11 +1191,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; @@ -1196,13 +1219,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"; + GULPS_PRINTF_OK("limit-down is {} kB/s", res.limit_down ); + GULPS_PRINTF_OK("limit-up is {} kB/s", res.limit_up ); return true; } @@ -1227,13 +1250,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"; + GULPS_PRINTF_OK("Set limit-down to {} kB/s", res.limit_down ); + GULPS_PRINTF_OK("Set limit-up to {} kB/s", res.limit_up ); return true; } @@ -1255,12 +1278,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"; + GULPS_PRINTF_OK("limit-up is {} kB/s", res.limit_up ); return true; } @@ -1282,12 +1305,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"; + GULPS_PRINTF_OK("limit-down is {} kB/s", res.limit_down ); return true; } @@ -1313,12 +1336,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; + GULPS_PRINTF_OK("Max number of out peers set to {}", limit); return true; } @@ -1345,12 +1368,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; } @@ -1375,14 +1398,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; + GULPS_PRINTF_OK("version {} {}, {}/{} votes, threshold {}", (uint32_t)version , (res.enabled ? "enabled" : "not enabled") , res.votes , res.window , res.threshold); + GULPS_PRINTF_OK("current version {}, voting for version {}", (uint32_t)res.version , (uint32_t)res.voting); return true; } @@ -1405,14 +1428,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"; + GULPS_PRINTF_OK("{} banned for {} seconds", epee::string_tools::get_ip_string_from_int32(i->ip), i->seconds); } return true; @@ -1428,7 +1451,7 @@ bool t_rpc_command_executor::ban(const std::string &ip, time_t seconds) cryptonote::COMMAND_RPC_SETBANS::ban 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; @@ -1446,7 +1469,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; } } @@ -1464,7 +1487,7 @@ bool t_rpc_command_executor::unban(const std::string &ip) cryptonote::COMMAND_RPC_SETBANS::ban 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; @@ -1482,7 +1505,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; } } @@ -1511,12 +1534,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; } @@ -1544,7 +1567,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; } } @@ -1553,7 +1576,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); + GULPS_PRINTF_OK("{} {}", e.total_instances, cryptonote::print_money(e.amount)); } return true; @@ -1581,16 +1604,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"; + GULPS_PRINTF_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; } @@ -1619,22 +1640,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; + GULPS_PRINTF_OK("{} blocks long, from height {} ({} deep), diff {}: {}", chain.length , start_height , (ires.height - start_height - 1) + , chain.difficulty , chain.block_hash); } return true; } @@ -1660,13 +1681,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"; + GULPS_PRINTF_OK("Height: {}, diff {}, cum. diff {}, target {} sec", ires.height , ires.difficulty , ires.cumulative_difficulty + , ires.target); if(nblocks > 0) { @@ -1686,7 +1707,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; } } @@ -1715,8 +1736,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; + GULPS_PRINTF_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]) @@ -1727,12 +1748,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; + GULPS_PRINTF_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; + GULPS_PRINTF_OK("Voting for: {}", s); } return true; } @@ -1757,29 +1778,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; + GULPS_PRINTF_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; + GULPS_PRINTF_OK("Update downloaded to: {}", res.path); else - tools::msg_writer() << "Update download failed: " << res.status; + GULPS_PRINTF_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; } @@ -1804,12 +1825,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; } @@ -1831,19 +1852,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) << "%)"; + GULPS_PRINTF_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); @@ -1851,23 +1872,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"; + GULPS_PRINTF_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"; + GULPS_PRINTF_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) << ") -"; + GULPS_PRINTF_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 << ")"; + GULPS_PRINTF_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 98f0ff06..b904003c 100644 --- a/src/daemon/rpc_command_executor.h +++ b/src/daemon/rpc_command_executor.h @@ -61,8 +61,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 670c527c..6ec44b37 100644 --- a/src/daemonizer/CMakeLists.txt +++ b/src/daemonizer/CMakeLists.txt @@ -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/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl index b28c9c2f..bf83db53 100644 --- a/src/daemonizer/posix_daemonizer.inl +++ b/src/daemonizer/posix_daemonizer.inl @@ -41,6 +41,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. +#undef GULPS_CAT_MAJOR +#define GULPS_CAT_MAJOR "posix_dmnzer" #pragma once @@ -51,8 +53,11 @@ #include #include +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) + namespace daemonizer { +extern gulps_log_level log_scr, log_dsk; namespace { const command_line::arg_descriptor arg_detach = { @@ -87,10 +92,11 @@ inline bool daemonize( int argc, char* argv[], T_executor &&executor // universal ref , 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)) { @@ -106,7 +112,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..389807f7 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -3,9 +3,9 @@ // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // +#define GULPS_CAT_MAJOR "posix_fork" #include "daemonizer/posix_fork.h" -#include "misc_log_ex.h" #include #include @@ -13,11 +13,15 @@ #include #include #include +#include #ifndef TMPDIR #define TMPDIR "/tmp" #endif +#include "common/gulps.hpp" + + namespace posix { @@ -25,7 +29,7 @@ namespace { void quit(const std::string &message) { - LOG_ERROR(message); + GULPS_ERROR(message); throw std::runtime_error(message); } } diff --git a/src/daemonizer/windows_daemonizer.inl b/src/daemonizer/windows_daemonizer.inl index 2898b3cd..f8dc24c4 100644 --- a/src/daemonizer/windows_daemonizer.inl +++ b/src/daemonizer/windows_daemonizer.inl @@ -41,6 +41,10 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "win_dmnzer" #pragma once @@ -54,8 +58,10 @@ namespace daemonizer { +extern gulps_log_level log_scr, log_dsk; + namespace -{ +{ const command_line::arg_descriptor arg_install_service = { "install-service", "Install Windows service"}; const command_line::arg_descriptor arg_uninstall_service = { @@ -134,7 +140,7 @@ inline bool daemonize( boost::program_options::variables_map const &vm) { std::string arguments = get_argument_string(argc, argv); - + if(command_line::has_arg(vm, arg_is_service)) { // TODO - Set the service status here for return codes @@ -173,7 +179,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 0ed7f608..f2726f1d 100644 --- a/src/daemonizer/windows_service.cpp +++ b/src/daemonizer/windows_service.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "win_ser" #include #include @@ -59,6 +60,13 @@ #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 { @@ -97,7 +105,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 @@ -125,14 +133,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; } @@ -175,7 +183,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; } @@ -193,11 +201,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(); @@ -207,7 +215,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; @@ -218,7 +226,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; } @@ -231,18 +239,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(); @@ -252,7 +260,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( @@ -260,7 +268,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; } @@ -270,18 +278,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(); @@ -297,7 +305,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; } @@ -307,18 +315,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/debug_utilities/cn_deserialize.cpp b/src/debug_utilities/cn_deserialize.cpp index d45fa73c..f4dfec11 100644 --- a/src/debug_utilities/cn_deserialize.cpp +++ b/src/debug_utilities/cn_deserialize.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "cn_deser" #include "common/command_line.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -49,8 +50,10 @@ #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; @@ -59,23 +62,22 @@ using namespace cryptonote; static void print_extra_fields(const std::vector &fields) { - std::cout << "tx_extra has " << fields.size() << " field(s)" << std::endl; + GULPS_PRINTF("tx_extra has {} field(s)", fields.size() ); for(size_t n = 0; n < fields.size(); ++n) { - std::cout << "field " << n << ": "; + GULPS_PRINTF("field {}: ", n ); if(typeid(cryptonote::tx_extra_padding) == fields[n].type()) - std::cout << "extra padding: " << boost::get(fields[n]).size << " bytes"; + GULPS_PRINTF("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; + GULPS_PRINTF("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); + GULPS_PRINTF("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; + GULPS_PRINTF("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); + GULPS_PRINTF("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"); } } @@ -111,11 +113,17 @@ 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; + GULPS_PRINTF("Ryo '{} ({})", RYO_RELEASE_NAME, RYO_VERSION_FULL); + GULPS_PRINT( desc_options ); return 0; } @@ -123,12 +131,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; @@ -144,7 +150,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; } } @@ -152,7 +158,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; } } @@ -173,8 +179,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; } @@ -183,17 +189,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()) { @@ -201,17 +207,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 4694dd21..68f80be4 100644 --- a/src/debug_utilities/object_sizes.cpp +++ b/src/debug_utilities/object_sizes.cpp @@ -41,6 +41,7 @@ // 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. +#define GULPS_CAT_MAJOR "obj_sizes" #include "blockchain_db/lmdb/db_lmdb.h" #include "cryptonote_basic/cryptonote_basic.h" @@ -59,8 +60,9 @@ #include "wallet/wallet2.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "debugtools.objectsizes" +#include "common/gulps.hpp" + + class size_logger { @@ -68,7 +70,7 @@ class size_logger ~size_logger() { for(const auto &i : types) - std::cout << std::to_string(i.first) << "\t" << i.second << std::endl; + GULPS_PRINTF("{}\t{}",i.first, i.second); } void add(const char *type, size_t size) { types.insert(std::make_pair(size, type)); } private: @@ -82,7 +84,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 427a9125..695fb27a 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -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 00462efa..4690ec96 100644 --- a/src/device/device.cpp +++ b/src/device/device.cpp @@ -42,13 +42,15 @@ // 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. // +#define GULPS_CAT_MAJOR "device" #include "device.hpp" #include "device_default.hpp" #ifdef HAVE_PCSC #include "device_ledger.hpp" #endif -#include "misc_log_ex.h" + +#include "common/gulps.hpp" namespace hw { @@ -76,12 +78,11 @@ 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_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_default.cpp b/src/device/device_default.cpp index 8fd9563a..3958f238 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -173,7 +173,7 @@ 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); @@ -181,7 +181,7 @@ std::vector device_default::get_subaddress_spend_public_keys 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); @@ -409,10 +409,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_ledger.cpp b/src/device/device_ledger.cpp index a7a4fc76..685164e9 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -61,7 +61,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/log.cpp b/src/device/log.cpp index fc38a667..1cdd2526 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -44,7 +44,7 @@ // #include "log.hpp" -#include "misc_log_ex.h" +#include "common/gulps.hpp" namespace hw { @@ -53,8 +53,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/gen_multisig/CMakeLists.txt b/src/gen_multisig/CMakeLists.txt index 24ff95b5..d7a79d0e 100644 --- a/src/gen_multisig/CMakeLists.txt +++ b/src/gen_multisig/CMakeLists.txt @@ -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 a790362e..b5c3b3b5 100644 --- a/src/gen_multisig/gen_multisig.cpp +++ b/src/gen_multisig/gen_multisig.cpp @@ -49,28 +49,34 @@ * * \brief Generates a set of multisig wallets */ +#define GULPS_CAT_MAJOR "gen_multisig" + #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 GULPS_PRINTF_FAIL(...) GULPS_ERRORF(tr("Error: "), __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) +#define GULPS_PRINTF_OK(...) GULPS_PRINTF(__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" + namespace genms { @@ -95,7 +101,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(); + GULPS_PRINTF_OK(genms::tr("Generating {} {}/{} multisig wallets"), total, threshold, total); const auto pwd_container = tools::password_container::prompt(true, "Enter password for new multisig wallets"); @@ -119,7 +125,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; } } @@ -153,7 +159,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; } } @@ -161,19 +167,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(); + GULPS_PRINTF_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; } @@ -192,6 +197,12 @@ int main(int argc, char *argv[]) } #endif + gulps::inst().set_thread_tag("GEN_MULTISIG"); + + 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)); + 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); @@ -208,11 +219,15 @@ 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; + + gulps::inst().remove_output(temp_handle); bool testnet, stagenet; uint32_t threshold = 0, total = 0; @@ -222,14 +237,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; } } @@ -237,7 +252,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); @@ -246,14 +261,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(); + GULPS_PRINTF_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()) @@ -262,13 +277,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); @@ -276,5 +291,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 37b59854..598d57ce 100644 --- a/src/mnemonics/CMakeLists.txt +++ b/src/mnemonics/CMakeLists.txt @@ -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/electrum-words.cpp b/src/mnemonics/electrum-words.cpp index 8db181b1..6642afe5 100644 --- a/src/mnemonics/electrum-words.cpp +++ b/src/mnemonics/electrum-words.cpp @@ -52,14 +52,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/language_base.h b/src/mnemonics/language_base.h index 7845b3ef..711a1c8e 100644 --- a/src/mnemonics/language_base.h +++ b/src/mnemonics/language_base.h @@ -27,6 +27,10 @@ // 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. +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "lan_base" /*! * \file language_base.h @@ -37,11 +41,12 @@ #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. @@ -102,7 +107,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 +123,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/multisig/CMakeLists.txt b/src/multisig/CMakeLists.txt index bcee44c6..2f4967e8 100644 --- a/src/multisig/CMakeLists.txt +++ b/src/multisig/CMakeLists.txt @@ -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 8215994e..861b6a6d 100644 --- a/src/multisig/multisig.cpp +++ b/src/multisig/multisig.cpp @@ -50,8 +50,7 @@ #include "ringct/rctOps.h" #include -//#undef RYO_DEFAULT_LOG_CATEGORY -//#define RYO_DEFAULT_LOG_CATEGORY "multisig" + using namespace std; @@ -73,7 +72,7 @@ void generate_multisig_N_N(const account_keys &keys, const std::vector @@ -62,6 +66,8 @@ #include "storages/levin_abstract_invoke2.h" #include "warnings.h" +#include "common/gulps.hpp" + PUSH_WARNINGS DISABLE_VS_WARNINGS(4355) @@ -281,11 +287,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 diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 8a3db318..1ca4db86 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -45,6 +45,10 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers // IP blocking adapted from Boolberry +#ifdef GULPS_CAT_MAJOR + #undef GULPS_CAT_MAJOR +#endif +#define GULPS_CAT_MAJOR "net_node" #include #include @@ -69,8 +73,11 @@ #include #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)))) @@ -104,7 +111,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); @@ -131,7 +138,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(); } @@ -160,7 +167,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; } //----------------------------------------------------------------------------------- @@ -190,7 +197,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."); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_CYAN, "Host {} unblocked.", address.host_str()); return true; } return false; @@ -227,7 +234,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."); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_CYAN, "Host {} blocked.", addr.host_str()); return true; } //----------------------------------------------------------------------------------- @@ -239,7 +246,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."); + GULPS_GLOBALF_PRINT_CLR(gulps::COLOR_CYAN, "Host {} unblocked", address.host_str()); return true; } //----------------------------------------------------------------------------------- @@ -248,11 +255,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); + GULPS_LOGF_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); } @@ -289,7 +296,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); } } @@ -342,7 +349,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); @@ -351,7 +358,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) @@ -361,11 +368,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()); + GULPS_INFOF("Added seed node: {}", na.str()); } else { - MWARNING("IPv6 unsupported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + GULPS_WARNF("IPv6 unsupported, skip '{}' -> {}", host , endpoint.address().to_v6().to_string(ec) ); throw std::runtime_error("IPv6 unsupported"); } } @@ -401,7 +408,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) { @@ -431,7 +438,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); + GULPS_LOGF_L1("dns_threads[{}] created for: {}", result_index , addr_str); // TODO: care about dnssec avail/valid bool avail, valid; std::vector addr_list; @@ -439,7 +446,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"); + GULPS_LOGF_L1("dns_threads[{}] DNS resolve done", result_index ); boost::this_thread::interruption_point(); } catch(const boost::thread_interrupted &) @@ -447,11 +454,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"); + GULPS_WARNF("dns_threads[{}] interrupted", result_index ); return; } - MINFO("dns_threads[" << result_index << "] addr_str: " << addr_str << " number of results: " << addr_list.size()); + GULPS_INFOF("dns_threads[{}] addr_str: {}", result_index , addr_str ); dns_results[result_index] = addr_list; }); @@ -459,14 +466,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"); + GULPS_LOGF_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"); + GULPS_WARNF("dns_threads[{}] timed out, sending interrupt", i ); th.interrupt(); } ++i; @@ -475,7 +482,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"); + GULPS_LOGF_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()) { @@ -489,9 +496,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); @@ -501,10 +508,10 @@ bool node_server::init(const boost::program_options::vari for(const auto &full_addr : full_addrs) { - MDEBUG("Seed node: " << full_addr); + GULPS_LOGF_L1("Seed node: {}", full_addr); append_net_address(m_seed_nodes, full_addr); } - MDEBUG("Number of seed nodes: " << m_seed_nodes.size()); + GULPS_LOGF_L1("Number of seed nodes: {}", m_seed_nodes.size()); m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir); @@ -514,10 +521,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); @@ -538,14 +545,14 @@ bool node_server::init(const boost::program_options::vari return res; //try to bind - MINFO("Binding on " << m_bind_ip << ":" << m_port); + GULPS_INFOF("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); + GULPS_INFOF_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); + GULPS_LOGF_L1("External port defined as {}", m_external_port); // add UPnP port mapping if(!m_no_igd) @@ -565,7 +572,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(); @@ -588,7 +595,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 @@ -601,13 +608,13 @@ bool node_server::run() attrs.set_stack_size(THREAD_STACK_SIZE); //go to loop - MINFO("Run net_service loop( " << thrds_count << " threads)..."); + GULPS_INFOF("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; } @@ -634,10 +641,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); + GULPS_WARNF("Failed to create data directory: {}", m_config_folder); return false; } @@ -646,14 +653,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); + GULPS_WARNF("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; } @@ -661,9 +668,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) { @@ -696,19 +703,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) << ")"); + GULPS_LOGF_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."); + GULPS_LOGF_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."); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection.", contextx_str(context)); add_host_fail(context.m_remote_address); return; } @@ -717,7 +724,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."); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE invoked, but process_payload_sync_data returned false, dropping connection.", contextx_str(context)); hsh_result = false; return; } @@ -727,15 +734,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"); + GULPS_LOGF_L1("{} Connection to self detected, dropping connection", contextx_str(context)); hsh_result = false; return; } - LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE INVOKED OK"); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE INVOKED OK", contextx_str(context)); } else { - LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK"); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK", contextx_str(context)); } }, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT); @@ -747,7 +754,7 @@ bool node_server::do_handshake_with_peer(peerid_type &pi, if(!hsh_result) { - LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed"); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE Failed", contextx_str(context_)); m_net_server.get_config_object().close(context_.m_connection_id); } else @@ -771,13 +778,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) << ")"); + GULPS_LOGF_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."); + GULPS_LOGF_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); } @@ -788,7 +795,7 @@ bool node_server::do_peer_timed_sync(const epee::net_util if(!r) { - LOG_WARNING_CC(context_, "COMMAND_TIMED_SYNC Failed"); + GULPS_LOGF_L1("{} COMMAND_TIMED_SYNC Failed", contextx_str(context_)); return false; } return true; @@ -803,7 +810,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 << ")"); + GULPS_LOGF_L1("Random connection index={}(x={}, max_index={})", res , x , max_index ); return res; } //----------------------------------------------------------------------------------- @@ -866,19 +873,8 @@ 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) @@ -893,11 +889,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") - << ")..."); + GULPS_LOGF_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(); @@ -910,7 +905,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; @@ -922,8 +917,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; } @@ -931,7 +925,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."); + GULPS_LOGF_L1("{} CONNECTION HANDSHAKED OK AND CLOSED.", contextx_str(con)); return true; } @@ -951,18 +945,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."); + GULPS_LOGF_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") - << ")..."); + GULPS_LOGF_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(); @@ -975,9 +968,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()); - + GULPS_INFOF("{} {} Connect failed to {}", contextx_str(con), priority_str(is_priority), na.str()); return false; } @@ -988,19 +979,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()); - + GULPS_INFOF("{} {} 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."); + GULPS_LOGF_L1("{} CONNECTION HANDSHAKED OK AND CLOSED.", contextx_str(con)); return true; } -#undef LOG_PRINT_CC_PRIORITY_NODE +#undef priority_str //----------------------------------------------------------------------------------- template @@ -1022,11 +1012,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()); + GULPS_LOGF_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; } @@ -1040,13 +1030,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)); + GULPS_LOGF_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; } @@ -1090,7 +1080,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; @@ -1098,15 +1088,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()); + GULPS_LOGF_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; } @@ -1116,13 +1106,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")); + GULPS_LOGF_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; } @@ -1151,10 +1141,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); + GULPS_LOGF_L1("Fallback seed node: {}", peer); append_net_address(m_seed_nodes, peer); } fallback_nodes_added = true; @@ -1162,7 +1152,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; } } @@ -1223,7 +1213,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; } @@ -1311,7 +1301,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) { @@ -1325,7 +1315,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; } //----------------------------------------------------------------------------------- @@ -1341,7 +1331,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); + GULPS_WARNF("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; @@ -1356,8 +1346,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_)); + GULPS_LOGF_L1("{} REMOTE PEERLIST: TIME_DELTA: {}, remote peerlist size={}",contextx_str(context), delta , peerlist_.size()); + GULPS_LOGF_L1("{} REMOTE PEERLIST: {}",contextx_str(context), print_peerlist_to_string(peerlist_)); return m_peerlist.merge_peerlist(peerlist_); } //----------------------------------------------------------------------------------- @@ -1384,17 +1374,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); + GULPS_WARNF("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); + GULPS_WARNF("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 << ")"); + GULPS_WARNF("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); @@ -1402,7 +1392,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 @@ -1526,7 +1516,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; @@ -1542,7 +1532,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()); + GULPS_LOGF_L1("{} back ping connect failed to {}",contextx_str(ping_context), address.str()); return false; } COMMAND_PING::request req; @@ -1560,13 +1550,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) << ")"); + GULPS_LOGF_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); + GULPS_LOGF_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; } @@ -1576,7 +1566,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()); + GULPS_LOGF_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; } @@ -1584,7 +1574,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."); + GULPS_LOGF_L1("{} Failed to call connect_async, network error.", contextx_str(context)); } return r; } @@ -1601,7 +1591,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) << ")"); + GULPS_LOGF_L1("{} COMMAND_REQUEST_SUPPORT_FLAGS invoke failed. ({}, {})", contextx_str(context_), code , epee::levin::get_err_descr(code) ); return; } @@ -1617,7 +1607,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"); + GULPS_LOGF_L1("{} Failed to process_payload_sync_data(), dropping connection", contextx_str(context)); drop_connection(context); return 1; } @@ -1626,7 +1616,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"); + GULPS_LOGF_L1("{} COMMAND_TIMED_SYNC", contextx_str(context)); return 1; } //----------------------------------------------------------------------------------- @@ -1636,7 +1626,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)); + GULPS_LOGF_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; @@ -1644,7 +1634,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"); + GULPS_LOGF_L1("{} COMMAND_HANDSHAKE came not from incoming connection", contextx_str(context)); drop_connection(context); add_host_fail(context.m_remote_address); return 1; @@ -1652,28 +1642,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?)"); + GULPS_LOGF_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."); + GULPS_LOGF_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."); + GULPS_LOGF_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"); + GULPS_LOGF_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; } @@ -1688,7 +1678,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; @@ -1699,7 +1689,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); + GULPS_LOGF_L1("{} PING SUCCESS {}:{}",contextx_str(context), context.m_remote_address.host_str() , port_l); }); } @@ -1711,14 +1701,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"); + GULPS_LOGF_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"); + GULPS_LOGF_L1("{} COMMAND_PING", contextx_str(context)); rsp.status = PING_OK_RESPONSE_STATUS_TEXT; rsp.peer_id = m_config.m_peer_id; return 1; @@ -1730,15 +1720,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)); + GULPS_INFOF("\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()); + GULPS_INFOF("Connections: \r\n{}", print_connections_container()); return true; } //----------------------------------------------------------------------------------- @@ -1761,7 +1750,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"); + GULPS_INFOF("[{}] NEW CONNECTION", epee::net_utils::print_connection_context(context) ); } //----------------------------------------------------------------------------------- template @@ -1777,7 +1766,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"); + GULPS_INFOF("[{}] CLOSE CONNECTION", epee::net_utils::print_connection_context(context) ); } template @@ -1815,7 +1804,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); } @@ -1866,7 +1855,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; } @@ -1882,7 +1871,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"); + GULPS_INFOF("Set limit-up to {} kB/s", limit ); return true; } @@ -1896,7 +1885,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"); + GULPS_INFOF("Set limit-down to {} kB/s", limit ); return true; } @@ -1919,12 +1908,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"); + GULPS_INFOF("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"); + GULPS_INFOF("Set limit-down to {} kB/s", limit_down ); } return true; @@ -1977,14 +1966,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)); + GULPS_LOGF_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)); + GULPS_LOGF_L2("PEER PROMOTED TO WHITE PEER LIST IP address: {} Peer ID: {}", pe.adr.host_str() , peerid_type(pe.id)); return true; } @@ -1992,7 +1981,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 @@ -2020,38 +2009,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)); + GULPS_LOGF_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 @@ -2076,31 +2065,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)); + GULPS_LOGF_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_peerlist.h b/src/p2p/net_peerlist.h index f3d029a8..cfc8d972 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -371,7 +371,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; @@ -379,12 +379,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; @@ -409,12 +409,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; @@ -438,12 +438,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); @@ -456,12 +456,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); @@ -477,12 +477,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); @@ -495,12 +495,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); @@ -515,12 +515,12 @@ inline bool peerlist_manager::get_and_empty_anchor_peerlist(std::vector({{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"); } @@ -279,7 +286,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"); } diff --git a/src/p2p/stdafx.h b/src/p2p/stdafx.h index 9c0f3eb9..2ec396e3 100644 --- a/src/p2p/stdafx.h +++ b/src/p2p/stdafx.h @@ -59,4 +59,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/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt index 0e8d914a..9f7a8e31 100644 --- a/src/ringct/CMakeLists.txt +++ b/src/ringct/CMakeLists.txt @@ -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 675dcd1a..c19ff519 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -43,9 +43,10 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Adapted from Java code by Sarang Noether +#define GULPS_CAT_MAJOR "bulletproofs" #include "common/perf_timer.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include extern "C" { #include "crypto/crypto-ops.h" @@ -54,8 +55,6 @@ extern "C" { #include "multiexp.h" #include "rctOps.h" -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "bulletproofs" #define DEBUG_BP @@ -84,7 +83,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); @@ -96,7 +95,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; @@ -107,7 +106,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; @@ -162,7 +161,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) { @@ -174,7 +173,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) { @@ -186,7 +185,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) { @@ -198,7 +197,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) { @@ -210,7 +209,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) { @@ -315,7 +314,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; } @@ -323,9 +322,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) { @@ -414,8 +413,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: @@ -440,14 +439,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; } @@ -484,7 +483,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); @@ -517,7 +516,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; } @@ -544,7 +543,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 @@ -598,7 +597,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; } @@ -639,12 +638,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); @@ -654,7 +653,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; @@ -708,8 +707,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 @@ -737,14 +736,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; } @@ -763,8 +762,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); } } @@ -799,7 +798,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; } @@ -811,7 +810,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; @@ -833,7 +832,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 @@ -841,7 +840,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; } @@ -893,7 +892,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; } @@ -916,7 +915,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); @@ -949,19 +948,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; @@ -984,7 +983,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(); @@ -992,13 +991,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 @@ -1026,7 +1025,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); @@ -1058,7 +1057,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 @@ -1067,7 +1066,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); @@ -1109,8 +1108,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); @@ -1158,7 +1157,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; @@ -1180,7 +1179,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/multiexp.cc b/src/ringct/multiexp.cc index 83850901..521ed37c 100644 --- a/src/ringct/multiexp.cc +++ b/src/ringct/multiexp.cc @@ -43,18 +43,16 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Adapted from Python code by Sarang Noether +#define GULPS_CAT_MAJOR "multiexp" #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) @@ -119,7 +117,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; @@ -151,7 +149,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; @@ -226,7 +224,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) @@ -345,7 +343,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; } @@ -355,9 +353,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]}); @@ -366,12 +364,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"); + GULPS_INFOF("Hi/Gi cache size: {} kB", (sizeof(Hi_cache) + sizeof(Gi_cache)) / 1024 ); + GULPS_INFOF("Hi_p3/Gi_p3 cache size: {} kB", (sizeof(Hi_p3_cache) + sizeof(Gi_p3_cache)) / 1024 ); + GULPS_INFOF("Straus cache size: {} kB", sizeof(straus_cache) / 1024 ); + GULPS_INFOF("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"); + GULPS_INFOF("Total cache size: {}kB", cache_size / 1024 ); } void straus_cache::init_cache(const std::vector &data, size_t N) @@ -379,7 +377,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; @@ -405,8 +403,8 @@ 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; @@ -512,7 +510,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) @@ -533,13 +531,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; @@ -586,7 +584,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)); @@ -614,8 +612,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) @@ -630,10 +628,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 eb7316fd..963ec066 100644 --- a/src/ringct/multiexp.h +++ b/src/ringct/multiexp.h @@ -43,12 +43,14 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Adapted from Python code by Sarang Noether +#undef GULPS_CAT_MAJOR +#define GULPS_CAT_MAJOR "multiexp" #pragma once #include "cryptonote_config.h" #include "crypto/crypto.h" -#include "misc_log_ex.h" +#include "common/gulps.hpp" #include "rctTypes.h" #include #include @@ -89,7 +91,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"); } }; diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index 7c04dd40..affc6a65 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -43,22 +43,25 @@ // 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. +#define GULPS_CAT_MAJOR "rctOps" #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_WARN(str); \ + throw std::runtime_error(str); \ } \ } @@ -101,7 +104,7 @@ key skGen() //Mainly used in testing keyV skvGen(size_t rows) { - CHECK_AND_ASSERT_THROW_MES(rows > 0, "0 keys requested"); + 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]); diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index f484cdd1..8dcc8844 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -43,6 +43,7 @@ // 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. +#define GULPS_CAT_MAJOR "rctSigs" #include "rctSigs.h" #include "bulletproofs.h" @@ -50,19 +51,16 @@ #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" - -#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; \ } \ } @@ -73,7 +71,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; } @@ -82,7 +80,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; @@ -303,25 +301,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; @@ -342,7 +340,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; @@ -454,11 +452,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)); @@ -518,16 +516,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); @@ -585,8 +583,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; @@ -617,12 +615,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); @@ -666,7 +664,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); @@ -757,14 +755,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; @@ -783,7 +781,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); @@ -822,20 +820,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; @@ -859,7 +857,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 } @@ -869,7 +867,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) { @@ -948,12 +946,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 { @@ -977,7 +975,7 @@ bool verRct(const rctSig &rv, bool semantics) { if(!results[i]) { - LOG_PRINT_L1("Range proof verified failed for proof " << i); + GULPS_LOGF_L1("Range proof verified failed for proof {}", i); return false; } } @@ -992,7 +990,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; } } @@ -1001,12 +999,12 @@ bool verRct(const rctSig &rv, bool semantics) } catch(const std::exception &e) { - LOG_PRINT_L1("Error in verRct: " << e.what()); + GULPS_LOGF_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; } } @@ -1027,25 +1025,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(); @@ -1075,7 +1073,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; } @@ -1093,7 +1091,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; } @@ -1102,7 +1100,7 @@ bool verRctSemanticsSimple(const std::vector &rvv) { if(!results[i]) { - LOG_PRINT_L1("Range proof verified failed for proof " << i); + GULPS_LOGF_L1("Range proof verified failed for proof {}", i); return false; } } @@ -1112,12 +1110,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()); + GULPS_LOGF_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; } } @@ -1135,13 +1133,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()); @@ -1167,7 +1165,7 @@ bool verRctNonSemanticsSimple(const rctSig &rv) { if(!results[i]) { - LOG_PRINT_L1("verRctMGSimple failed for input " << i); + GULPS_LOGF_L1("verRctMGSimple failed for input {}", i); return false; } } @@ -1177,12 +1175,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()); + GULPS_LOGF_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; } } @@ -1199,9 +1197,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]; @@ -1212,14 +1210,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); } @@ -1232,9 +1230,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]; @@ -1245,14 +1243,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); } @@ -1265,19 +1263,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/rctTypes.cpp b/src/ringct/rctTypes.cpp index 9da6d905..fd70a370 100644 --- a/src/ringct/rctTypes.cpp +++ b/src/ringct/rctTypes.cpp @@ -43,16 +43,14 @@ // 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. +#define GULPS_CAT_MAJOR "rctTypes" #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 { @@ -63,86 +61,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]); + GULPS_PRINTF("{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"); + GULPS_PRINTF(" ... {} ... ", 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]); + GULPS_PRINTF("{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"); + GULPS_PRINTF("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); + GULPS_PRINTF("{}\n", st); } //Various Conversions @@ -264,14 +260,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(); } @@ -281,7 +277,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; @@ -291,11 +287,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); } @@ -305,7 +301,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/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 2c641272..417d8ab3 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -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 fb8b01fb..1e624f9e 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -43,6 +43,7 @@ // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers +#define GULPS_CAT_MAJOR "c_rpc_serv" #include "include_base_utils.h" #include "string_tools.h" @@ -66,8 +67,9 @@ 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 @@ -234,7 +236,7 @@ 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"); + GULPS_CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); return ss.str(); } //------------------------------------------------------------------------------------------------------------------------------ @@ -244,7 +246,7 @@ static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobd if(!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx)) { - MERROR("Failed to parse and validate tx from blob"); + GULPS_ERROR("Failed to parse and validate tx from blob"); return cryptonote::blobdata(); } return get_pruned_tx_blob(tx); @@ -309,7 +311,7 @@ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request & } } - MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, pruned size " << pruned_size << ", unpruned size " << unpruned_size); + GULPS_LOGF_L1("on_get_blocks: {} blocks, {} txes, pruned size {}, unpruned size {}", bs.size() , ntxes , pruned_size , unpruned_size); res.status = CORE_RPC_STATUS_OK; return true; } @@ -335,7 +337,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 "); + GULPS_LOGF_L1("on_get_alt_blocks_hashes: {} blocks ", blks.size() ); res.status = CORE_RPC_STATUS_OK; return true; } @@ -426,14 +428,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); + GULPS_LOGF_L2("COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: \n{}", s); res.status = CORE_RPC_STATUS_OK; return true; } @@ -523,13 +525,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); + GULPS_LOGF_L2("COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS: \n{}", s); res.status = CORE_RPC_STATUS_OK; return true; } @@ -548,7 +550,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() << "]"); + GULPS_LOGF_L2("COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES: [{}]", res.o_indexes.size() ); return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -583,7 +585,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"); + GULPS_LOGF_L2("Found {}/{} transactions on the blockchain", txs.size() , vh.size() ); // try the pool for any missing txes size_t found_in_pool = 0; @@ -642,7 +644,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"); + GULPS_LOGF_L2("Found {}/{} transactions in the pool", found_in_pool , vh.size() ); } std::list::const_iterator txhi = req.txs_hashes.begin(); @@ -668,7 +670,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; } } @@ -701,7 +703,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"); + GULPS_LOGF_L2("{} transactions found, {} not found", res.txs.size(), res.missed_tx.size()); res.status = CORE_RPC_STATUS_OK; return true; } @@ -785,7 +787,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); + GULPS_PRINTF("[on_send_raw_tx]: Failed to parse tx from hexbuff: {}", req.tx_as_hex); res.status = "Failed"; return true; } @@ -815,18 +817,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); + GULPS_PRINTF("[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); + GULPS_PRINTF("[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; @@ -849,22 +851,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; } @@ -881,7 +883,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; } @@ -891,7 +893,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; @@ -904,7 +906,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; @@ -995,17 +997,15 @@ 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); - res.status = CORE_RPC_STATUS_OK; + + res.status = "Error: not implemented"; //\todo return true; } //------------------------------------------------------------------------------------------------------------------------------ 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(); - res.status = CORE_RPC_STATUS_OK; + res.status = "Error: not implemented"; //\todo return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -1167,7 +1167,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); @@ -1176,7 +1176,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 get 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)); @@ -1184,7 +1184,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) @@ -1192,7 +1192,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); @@ -1297,7 +1297,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; } @@ -1318,7 +1318,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 << ")"); + GULPS_INFOF("{} 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; @@ -1345,7 +1345,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; @@ -1969,27 +1969,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); + GULPS_INFOF("New version downloaded to {}", path); } else { - MDEBUG("We already have " << path << " with expected hash"); + GULPS_LOGF_L1("We already have {} with expected hash", path ); } res.path = path.string(); diff --git a/src/rpc/daemon_handler.cpp b/src/rpc/daemon_handler.cpp index d3126a01..9a45b760 100644 --- a/src/rpc/daemon_handler.cpp +++ b/src/rpc/daemon_handler.cpp @@ -344,11 +344,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 = ""; @@ -409,7 +409,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; @@ -434,14 +434,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; } @@ -459,7 +459,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; } @@ -470,7 +470,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; } @@ -525,7 +525,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; } @@ -679,7 +679,6 @@ void DaemonHandler::handle(const SetLogLevel::Request &req, SetLogLevel::Respons else { res.status = Message::STATUS_OK; - mlog_set_log_level(req.level); } } @@ -842,7 +841,7 @@ bool DaemonHandler::getBlockHeaderByHash(const crypto::hash &hash_in, cryptonote std::string DaemonHandler::handle(const std::string &request) { - MDEBUG("Handling RPC request: " << request); + GULPS_LOGF_L1("Handling RPC request: {}", request); Message *resp_message = NULL; @@ -893,7 +892,7 @@ std::string DaemonHandler::handle(const std::string &request) delete resp_message; resp_message = NULL; - MDEBUG("Returning RPC response: " << response); + GULPS_LOGF_L1("Returning RPC response: {}", response); return response; } diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index d1ccc500..f41b1bf5 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -42,6 +42,8 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +#define GULPS_CAT_MAJOR "rpc_args" + #include "rpc_args.h" #include "common/command_line.h" @@ -50,6 +52,8 @@ #include #include +#include "common/gulps.hpp" + namespace cryptonote { rpc_args::descriptors::descriptors() @@ -81,14 +85,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; } } @@ -103,7 +107,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; } } @@ -113,7 +117,7 @@ boost::optional rpc_args::process(const boost::program_options::variab { if(!config.login) { - LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RPC 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/zmq_server.cpp b/src/rpc/zmq_server.cpp index 464053e5..24eda0b2 100644 --- a/src/rpc/zmq_server.cpp +++ b/src/rpc/zmq_server.cpp @@ -41,10 +41,13 @@ // 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. +#define GULPS_CAT_MAJOR "zmq_serv" #include "zmq_server.h" #include +#include "common/gulps.hpp" + namespace cryptonote { @@ -79,7 +82,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); @@ -87,16 +90,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(); } @@ -104,7 +107,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; } @@ -123,7 +126,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/serialization/CMakeLists.txt b/src/serialization/CMakeLists.txt index 2e740876..d5143077 100644 --- a/src/serialization/CMakeLists.txt +++ b/src/serialization/CMakeLists.txt @@ -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/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 472e39df..dd43e046 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -46,16 +46,18 @@ /*! * \file simplewallet.cpp - * + * * \brief Source file that defines simple_wallet class. */ + +#define GULPS_CAT_MAJOR "cli_wallet" + #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 @@ -82,6 +84,16 @@ #include #include +#include "common/gulps.hpp" + +#define GULPS_PRINT_FAIL(...) GULPS_ERROR(tr("Error: "), __VA_ARGS__) +#define GULPS_PRINT_OK(...) GULPS_PRINT(__VA_ARGS__) +#define GULPS_PRINTF_OK(...) GULPS_PRINTF(__VA_ARGS__) +#define GULPS_PRINT_BOLD(...) GULPS_PRINT_CLR(gulps::COLOR_BOLD_WHITE, __VA_ARGS__) +#define GULPS_PRINT_GREEN(...) GULPS_PRINT_CLR(gulps::COLOR_GREEN, __VA_ARGS__) +#define GULPS_PRINTF_GREEN(...) GULPS_PRINTF_CLR(gulps::COLOR_GREEN, __VA_ARGS__) +#define GULPS_PRINT_SECRET(...) GULPS_OUTPUT(gulps::OUT_USER_1, gulps::LEVEL_PRINT, GULPS_CAT_MAJOR, "secret", gulps::COLOR_WHITE, __VA_ARGS__) + #ifdef WIN32 #undef fmt #include @@ -89,9 +101,7 @@ #include #endif -#ifdef HAVE_READLINE #include "readline_buffer.h" -#endif using namespace std; using namespace epee; @@ -100,8 +110,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" + #define EXTENDED_LOGS_FILE "wallet_details.log" @@ -157,10 +166,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); @@ -178,7 +186,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); @@ -193,13 +201,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; } @@ -230,21 +236,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)) @@ -284,7 +275,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; } } @@ -310,7 +301,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; } @@ -344,7 +335,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; } @@ -367,7 +358,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 {}; } } @@ -381,50 +372,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"); + GULPS_LOGF_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"); + GULPS_LOGF_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"); + GULPS_LOGF_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()) { @@ -432,58 +421,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(); + GULPS_ERRORF(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 transaction 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) @@ -493,10 +485,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; + GULPS_ERRORF(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; } @@ -519,11 +511,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(); } @@ -540,10 +532,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(); } @@ -557,20 +549,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; } @@ -579,23 +570,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; } @@ -609,12 +601,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()) @@ -627,13 +619,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; } @@ -649,7 +641,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; } @@ -663,22 +655,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; } @@ -701,7 +693,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; } @@ -717,7 +709,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; } @@ -729,11 +721,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; } @@ -741,15 +733,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())); + GULPS_PRINTF_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) @@ -767,12 +759,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; } @@ -787,12 +779,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(); + GULPS_PRINTF_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(); + GULPS_PRINTF_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; } @@ -801,45 +793,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; } @@ -847,44 +839,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; } @@ -892,7 +884,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; } @@ -905,26 +897,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; } @@ -934,30 +925,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; } @@ -965,13 +956,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; } @@ -983,22 +974,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()) @@ -1014,18 +1005,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; } @@ -1035,22 +1026,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()) @@ -1064,7 +1055,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)); @@ -1076,13 +1067,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) @@ -1093,12 +1082,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; } @@ -1114,22 +1103,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()) @@ -1145,18 +1134,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; } @@ -1165,8 +1154,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 @@ -1178,8 +1166,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; } @@ -1190,22 +1178,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()) @@ -1223,12 +1211,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(); + GULPS_ERRORF(tr("Error: Multisig transaction signed by only {} signers, needs {} more signatures"), txs.m_signers.size(), threshold - txs.m_signers.size()); return true; } @@ -1236,8 +1224,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) @@ -1246,8 +1234,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; @@ -1259,22 +1247,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()) @@ -1291,12 +1279,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(); + GULPS_ERRORF(tr("Error: Multisig transaction signed by only {} signers, needs {} more signatures"), txs.m_signers.size(), threshold - txs.m_signers.size()); return true; } @@ -1311,21 +1299,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; @@ -1337,19 +1325,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; } @@ -1361,7 +1349,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; } @@ -1371,12 +1359,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; @@ -1387,13 +1375,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; } @@ -1408,7 +1396,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; } @@ -1418,14 +1406,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; @@ -1433,7 +1421,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; @@ -1443,14 +1431,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; } @@ -1462,7 +1450,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; } @@ -1492,7 +1480,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; } } @@ -1502,7 +1490,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; @@ -1511,19 +1499,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; @@ -1534,13 +1522,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; } @@ -1550,7 +1538,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; @@ -1561,26 +1549,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; @@ -1595,14 +1583,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; } @@ -1636,7 +1624,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; } @@ -1655,7 +1643,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; } @@ -1663,18 +1651,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) @@ -1686,12 +1674,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; } } @@ -1703,7 +1691,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") @@ -1715,7 +1703,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; } } @@ -1730,12 +1718,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; } } @@ -1816,7 +1804,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; } @@ -1834,7 +1822,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; } @@ -1852,7 +1840,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; } @@ -1896,7 +1884,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; } @@ -1930,7 +1918,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); @@ -2001,7 +1989,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); @@ -2014,11 +2002,11 @@ bool simple_wallet::help(const std::vector &args /* = std::vector.")); } //---------------------------------------------------------------------------------------------------- +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()) @@ -2359,57 +2365,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") @@ -2418,30 +2406,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; } @@ -2450,18 +2443,18 @@ 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(!args.empty()) + // mlog_set_log(args[0].c_str()); + //GULPS_PRINT_OK("New log categories: ", mlog_get_categories()); 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; @@ -2470,7 +2463,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): " @@ -2478,41 +2471,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); + GULPS_LOGF_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 @@ -2520,18 +2512,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; } @@ -2539,7 +2531,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; } @@ -2549,10 +2541,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) { @@ -2565,7 +2557,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) @@ -2584,7 +2576,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; @@ -2594,12 +2586,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; @@ -2617,9 +2612,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; } @@ -2633,13 +2628,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; } @@ -2658,7 +2653,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; @@ -2676,18 +2671,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; } @@ -2697,13 +2692,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()); @@ -2714,17 +2709,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()) { @@ -2735,18 +2730,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()) { @@ -2757,18 +2752,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; } @@ -2778,13 +2773,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()); @@ -2795,13 +2790,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()); @@ -2812,26 +2807,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. @@ -2847,25 +2842,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; + GULPS_PRINTF_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: "); @@ -2873,13 +2868,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; } @@ -2889,13 +2884,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()); @@ -2904,12 +2899,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; } @@ -2924,17 +2919,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()); @@ -2948,25 +2943,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()) @@ -2978,7 +2973,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) @@ -2989,19 +2984,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); @@ -3012,7 +3005,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; @@ -3029,7 +3022,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()) @@ -3063,12 +3056,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; @@ -3081,7 +3074,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; @@ -3090,11 +3083,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()); } } } @@ -3104,7 +3097,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; @@ -3117,15 +3110,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; } @@ -3134,7 +3127,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; } } @@ -3143,10 +3136,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(); + GULPS_PRINTF_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); @@ -3201,14 +3194,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(); + { + GULPS_ERRORF(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; @@ -3216,9 +3214,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) @@ -3234,18 +3232,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(); + GULPS_ERRORF(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) { @@ -3258,12 +3256,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]; @@ -3277,7 +3275,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; @@ -3317,13 +3315,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; } @@ -3333,7 +3331,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 @@ -3342,7 +3340,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{}}; } } @@ -3372,14 +3370,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; } @@ -3390,18 +3387,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; } @@ -3429,31 +3426,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; } //---------------------------------------------------------------------------------------------------- @@ -3490,12 +3486,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; } @@ -3525,12 +3520,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; } @@ -3573,15 +3567,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()); + + GULPS_PRINTF_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; } @@ -3592,7 +3586,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; @@ -3612,18 +3606,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 @@ -3636,12 +3631,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; + GULPS_ERRORF(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; } //---------------------------------------------------------------------------------------------------- @@ -3661,7 +3658,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; } @@ -3671,7 +3668,7 @@ bool simple_wallet::close_wallet() } catch(const std::exception &e) { - fail_msg_writer() << e.what(); + GULPS_PRINT_FAIL(e.what()); return false; } @@ -3684,11 +3681,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; @@ -3698,7 +3695,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; } @@ -3706,7 +3703,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; } @@ -3714,11 +3711,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; @@ -3729,7 +3726,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; } @@ -3738,7 +3735,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); @@ -3771,9 +3768,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; } @@ -3781,9 +3777,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; } //---------------------------------------------------------------------------------------------------- @@ -3794,7 +3790,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; } @@ -3803,9 +3799,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; } //---------------------------------------------------------------------------------------------------- @@ -3815,7 +3811,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; } @@ -3826,7 +3822,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 @@ -3844,7 +3840,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; } @@ -3856,7 +3852,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; @@ -3864,9 +3860,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; } //---------------------------------------------------------------------------------------------------- @@ -3880,14 +3876,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 @@ -3901,7 +3897,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 @@ -3922,11 +3919,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; @@ -3944,9 +3938,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(); @@ -3961,33 +3953,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; @@ -4015,17 +4007,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:")); + GULPS_PRINTF_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) @@ -4033,7 +4025,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); + GULPS_PRINTF_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; } @@ -4042,7 +4035,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(); @@ -4054,7 +4047,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; @@ -4096,7 +4089,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; } @@ -4114,22 +4107,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")); + + GULPS_PRINTF_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); + } + + GULPS_PRINTF_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); } } @@ -4137,15 +4139,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")); } } @@ -4156,7 +4158,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; } @@ -4164,8 +4166,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"); + GULPS_PRINTF_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) @@ -4177,7 +4178,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; } @@ -4187,18 +4188,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; + GULPS_PRINTF_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); } } @@ -4227,9 +4228,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; } //---------------------------------------------------------------------------------------------------- @@ -4237,7 +4238,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; } @@ -4251,30 +4252,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; @@ -4285,7 +4286,7 @@ bool simple_wallet::print_ring_members(const std::vector spent_key_height(tx.vin.size()); std::vector spent_key_txid(tx.vin.size()); @@ -4319,12 +4320,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 @@ -4340,7 +4341,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; } } @@ -4384,12 +4385,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(); + GULPS_ERRORF(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) @@ -4466,12 +4466,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; @@ -4483,12 +4483,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(); @@ -4501,7 +4501,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; @@ -4511,7 +4511,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; } @@ -4536,7 +4536,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; } @@ -4600,12 +4600,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(); @@ -4616,7 +4616,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()) { @@ -4697,14 +4696,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()) @@ -4728,11 +4727,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 @@ -4746,8 +4745,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; } @@ -4807,7 +4806,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 @@ -4819,7 +4818,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(); + GULPS_ERRORF(tr("Error: ring size {} is too small, minimum is {}"), fake_outs_count + 1, adjusted_fake_outs_count + 1); return true; } @@ -4828,7 +4827,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; } @@ -4839,7 +4838,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; } @@ -4847,7 +4846,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; } @@ -4862,7 +4861,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; } @@ -4873,12 +4872,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; } @@ -4899,7 +4898,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"); } @@ -4907,23 +4906,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; } @@ -4934,11 +4930,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()) @@ -4946,11 +4942,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 @@ -4964,8 +4960,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; @@ -5010,7 +5006,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(); @@ -5018,21 +5014,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; } @@ -5040,7 +5036,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; } @@ -5055,7 +5051,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* @@ -5066,22 +5062,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; } @@ -5091,15 +5087,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; } @@ -5109,11 +5104,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()) @@ -5121,17 +5116,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) @@ -5140,8 +5135,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; @@ -5157,12 +5152,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())); @@ -5172,14 +5167,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; @@ -5199,7 +5194,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; } @@ -5254,12 +5249,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) @@ -5268,7 +5263,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; } } @@ -5287,7 +5282,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; @@ -5306,7 +5301,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"); @@ -5320,7 +5315,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); } //---------------------------------------------------------------------------------------------------- @@ -5328,7 +5323,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); } //---------------------------------------------------------------------------------------------------- @@ -5336,22 +5331,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()) @@ -5366,13 +5361,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; } @@ -5383,8 +5378,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; @@ -5394,7 +5388,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; } @@ -5403,7 +5397,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()) @@ -5415,7 +5409,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; } @@ -5427,8 +5421,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; @@ -5440,12 +5434,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()) @@ -5456,7 +5450,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; } @@ -5470,12 +5464,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; } } @@ -5484,26 +5478,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; } @@ -5517,13 +5511,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; } @@ -5534,7 +5528,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; } @@ -5543,13 +5537,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; } @@ -5557,7 +5551,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); @@ -5566,7 +5560,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); @@ -5575,7 +5569,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; } @@ -5588,31 +5582,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; + GULPS_PRINTF_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; } @@ -5621,7 +5615,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; } @@ -5632,7 +5626,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; } @@ -5640,7 +5634,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; } @@ -5648,7 +5642,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; } @@ -5659,39 +5653,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; + GULPS_PRINTF_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; } @@ -5700,31 +5694,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; } @@ -5738,13 +5732,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; } @@ -5753,40 +5747,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; } @@ -5795,18 +5789,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; } @@ -5817,14 +5811,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; } @@ -5840,13 +5834,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; } @@ -5855,32 +5849,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; } @@ -5891,16 +5885,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); + GULPS_PRINTF_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; } @@ -5926,25 +5920,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_; @@ -5959,7 +5934,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; } @@ -6017,7 +5992,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()); @@ -6032,7 +6007,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()); @@ -6053,7 +6028,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)))); } } @@ -6088,15 +6064,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; + GULPS_PRINTF_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) @@ -6116,12 +6093,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(); + GULPS_PRINTF_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()); } } @@ -6142,7 +6120,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(); + GULPS_PRINTF_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); } } } @@ -6154,7 +6134,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_; @@ -6173,7 +6153,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()); @@ -6181,14 +6161,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; } } @@ -6218,27 +6198,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; @@ -6277,9 +6258,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) @@ -6288,7 +6268,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; } //---------------------------------------------------------------------------------------------------- @@ -6297,7 +6277,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) @@ -6308,15 +6288,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; } @@ -6375,7 +6355,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(); }, ""); } //---------------------------------------------------------------------------------------------------- @@ -6430,12 +6410,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; @@ -6448,7 +6428,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()); @@ -6461,7 +6441,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) @@ -6473,7 +6453,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); @@ -6485,7 +6465,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) @@ -6496,7 +6476,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); @@ -6508,7 +6488,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) @@ -6527,19 +6507,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