From 0cafd79fd75cbc1dd6020ed548b8f7609cdd1db0 Mon Sep 17 00:00:00 2001 From: muscleman Date: Sat, 15 Jan 2022 11:48:32 -0600 Subject: [PATCH] fixed --- index.js | 6 + package.json | 7 +- src/common/boost_serialization_helper.h | 1 + src/common/command_line.h | 10 +- src/common/crypto_stream_operators.h | 6 +- src/common/db_backend_mdbx.cpp | 7 +- src/common/error_codes.h | 1 + src/common/general_purpose_commands_defs.h | 40 + src/common/pre_download.h | 13 +- src/contrib/epee/include/console_handler.h | 8 +- src/contrib/epee/include/misc_language.h | 2 + src/contrib/epee/include/misc_log_ex.h | 49 +- .../serialization/keyvalue_helper_structs.h | 40 + .../serialization/keyvalue_serialization.h | 2 +- .../keyvalue_serialization_overloads.h | 1 + .../include/storages/http_abstract_invoke.h | 21 +- .../epee/include/storages/portable_storage.h | 1 + src/contrib/epee/include/string_tools.h | 11 +- src/contrib/epee/include/time_helper.h | 2 +- src/crypto/crypto-sugar.h | 179 +++- src/crypto/range_proofs.cpp | 12 + src/crypto/range_proofs.h | 823 ++++++++++++++++++ src/currency_core/account.cpp | 3 +- src/currency_core/account.h | 15 +- src/currency_core/bc_block_datetime_service.h | 7 + src/currency_core/blockchain_storage.cpp | 81 +- src/currency_core/blockchain_storage.h | 52 +- src/currency_core/checkpoints.cpp | 27 +- src/currency_core/checkpoints.h | 2 + src/currency_core/checkpoints_create.h | 11 +- src/currency_core/currency_basic.h | 19 +- src/currency_core/currency_config.h | 12 +- src/currency_core/currency_format_utils.cpp | 186 +++- src/currency_core/currency_format_utils.h | 12 +- src/currency_core/offers_services_helpers.h | 8 +- .../currency_protocol_handler.inl | 3 +- src/main.cc | 101 ++- src/p2p/net_node.h | 6 +- src/p2p/net_node.inl | 102 ++- src/p2p/net_peerlist.h | 63 +- src/rpc/core_rpc_server.cpp | 25 +- src/rpc/core_rpc_server_commands_defs.h | 3 + 42 files changed, 1678 insertions(+), 302 deletions(-) create mode 100644 src/common/general_purpose_commands_defs.h create mode 100644 src/contrib/epee/include/serialization/keyvalue_helper_structs.h create mode 100644 src/crypto/range_proofs.cpp create mode 100644 src/crypto/range_proofs.h create mode 100644 src/currency_core/bc_block_datetime_service.h diff --git a/index.js b/index.js index df4a334..addf58b 100644 --- a/index.js +++ b/index.js @@ -1 +1,7 @@ module.exports = require('bindings')('cryptonote.node') + +const bignum = require('bignum'); + +module.exports.baseDiff = function() { + return bignum('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16); +}; \ No newline at end of file diff --git a/package.json b/package.json index 081e7e2..65dc666 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,10 @@ "type": "git", "url": "https://github.com/hyle-team/zano-node-util.git" }, - "dependencies" : { - "bindings" : "*", - "nan" : "^2.0.0" + "dependencies": { + "bindings": "*", + "nan": "^2.14.2", + "bignum": "^0.13.1" }, "keywords": [ "cryptonight", diff --git a/src/common/boost_serialization_helper.h b/src/common/boost_serialization_helper.h index 2ba8a52..5ad68a0 100644 --- a/src/common/boost_serialization_helper.h +++ b/src/common/boost_serialization_helper.h @@ -12,6 +12,7 @@ + #define CHECK_PROJECT_NAME() std::string project_name = CURRENCY_NAME; ar & project_name; if(!(project_name == CURRENCY_NAME) ) {throw std::runtime_error(std::string("wrong storage file: project name in file: ") + project_name + ", expected: " + CURRENCY_NAME );} diff --git a/src/common/command_line.h b/src/common/command_line.h index f19a04a..ee7985c 100644 --- a/src/common/command_line.h +++ b/src/common/command_line.h @@ -151,7 +151,7 @@ namespace command_line } template - bool handle_error_helper(const boost::program_options::options_description& desc, F parser) + bool handle_error_helper(const boost::program_options::options_description& desc, std::string& err, F parser) { try { @@ -159,6 +159,7 @@ namespace command_line } catch (std::exception& e) { + err = e.what(); std::cerr << "Failed to parse arguments: " << e.what() << std::endl; std::cerr << desc << std::endl; return false; @@ -171,6 +172,13 @@ namespace command_line } } + template + bool handle_error_helper(const boost::program_options::options_description& desc, F parser) + { + std::string stub_err; + return handle_error_helper(desc, stub_err, parser); + } + template bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor& arg) { diff --git a/src/common/crypto_stream_operators.h b/src/common/crypto_stream_operators.h index 0201603..fa2531d 100644 --- a/src/common/crypto_stream_operators.h +++ b/src/common/crypto_stream_operators.h @@ -15,20 +15,20 @@ bool parse_hash256(const std::string str_hash, crypto::hash& hash); template std::ostream &print_t(std::ostream &o, const T &v) { - return o << "<" << epee::string_tools::pod_to_hex(v) << ">"; + return o << "" << epee::string_tools::pod_to_hex(v) << ""; } template std::ostream &print16(std::ostream &o, const T &v) { - return o << "<" << epee::string_tools::pod_to_hex(v).substr(0, 5) << "..>"; + return o << "" << epee::string_tools::pod_to_hex(v).substr(0, 5) << ".."; } template std::string print16(const T &v) { - return std::string("<") + epee::string_tools::pod_to_hex(v).substr(0, 5) + "..>"; + return std::string("") + epee::string_tools::pod_to_hex(v).substr(0, 5) + ".."; } diff --git a/src/common/db_backend_mdbx.cpp b/src/common/db_backend_mdbx.cpp index 09670a8..3307dec 100644 --- a/src/common/db_backend_mdbx.cpp +++ b/src/common/db_backend_mdbx.cpp @@ -143,9 +143,10 @@ namespace tools else { int res = 0; + //MDBX_txn_flags_t flags = MDBX_txn_flags_t(); unsigned int flags = 0; if (read_only) - flags += MDBX_RDONLY; + flags = MDBX_RDONLY;//flags = MDBX_TXN_RDONLY; //don't use parent tx in write transactions if parent tx was read-only (restriction in mdbx) //see "Nested transactions: Max 1 child, write txns only, no writemap" @@ -340,7 +341,9 @@ namespace tools data[0].iov_base = (void*)v; data[0].iov_len = vs; - res = mdbx_put(get_current_tx(), static_cast(h), &key, data, 0); + //MDBX_put_flags_t flags = MDBX_put_flags_t(); + unsigned flags = 0; + res = mdbx_put(get_current_tx(), static_cast(h), &key, data, flags); CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put"); return true; } diff --git a/src/common/error_codes.h b/src/common/error_codes.h index 648bd6f..7b77fec 100644 --- a/src/common/error_codes.h +++ b/src/common/error_codes.h @@ -40,3 +40,4 @@ #define API_RETURN_CODE_TX_IS_TOO_BIG "TX_IS_TOO_BIG" #define API_RETURN_CODE_TX_REJECTED "TX_REJECTED" #define API_RETURN_CODE_HTLC_ORIGIN_HASH_MISSMATCHED "HTLC_ORIGIN_HASH_MISSMATCHED" +#define API_RETURN_CODE_WRAP "WRAP" \ No newline at end of file diff --git a/src/common/general_purpose_commands_defs.h b/src/common/general_purpose_commands_defs.h new file mode 100644 index 0000000..f9da996 --- /dev/null +++ b/src/common/general_purpose_commands_defs.h @@ -0,0 +1,40 @@ +// Copyright (c) 2014-2018 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#pragma once +#include "serialization/keyvalue_hexemizer.h" +#include "currency_core/currency_basic.h" +#include "storages/portable_storage_base.h" +#include "currency_core/basic_api_response_codes.h" +#include "common/error_codes.h" +namespace currency +{ + //----------------------------------------------- + + + struct tx_cost_struct + { + std::string usd_needed_for_erc20; + std::string zano_needed_for_erc20; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(usd_needed_for_erc20) + KV_SERIALIZE(zano_needed_for_erc20) + END_KV_SERIALIZE_MAP() + }; + + struct rpc_get_wrap_info_response + { + std::string unwraped_coins_left; + tx_cost_struct tx_cost; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(unwraped_coins_left) + KV_SERIALIZE(tx_cost) + END_KV_SERIALIZE_MAP() + }; + + +} + diff --git a/src/common/pre_download.h b/src/common/pre_download.h index 6ea723b..5feec36 100644 --- a/src/common/pre_download.h +++ b/src/common/pre_download.h @@ -21,8 +21,8 @@ namespace tools }; #ifndef TESTNET - static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_95_1000000.pak", "6b0bbba85bc420eaae5ec68373e528f70bffaa17fb111c796e951d06ad71e4fe", 1104150892, 2147450880 }; - static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_95_1000000.pak", "b4d45c727dbf1b92671f9fd1a9624e79019e890bd3d33cb71e011ab4bcb0d21e", 1450748151, 2114449408 }; + static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.42.247/pre-download/zano_mdbx_95_1161000.pak", "26660ffcdaf80a43a586e64a1a6da042dcb9ff3b58e14ce1ec9a775b995dc146", 1330022593, 2684313600 }; + static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.42.247/pre-download/zano_lmdb_95_1161000.pak", "9dd03f08dea396fe32e6483a8221b292be35fa41c29748f119f11c3275956cdc", 1787475468, 2600247296 }; #else static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 }; static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 }; @@ -50,7 +50,8 @@ namespace tools boost::system::error_code ec; uint64_t sz = boost::filesystem::file_size(db_main_file_path, ec); - if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || command_line::has_arg(vm, command_line::arg_force_predownload)) ) + bool flag_force_predownload = command_line::has_arg(vm, command_line::arg_force_predownload); + if (pre_download.unpacked_size == 0 || !(ec || (pre_download.unpacked_size > sz && pre_download.unpacked_size - sz > pre_download_min_size_difference) || flag_force_predownload) ) { LOG_PRINT_MAGENTA("Pre-downloading not needed (db file size = " << sz << ")", LOG_LEVEL_0); return true; @@ -92,15 +93,15 @@ namespace tools r = cl.download_and_unzip(cb, downloading_file_path, url, 5000 /* timout */, "GET", std::string(), 30 /* fails count */); if (!r) { - LOG_PRINT_RED("Download failed", LOG_LEVEL_0); - return false; + LOG_PRINT_RED("Downloading failed", LOG_LEVEL_0); + return !flag_force_predownload; // fatal error only if force-predownload } crypto::hash data_hash = hash_stream.calculate_hash(); if (epee::string_tools::pod_to_hex(data_hash) != pre_download.hash) { LOG_ERROR("hash missmatch in downloaded file, got: " << epee::string_tools::pod_to_hex(data_hash) << ", expected: " << pre_download.hash); - return false; + return !flag_force_predownload; // fatal error only if force-predownload } LOG_PRINT_GREEN("Download succeeded, hash " << pre_download.hash << " is correct" , LOG_LEVEL_0); diff --git a/src/contrib/epee/include/console_handler.h b/src/contrib/epee/include/console_handler.h index 4887c7c..2d098e3 100644 --- a/src/contrib/epee/include/console_handler.h +++ b/src/contrib/epee/include/console_handler.h @@ -376,7 +376,7 @@ namespace epee bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, const std::string& prompt, const std::string& usage = "") { async_console_handler console_handler; - return console_handler.run(ptsrv, boost::bind(no_srv_param_adapter, _1, _2, handlr), prompt, usage); + return console_handler.run(ptsrv, boost::bind(no_srv_param_adapter, boost::placeholders::_1, boost::placeholders::_2, handlr), prompt, usage); } template @@ -460,7 +460,7 @@ namespace epee /*template bool start_handling(t_srv& srv, const std::string& usage_string = "") { - start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, _1)); + start_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1)); return true; }*/ @@ -489,7 +489,7 @@ namespace epee /*template bool run_handling(t_srv& srv, const std::string& usage_string) { - return run_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, _1), usage_string); + return run_default_console_handler_no_srv_param(&srv, boost::bind(&console_handlers_binder::process_command_str, this, boost::placeholders::_1), usage_string); }*/ }; @@ -510,7 +510,7 @@ namespace epee bool run_handling(t_server* psrv, const std::string& prompt, const std::string& usage_string) { - return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, _1, _2), prompt, usage_string); + return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder::process_command_str, this, boost::placeholders::_1, boost::placeholders::_2), prompt, usage_string); } void stop_handling() diff --git a/src/contrib/epee/include/misc_language.h b/src/contrib/epee/include/misc_language.h index 1a02c7c..276dfe0 100644 --- a/src/contrib/epee/include/misc_language.h +++ b/src/contrib/epee/include/misc_language.h @@ -65,6 +65,8 @@ namespace epee } +#define STD_TRY_CATCH_LOCATION(return_val) STD_TRY_CATCH(LOCATION_SS, return_val) + /* helper class, to make able get namespace via decltype()::*/ template class namespace_accessor: public base_class{}; diff --git a/src/contrib/epee/include/misc_log_ex.h b/src/contrib/epee/include/misc_log_ex.h index e0a5861..0b957a5 100644 --- a/src/contrib/epee/include/misc_log_ex.h +++ b/src/contrib/epee/include/misc_log_ex.h @@ -132,17 +132,21 @@ DISABLE_VS_WARNINGS(4100) #define LOG_PRINT_CHANNEL_NO_POSTFIX2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x; epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}} -#define LOG_PRINT_CHANNEL2(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);CATCH_ALL_DO_NOTHING();}} +#define LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ + {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, false, log_name);cb(ss________.str());CATCH_ALL_DO_NOTHING();}} -#define LOG_PRINT_CHANNEL_COLOR2(log_channel, log_name, x, y, color) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ - {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name);CATCH_ALL_DO_NOTHING();}} +#define LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, cb) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ + {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, color, false, log_name); cb(ss________.str());CATCH_ALL_DO_NOTHING();}} #define LOG_PRINT_CHANNEL_2_JORNAL(log_channel, log_name, x, y) {if ( y <= epee::log_space::log_singletone::get_log_detalisation_level() && epee::log_space::log_singletone::channel_enabled(log_channel))\ {TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << x << std::endl;epee::log_space::log_singletone::do_log_message(ss________.str(), y, epee::log_space::console_color_default, true, log_name);CATCH_ALL_DO_NOTHING();}} -#define LOG_ERROR2(log_name, x) { \ - TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "[ERROR] Location: " << std::endl << LOCATION_SS << epee::misc_utils::get_callstack() << " Message:" << std::endl << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name); LOCAL_ASSERT(0); epee::log_space::increase_error_count(LOG_DEFAULT_CHANNEL);CATCH_ALL_DO_NOTHING();} +#define LOG_ERROR2_CB(log_name, x, cb) { \ + TRY_ENTRY();std::stringstream ss________; ss________ << epee::log_space::log_singletone::get_prefix_entry() << "[ERROR] Location: " << std::endl << LOCATION_SS << epee::misc_utils::get_callstack() << " Message:" << std::endl << x << std::endl; epee::log_space::log_singletone::do_log_message(ss________.str(), LOG_LEVEL_0, epee::log_space::console_color_red, true, log_name); LOCAL_ASSERT(0); epee::log_space::increase_error_count(LOG_DEFAULT_CHANNEL); cb(ss________.str()); CATCH_ALL_DO_NOTHING();} + +#define LOG_ERROR2(log_name, x) LOG_ERROR2_CB(log_name, x, epee::log_space::log_stub) +#define LOG_PRINT_CHANNEL2(log_channel, log_name, x, y) LOG_PRINT_CHANNEL2_CB(log_channel, log_name, x, y, epee::log_space::log_stub) +#define LOG_PRINT_CHANNEL_COLOR2(log_channel, log_name, x, y, color) LOG_PRINT_CHANNEL_COLOR2_CB(log_channel, log_name, x, y, color, epee::log_space::log_stub) #define LOG_FRAME2(log_name, x, y) epee::log_space::log_frame frame(x, y, log_name) @@ -163,7 +167,9 @@ DISABLE_VS_WARNINGS(4100) #define LOG_PRINT_NO_PREFIX_NO_POSTFIX2(log_name, x, y) LOG_PRINT_CHANNEL_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_CHANNEL, log_name, x, y) #define LOG_PRINT_NO_POSTFIX2(log_name, x, y) LOG_PRINT_CHANNEL_NO_POSTFIX2(LOG_DEFAULT_CHANNEL, log_name, x, y) #define LOG_PRINT2(log_name, x, y) LOG_PRINT_CHANNEL2(LOG_DEFAULT_CHANNEL, log_name, x, y) +#define LOG_PRINT2_CB(log_name, x, y, cb) LOG_PRINT_CHANNEL2_CB(LOG_DEFAULT_CHANNEL, log_name, x, y, cb) #define LOG_PRINT_COLOR2(log_name, x, y, color) LOG_PRINT_CHANNEL_COLOR2(LOG_DEFAULT_CHANNEL, log_name, x, y, color) +#define LOG_PRINT_COLOR2_CB(log_name, x, y, color, cb) LOG_PRINT_CHANNEL_COLOR2_CB(LOG_DEFAULT_CHANNEL, log_name, x, y, color, cb) #define LOG_PRINT2_JORNAL(log_name, x, y) LOG_PRINT_CHANNEL_2_JORNAL(LOG_DEFAULT_CHANNEL, log_name, x, y) #ifndef LOG_DEFAULT_TARGET @@ -173,17 +179,28 @@ DISABLE_VS_WARNINGS(4100) #define LOG_PRINT_NO_POSTFIX(mess, level) LOG_PRINT_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) #define LOG_PRINT_NO_PREFIX(mess, level) LOG_PRINT_NO_PREFIX2(LOG_DEFAULT_TARGET, mess, level) #define LOG_PRINT_NO_PREFIX_NO_POSTFIX(mess, level) LOG_PRINT_NO_PREFIX_NO_POSTFIX2(LOG_DEFAULT_TARGET, mess, level) -#define LOG_PRINT(mess, level) LOG_PRINT2(LOG_DEFAULT_TARGET, mess, level) +#define LOG_PRINT(mess, level) LOG_PRINT2(LOG_DEFAULT_TARGET, mess, level) +#define LOG_PRINT_CB(mess, level, cb) LOG_PRINT2_CB(LOG_DEFAULT_TARGET, mess, level, cb) +#define LOG_PRINT_COLOR_CB(mess, level, color, cb) LOG_PRINT_COLOR2_CB(LOG_DEFAULT_TARGET, mess, level, color, cb) + +#define LOG_COLOR_RED epee::log_space::console_color_red +#define LOG_COLOR_GREEN epee::log_space::console_color_green +#define LOG_COLOR_BLUE epee::log_space::console_color_blue +#define LOG_COLOR_YELLOW epee::log_space::console_color_yellow +#define LOG_COLOR_CYAN epee::log_space::console_color_cyan +#define LOG_COLOR_MAGENTA epee::log_space::console_color_magenta + #define LOG_PRINT_COLOR(mess, level, color) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, color) -#define LOG_PRINT_RED(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_red) -#define LOG_PRINT_GREEN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_green) -#define LOG_PRINT_BLUE(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_blue) -#define LOG_PRINT_YELLOW(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_yellow) -#define LOG_PRINT_CYAN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_cyan) -#define LOG_PRINT_MAGENTA(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, epee::log_space::console_color_magenta) +#define LOG_PRINT_RED(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_RED) +#define LOG_PRINT_GREEN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_GREEN) +#define LOG_PRINT_BLUE(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_BLUE) +#define LOG_PRINT_YELLOW(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_YELLOW) +#define LOG_PRINT_CYAN(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_CYAN) +#define LOG_PRINT_MAGENTA(mess, level) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, level, LOG_COLOR_MAGENTA) -#define LOG_PRINT_RED_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_red) +#define LOG_PRINT_RED_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_red) +#define LOG_PRINT_GREEN_L0(mess) LOG_PRINT_COLOR2(LOG_DEFAULT_TARGET, mess, LOG_LEVEL_0, epee::log_space::console_color_green) #define LOG_PRINT_L0(mess) LOG_PRINT(mess, LOG_LEVEL_0) #define LOG_PRINT_L1(mess) LOG_PRINT(mess, LOG_LEVEL_1) @@ -193,6 +210,7 @@ DISABLE_VS_WARNINGS(4100) #define LOG_PRINT_J(mess, level) LOG_PRINT2_JORNAL(LOG_DEFAULT_TARGET, mess, level) #define LOG_ERROR(mess) LOG_ERROR2(LOG_DEFAULT_TARGET, mess) +#define LOG_ERROR_CB(mess, cb) LOG_ERROR2_CB(LOG_DEFAULT_TARGET, mess, cb) #define LOG_FRAME(mess, level) LOG_FRAME2(LOG_DEFAULT_TARGET, mess, level) #define LOG_VALUE(mess, level) LOG_VALUE2(LOG_DEFAULT_TARGET, mess, level) #define LOG_ARRAY(mess, level) LOG_ARRAY2(LOG_DEFAULT_TARGET, mess, level) @@ -333,7 +351,8 @@ namespace log_space /* */ /************************************************************************/ #define CONSOLE_DEFAULT_STREAM std::cout - + + inline void log_stub(const std::string& /**/) {} struct delete_ptr { diff --git a/src/contrib/epee/include/serialization/keyvalue_helper_structs.h b/src/contrib/epee/include/serialization/keyvalue_helper_structs.h new file mode 100644 index 0000000..e0e3f16 --- /dev/null +++ b/src/contrib/epee/include/serialization/keyvalue_helper_structs.h @@ -0,0 +1,40 @@ +// Copyright (c) 2006-2021, 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. +// + +#pragma once + +namespace epee +{ + + template + struct kvserializable_pair : public std::pair<_Ty1, _Ty2> + { + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(first) + KV_SERIALIZE(second) + END_KV_SERIALIZE_MAP() + }; +} \ No newline at end of file diff --git a/src/contrib/epee/include/serialization/keyvalue_serialization.h b/src/contrib/epee/include/serialization/keyvalue_serialization.h index 31a4fb8..31c90df 100644 --- a/src/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/src/contrib/epee/include/serialization/keyvalue_serialization.h @@ -115,7 +115,7 @@ public: \ template inline static bool get_value_of_flag_by_mask(const t_uint& given_flags) { - return given_flags&mask == 0 ? false : true; + return (given_flags&mask) == 0 ? false : true; } }; diff --git a/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 05c235d..01f9e25 100644 --- a/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/src/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -26,6 +26,7 @@ #pragma once +#include #include namespace epee diff --git a/src/contrib/epee/include/storages/http_abstract_invoke.h b/src/contrib/epee/include/storages/http_abstract_invoke.h index 5305c54..0b6ef8e 100644 --- a/src/contrib/epee/include/storages/http_abstract_invoke.h +++ b/src/contrib/epee/include/storages/http_abstract_invoke.h @@ -94,9 +94,28 @@ namespace epee return serialization::load_t_from_binary(result_struct, pri->m_body); } + + template + bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, epee::json_rpc::error& err, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") + { + epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); + req_t.jsonrpc = "2.0"; + req_t.id = req_id; + req_t.method = method_name; + req_t.params = out_struct; + epee::json_rpc::response resp_t = AUTO_VAL_INIT(resp_t); + if (!epee::net_utils::invoke_http_json_remote_command2(url, req_t, resp_t, transport, timeout, http_method)) + { + return false; + } + err = resp_t.error; + result_struct = resp_t.result; + return true; + } + template bool invoke_http_json_rpc(const std::string& url, const std::string& method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, unsigned int timeout = 5000, const std::string& http_method = "GET", const std::string& req_id = "0") - { + { epee::json_rpc::request req_t = AUTO_VAL_INIT(req_t); req_t.jsonrpc = "2.0"; req_t.id = req_id; diff --git a/src/contrib/epee/include/storages/portable_storage.h b/src/contrib/epee/include/storages/portable_storage.h index 92fbeec..4d36cc0 100644 --- a/src/contrib/epee/include/storages/portable_storage.h +++ b/src/contrib/epee/include/storages/portable_storage.h @@ -28,6 +28,7 @@ #pragma once +#include #include "misc_language.h" #include "portable_storage_base.h" #include "portable_storage_to_bin.h" diff --git a/src/contrib/epee/include/string_tools.h b/src/contrib/epee/include/string_tools.h index a4e67f4..95a5d88 100644 --- a/src/contrib/epee/include/string_tools.h +++ b/src/contrib/epee/include/string_tools.h @@ -284,12 +284,19 @@ POP_GCC_WARNINGS typedef std::map command_line_params_w; template - void apped_pod_to_strbuff(std::string& buff, const t_pod_data& pod) + void append_pod_to_strbuff(std::string& buff, const t_pod_data& pod) { buff.append(reinterpret_cast(&pod), sizeof(pod)); } - + template + bool get_pod_from_strbuff(const std::string& buff, pod_t& output) + { + if (buff.size() != sizeof(pod_t)) + return false; + output = *reinterpret_cast(buff.data()); + return true; + } template bool parse_commandline(std::map& res, int argc, char** argv) diff --git a/src/contrib/epee/include/time_helper.h b/src/contrib/epee/include/time_helper.h index f11dae9..4081142 100644 --- a/src/contrib/epee/include/time_helper.h +++ b/src/contrib/epee/include/time_helper.h @@ -87,7 +87,7 @@ DISABLE_VS_WARNINGS(4996) POP_VS_WARNINGS if(pt) - strftime( tmpbuf, 199, "%Y_%m_%d %H_%M_%S", pt ); + strftime( tmpbuf, 199, "%Y-%m-%d %H-%M-%S", pt ); else { std::stringstream strs; diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 43e69c4..600fe91 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -315,6 +315,13 @@ namespace crypto return *this; } + // returns this = a * b + scalar_t& assign_mul(const scalar_t& a, const scalar_t& b) + { + sc_mul(m_s, a.m_s, b.m_s); + return *this; + } + /* I think it has bad symantic (operator-like), consider rename/reimplement -- sowle */ @@ -426,6 +433,17 @@ namespace crypto }; // struct scalar_t + // + // Global constants + // + + extern const scalar_t c_scalar_1; + extern const scalar_t c_scalar_L; + extern const scalar_t c_scalar_Lm1; + extern const scalar_t c_scalar_P; + extern const scalar_t c_scalar_Pm1; + extern const scalar_t c_scalar_256m1; + extern const scalar_t c_scalar_1div8; // // @@ -479,6 +497,7 @@ namespace crypto zero(); } + // as we're using additive notation, zero means identity group element here and after void zero() { ge_p3_0(&m_p3); @@ -490,6 +509,11 @@ namespace crypto return fe_isnonzero(m_p3.X) * fe_cmp(m_p3.Y, m_p3.Z) == 0; } + bool is_in_main_subgroup() const + { + return (c_scalar_L * *this).is_zero(); + } + bool from_public_key(const crypto::public_key& pk) { return ge_frombytes_vartime(&m_p3, reinterpret_cast(&pk)) == 0; @@ -710,19 +734,151 @@ namespace crypto }; // struct point_g_t + // + // vector of scalars + // + struct scalar_vec_t : public std::vector + { + typedef std::vector super_t; + + scalar_vec_t() {} + scalar_vec_t(size_t n) : super_t(n) {} + scalar_vec_t(std::initializer_list init_list) : super_t(init_list) {} + + bool is_reduced() const + { + for (auto& el : *this) + if (!el.is_reduced()) + return false; + return true; + } + + // add a scalar rhs to each element + scalar_vec_t operator+(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) + rhs; + return result; + } + + // subtract a scalar rhs to each element + scalar_vec_t operator-(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) - rhs; + return result; + } + + // multiply each element of the vector by a scalar + scalar_vec_t operator*(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) * rhs; + return result; + } + + // component-wise multiplication (a.k.a the Hadamard product) (only if their sizes match) + scalar_vec_t operator*(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) * rhs[i]; + return result; + } + + // add each element of two vectors, but only if their sizes match + scalar_vec_t operator+(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) + rhs[i]; + return result; + } + + // zeroes all elements + void zero() + { + size_t size_bytes = sizeof(scalar_t) * size(); + memset(data(), 0, size_bytes); + } + + // invert all elements in-place efficiently: 4*N muptiplications + 1 inversion + void invert() + { + // muls muls_rev + // 0: 1 2 3 .. n-1 + // 1: 0 2 3 .. n-1 + // 2: 0 1 3 .. n-1 + // + // n-1: 0 1 2 3 .. n-2 + + const size_t size = this->size(); + + if (size < 2) + { + if (size == 1) + at(0) = at(0).reciprocal(); + return; + } + + scalar_vec_t muls(size), muls_rev(size); + muls[0] = 1; + for (size_t i = 0; i < size - 1; ++i) + muls[i + 1] = at(i) * muls[i]; + + muls_rev[size - 1] = 1; + for (size_t i = size - 1; i != 0; --i) + muls_rev[i - 1] = at(i) * muls_rev[i]; + + scalar_t inv = (muls[size - 1] * at(size - 1)).reciprocal(); + + for (size_t i = 0; i < size; ++i) + at(i) = muls[i] * inv * muls_rev[i]; + } + + scalar_t calc_hs() const; + + }; // scalar_vec_t + + + // treats vector of scalars as an M x N matrix just for convenience + template + struct scalar_mat_t : public scalar_vec_t + { + typedef scalar_vec_t super_t; + static_assert(N > 0, "invalid N value"); + + scalar_mat_t() {} + scalar_mat_t(size_t n) : super_t(n) {} + scalar_mat_t(std::initializer_list init_list) : super_t(init_list) {} + + // matrix accessor M rows x N cols + scalar_t& operator()(size_t row, size_t col) + { + return at(row * N + col); + } + }; // scalar_mat_t + + + // // Global constants // extern const point_g_t c_point_G; - - extern const scalar_t c_scalar_1; - extern const scalar_t c_scalar_L; - extern const scalar_t c_scalar_Lm1; - extern const scalar_t c_scalar_P; - extern const scalar_t c_scalar_Pm1; - extern const scalar_t c_scalar_256m1; - extern const scalar_t c_scalar_1div8; extern const point_t c_point_H; extern const point_t c_point_0; @@ -901,4 +1057,11 @@ namespace crypto }; // hash_helper_t struct + inline scalar_t scalar_vec_t::calc_hs() const + { + // hs won't touch memory if size is 0, so it's safe + return hash_helper_t::hs(data(), sizeof(scalar_t) * size()); + } + + } // namespace crypto diff --git a/src/crypto/range_proofs.cpp b/src/crypto/range_proofs.cpp new file mode 100644 index 0000000..b6750a0 --- /dev/null +++ b/src/crypto/range_proofs.cpp @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Zano Project (https://zano.org/) +// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "range_proofs.h" + +namespace crypto +{ + const point_t& bpp_crypto_trait_zano::bpp_H = c_point_H; + + +} diff --git a/src/crypto/range_proofs.h b/src/crypto/range_proofs.h new file mode 100644 index 0000000..b3d04d6 --- /dev/null +++ b/src/crypto/range_proofs.h @@ -0,0 +1,823 @@ +// Copyright (c) 2021 Zano Project (https://zano.org/) +// Copyright (c) 2021 sowle (val@zano.org, crypto.sowle@gmail.com) +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735.pdf +// + +#include "epee/include/misc_log_ex.h" +#include "crypto-sugar.h" + +namespace crypto +{ + + // returns x + x^2 + x^3 + ... + x^(2^f) + // == x * (x + 1) * (x^2 + 1) * (x^4 + 1) * ...(x^(f+1) + 1) + inline scalar_t sum_of_powers(scalar_t x, size_t f) + { + scalar_t result = x; + for (size_t i = 0; i < f; ++i) + { + result.assign_muladd(result, x, result); + x *= x; + } + return result; + } + + constexpr size_t c_bpp_log2_n = 6; + constexpr size_t c_bpp_n = 64; // 2^64 is the upper bound for the witness's range + constexpr size_t c_bpp_values_max = 16; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs + constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; + + // returns smallest k, s.t. v <= 2**k + inline size_t calc_exp_power_of_2_upper_bound(size_t v) + { + constexpr size_t max_v = (SIZE_MAX >> 1) + 1; + //if (v > max_v) + // return 0; + + size_t pow = 1, result = 0; + while (v > pow) + { + pow <<= 1; + ++result; + } + return result; + } + + // returns least significant bit uing de Bruijn sequence + // http://graphics.stanford.edu/~seander/bithacks.html + inline uint8_t calc_lsb_32(uint32_t v) + { + static const uint8_t multiply_de_bruijn_bit_position[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27]; + } + + + //////////////////////////////////////// + // crypto trait for Zano + //////////////////////////////////////// + struct bpp_crypto_trait_zano + { + static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment) + { + commitment = value * c_point_G + mask * c_point_H; + } + + static const scalar_t& get_initial_transcript() + { + static scalar_t value = hash_helper_t::hs("Zano BP+ initial transcript"); + return value; + } + + // assumes hsc is cleared + static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector& points) + { + hsc.add_scalar(e); + hsc.add_points_array(points); + e = hsc.calc_hash(); + } + + static const point_t& get_generator(bool select_H, size_t index) + { + if (index >= c_bpp_mn_max) + return c_point_0; // out of bound + + static std::vector generators(2 * c_bpp_mn_max); + static bool calculated = false; + if (!calculated) + { + scalar_t hash_buf[2] = { hash_helper_t::hs("Zano BP+ generator"), 0 }; + for (size_t i = 0; i < 2 * c_bpp_mn_max; ++i) + { + hash_buf[1].m_u64[0] = i; + ge_bytes_hash_to_ec(&generators[i].m_p3, &hash_buf, sizeof hash_buf); + } + calculated = true; + } + + return generators[2 * index + (select_H ? 1 : 0)]; + } + + static const point_t& bpp_H; + }; + + + struct bpp_signature + { + std::vector L; // size = log_2(m * n) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta; + }; + +#define DBG_VAL_PRINT(x) std::cout << #x ": " << x << ENDL +#define DBG_PRINT(x) std::cout << x << ENDL + + template + bool bpp_gen(const std::vector& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= c_bpp_values_max && values.size() == masks.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); + + const size_t c_bpp_log2_m = calc_exp_power_of_2_upper_bound(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + c_bpp_log2_n; + + // pre-multiply all output points by c_scalar_1div8 + // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) + + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + commitments.resize(values.size()); + for (size_t i = 0; i < values.size(); ++i) + CT::calc_pedersen_commitment(scalar_t(values[i]) * c_scalar_1div8, masks[i] * c_scalar_1div8, commitments[i]); + + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + uint64_t v = values[i]; + for (size_t j = 0; j < c_bpp_n; ++j) + { + if (v & 1) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + v >>= 1; + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments); + + // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) + // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha = scalar_t::random(); + point_t A0 = alpha * CT::bpp_H; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // part of 1/8 defense scheme + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements is stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aL_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat = 0; + for (size_t i = 0; i < masks.size(); ++i) + alpha_hat += d(i, 0) * masks[i]; + alpha_hat = alpha + y_mn_p1 * alpha_hat; + + DBG_VAL_PRINT(alpha_hat); + + // calculate y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, P, a, b, alpha) + + scalar_t dL = scalar_t::random(); + DBG_VAL_PRINT(dL); + scalar_t dR = scalar_t::random(); + DBG_VAL_PRINT(dR); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment(cL, dL, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment(cR, dR, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar + alpha_hat += e_squared * dL + e_inverse_squared * dR; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta = scalar_t::random(); + scalar_t eta = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta); + DBG_VAL_PRINT(eta); + + // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta * H + point_t B = c_point_0; + CT::calc_pedersen_commitment(r * y * s, eta, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta = eta + e * delta + e * e * alpha_hat; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta); + + return true; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } // bpp_gen() + + + // efficient multiexponentiation (naive stub implementation atm, TODO) + template + bool multiexp_and_check_being_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) + { + CHECK_AND_ASSERT_MES(g_scalars.size() < c_bpp_mn_max, false, "g_scalars oversized"); + CHECK_AND_ASSERT_MES(h_scalars.size() < c_bpp_mn_max, false, "h_scalars oversized"); + + point_t result = summand; + + for (size_t i = 0; i < g_scalars.size(); ++i) + result += g_scalars[i] * CT::get_generator(false, i); + + for (size_t i = 0; i < h_scalars.size(); ++i) + result += h_scalars[i] * CT::get_generator(true, i); + + if (!result.is_zero()) + { + LOG_PRINT_L0("multiexp result is non zero: " << result); + return false; + } + return true; + } + + + struct bpp_sig_commit_ref_t + { + bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bpp_signature& sig; + const std::vector& commitments; + }; + + + template + bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); + + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = calc_exp_power_of_2_upper_bound(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from page 13, Fig 1: + // Verifier outputs Accept IFF the following equality holds (single proof): + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta' is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from page 18, Fig 3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta' * H | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + static const scalar_t c_scalar_2_power_n_minus_1 = { 0xffffffffffffffff, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; + const scalar_t sum_d = c_scalar_2_power_n_minus_1 * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta + H_scalar += rwf * sig.delta; + DBG_PRINT("H_scalar: " << H_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); + bool result = multiexp_and_check_being_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +} // namespace crypto diff --git a/src/currency_core/account.cpp b/src/currency_core/account.cpp index 97d9480..def2025 100644 --- a/src/currency_core/account.cpp +++ b/src/currency_core/account.cpp @@ -70,8 +70,7 @@ namespace currency iv = *((crypto::chacha8_iv*)&pass_hash); crypto::chacha8(scr_data, src_length, key, iv, (char*)dst_data); } - - + //----------------------------------------------------------------- std::string account_base::get_seed_phrase(const std::string& password) const { if (m_keys_seed_binary.empty()) diff --git a/src/currency_core/account.h b/src/currency_core/account.h index 305b02e..37a0c95 100644 --- a/src/currency_core/account.h +++ b/src/currency_core/account.h @@ -16,13 +16,15 @@ #define SEED_PHRASE_V2_WORDS_COUNT 26 +#ifndef FORCE_HEADER_ONLY + #define KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, val_name) \ + KV_SERIALIZE_CUSTOM_N(varialble, std::string, currency::transform_addr_to_str, currency::transform_str_to_addr, val_name) -#define KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, val_name) \ - KV_SERIALIZE_CUSTOM_N(varialble, std::string, currency::transform_addr_to_str, currency::transform_str_to_addr, val_name) - -#define KV_SERIALIZE_ADDRESS_AS_TEXT(varialble) KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, #varialble) - - + #define KV_SERIALIZE_ADDRESS_AS_TEXT(varialble) KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, #varialble) +#else + #define KV_SERIALIZE_ADDRESS_AS_TEXT_N(varialble, val_name) + #define KV_SERIALIZE_ADDRESS_AS_TEXT(varialble) +#endif namespace currency { @@ -97,6 +99,7 @@ namespace currency std::vector m_keys_seed_binary; }; + const static account_keys null_acc_keys = AUTO_VAL_INIT(null_acc_keys); std::string transform_addr_to_str(const account_public_address& addr); account_public_address transform_str_to_addr(const std::string& str); diff --git a/src/currency_core/bc_block_datetime_service.h b/src/currency_core/bc_block_datetime_service.h new file mode 100644 index 0000000..4db3d74 --- /dev/null +++ b/src/currency_core/bc_block_datetime_service.h @@ -0,0 +1,7 @@ +// Copyright (c) 2014-2021 Zano Project +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +#pragma once + +#define BC_BLOCK_DATETIME_SERVICE_ID "d" +#define BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT "" diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index e60e5b6..6bb4771 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -578,13 +578,13 @@ bool blockchain_storage::set_checkpoints(checkpoints&& chk_pts) catch (const std::exception& ex) { m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK: " << ex.what()); + LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS: " << ex.what()); return false; } catch (...) { m_db.abort_transaction(); - LOG_ERROR("UNKNOWN EXCEPTION WHILE ADDINIG NEW BLOCK."); + LOG_ERROR("UNKNOWN EXCEPTION WHILE SETTING CHECKPOINTS."); return false; } @@ -594,7 +594,7 @@ bool blockchain_storage::prune_ring_signatures_and_attachments(uint64_t height, { CRITICAL_REGION_LOCAL(m_read_lock); - CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() " << m_db_blocks.size()); + CHECK_AND_ASSERT_MES(height < m_db_blocks.size(), false, "prune_ring_signatures called with wrong parameter: " << height << ", m_blocks.size() = " << m_db_blocks.size()); auto vptr = m_db_blocks[height]; CHECK_AND_ASSERT_MES(vptr.get(), false, "Failed to get block on height"); @@ -626,22 +626,20 @@ bool blockchain_storage::prune_ring_signatures_and_attachments_if_need() { CRITICAL_REGION_LOCAL(m_read_lock); - if (m_db_blocks.size() > 1 && m_checkpoints.get_top_checkpoint_height() && m_checkpoints.get_top_checkpoint_height() > m_db_current_pruned_rs_height) - { - uint64_t pruning_last_height = std::min(m_db_blocks.size() - 1, m_checkpoints.get_top_checkpoint_height()); - if (pruning_last_height > m_db_current_pruned_rs_height) + uint64_t top_block_height = get_top_block_height(); + uint64_t pruning_end_height = m_checkpoints.get_checkpoint_before_height(top_block_height); + if (pruning_end_height > m_db_current_pruned_rs_height) + { + LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_end_height + << " (" << pruning_end_height - m_db_current_pruned_rs_height << " blocks), top block height is " << top_block_height, LOG_LEVEL_0); + uint64_t tx_count = 0, sig_count = 0, attach_count = 0; + for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_end_height; height++) { - LOG_PRINT_CYAN("Starting pruning ring signatues and attachments from height " << m_db_current_pruned_rs_height + 1 << " to height " << pruning_last_height - << " (" << pruning_last_height - m_db_current_pruned_rs_height << " blocks)", LOG_LEVEL_0); - uint64_t tx_count = 0, sig_count = 0, attach_count = 0; - for(uint64_t height = m_db_current_pruned_rs_height + 1; height <= pruning_last_height; height++) - { - bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count); - CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height); - } - m_db_current_pruned_rs_height = pruning_last_height; - LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0); + bool res = prune_ring_signatures_and_attachments(height, tx_count, sig_count, attach_count); + CHECK_AND_ASSERT_MES(res, false, "failed to prune_ring_signatures_and_attachments for height = " << height); } + m_db_current_pruned_rs_height = pruning_end_height; + LOG_PRINT_CYAN("Transaction pruning finished: " << sig_count << " signatures and " << attach_count << " attachments released in " << tx_count << " transactions.", LOG_LEVEL_0); } return true; } @@ -1036,7 +1034,9 @@ void blockchain_storage::purge_alt_block_txs_hashs(const block& b) //------------------------------------------------------------------ void blockchain_storage::do_erase_altblock(alt_chain_container::iterator it) { - purge_altblock_keyimages_from_big_heap(it->second.bl, get_block_hash(it->second.bl)); + crypto::hash id = get_block_hash(it->second.bl); + LOG_PRINT_L1("erasing alt block " << print16(id) << " @ " << get_block_height(it->second.bl)); + purge_altblock_keyimages_from_big_heap(it->second.bl, id); purge_alt_block_txs_hashs(it->second.bl); m_alternative_chains.erase(it); } @@ -2114,7 +2114,7 @@ bool blockchain_storage::get_tx_rpc_details(const crypto::hash& h, tx_rpc_extend if (tx_ptr && !timestamp) { - timestamp = get_actual_timestamp(m_db_blocks[tx_ptr->m_keeper_block_height]->bl); + timestamp = get_block_datetime(m_db_blocks[tx_ptr->m_keeper_block_height]->bl); } tei.keeper_block = static_cast(tx_ptr->m_keeper_block_height); fill_tx_rpc_details(tei, tx_ptr->tx, &(*tx_ptr), h, timestamp, is_short); @@ -2203,11 +2203,11 @@ bool blockchain_storage::get_main_block_rpc_details(uint64_t i, block_rpc_extend crypto::hash coinbase_id = get_transaction_hash(core_bei_ptr->bl.miner_tx); //load transactions details bei.transactions_details.push_back(tx_rpc_extended_info()); - get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true); + get_tx_rpc_details(coinbase_id, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true); for (auto& h : core_bei_ptr->bl.tx_hashes) { bei.transactions_details.push_back(tx_rpc_extended_info()); - get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(core_bei_ptr->bl), true); + get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(core_bei_ptr->bl), true); bei.total_fee += bei.transactions_details.back().fee; bei.total_txs_size += bei.transactions_details.back().blob_size; } @@ -2288,13 +2288,13 @@ bool blockchain_storage::get_alt_block_rpc_details(const block_extended_info& be crypto::hash coinbase_id = get_transaction_hash(bei_core.bl.miner_tx); //load transactions details bei.transactions_details.push_back(tx_rpc_extended_info()); - fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_actual_timestamp(bei_core.bl)); + fill_tx_rpc_details(bei.transactions_details.back(), bei_core.bl.miner_tx, nullptr, coinbase_id, get_block_datetime(bei_core.bl)); bei.total_fee = 0; for (auto& h : bei_core.bl.tx_hashes) { bei.transactions_details.push_back(tx_rpc_extended_info()); - if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_actual_timestamp(bei_core.bl), true)) + if (!get_tx_rpc_details(h, bei.transactions_details.back(), get_block_datetime(bei_core.bl), true)) { //tx not in blockchain, supposed to be in tx pool m_tx_pool.get_transaction_details(h, bei.transactions_details.back()); @@ -2407,8 +2407,8 @@ uint64_t blockchain_storage::get_seconds_between_last_n_block(size_t n) const if (m_db_blocks.size() <= n) return 0; - uint64_t top_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1]->bl); - uint64_t n_block_ts = get_actual_timestamp(m_db_blocks[m_db_blocks.size() - 1 - n]->bl); + uint64_t top_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1]->bl); + uint64_t n_block_ts = get_block_datetime(m_db_blocks[m_db_blocks.size() - 1 - n]->bl); return top_block_ts > n_block_ts ? top_block_ts - n_block_ts : 0; } @@ -3816,12 +3816,14 @@ namespace currency const crypto::hash& m_tx_id; const crypto::hash& m_bl_id; const uint64_t m_bl_height; - add_transaction_input_visitor(blockchain_storage& bcs, blockchain_storage::key_images_container& m_db_spent_keys, const crypto::hash& tx_id, const crypto::hash& bl_id, const uint64_t bl_height) : + uint64_t &m_mixins_count; + add_transaction_input_visitor(blockchain_storage& bcs, blockchain_storage::key_images_container& m_db_spent_keys, const crypto::hash& tx_id, const crypto::hash& bl_id, const uint64_t bl_height, uint64_t& mixins_count) : m_bcs(bcs), m_db_spent_keys(m_db_spent_keys), m_tx_id(tx_id), m_bl_id(bl_id), - m_bl_height(bl_height) + m_bl_height(bl_height), + m_mixins_count(mixins_count) {} bool operator()(const txin_to_key& in) const { @@ -3846,7 +3848,8 @@ namespace currency return false; } } - + if (m_mixins_count < in.key_offsets.size()) + m_mixins_count = in.key_offsets.size(); return true; } bool operator()(const txin_htlc& in) const @@ -3896,11 +3899,11 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const process_blockchain_tx_attachments(tx, bl_height, bl_id, timestamp); TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_attachment); - + uint64_t mixins_count = 0; TIME_MEASURE_START_PD(tx_process_inputs); for(const txin_v& in : tx.vin) { - if(!boost::apply_visitor(add_transaction_input_visitor(*this, m_db_spent_keys, tx_id, bl_id, bl_height), in)) + if(!boost::apply_visitor(add_transaction_input_visitor(*this, m_db_spent_keys, tx_id, bl_id, bl_height, mixins_count), in)) { LOG_ERROR("critical internal error: add_transaction_input_visitor failed. but key_images should be already checked"); purge_transaction_keyimages_from_blockchain(tx, false); @@ -3913,6 +3916,13 @@ bool blockchain_storage::add_transaction_from_block(const transaction& tx, const } } TIME_MEASURE_FINISH_PD_COND(need_to_profile, tx_process_inputs); + if (need_to_profile && mixins_count > 0) + { + m_performance_data.tx_mixin_count.push(mixins_count); +#ifdef _DEBUG + LOG_PRINT_L0("[TX_MIXINS]: " << mixins_count); +#endif + } //check if there is already transaction with this hash TIME_MEASURE_START_PD(tx_check_exist); @@ -4895,7 +4905,7 @@ void blockchain_storage::get_pos_mining_estimate(uint64_t amount_coins, auto bei = m_db_blocks[h]; if (!is_pos_block(bei->bl)) continue; - uint64_t ts = get_actual_timestamp(bei->bl); + uint64_t ts = get_block_datetime(bei->bl); pos_ts_min = min(pos_ts_min, ts); pos_ts_max = max(pos_ts_max, ts); pos_total_minted_money += get_reward_from_miner_tx(bei->bl.miner_tx); @@ -5050,7 +5060,8 @@ bool blockchain_storage::validate_pos_block(const block& b, } - //check actual time if it there + // the following check is de-facto not applicable since 2021-10, but left intact to avoid consensus issues + // PoS blocks don't use etc_tx_time anymore to store actual timestamp; instead, they use tx_service_attachment in mining tx extra uint64_t actual_ts = get_actual_timestamp(b); if ((actual_ts > b.timestamp && actual_ts - b.timestamp > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) || (actual_ts < b.timestamp && b.timestamp - actual_ts > POS_MAX_ACTUAL_TIMESTAMP_TO_MINED) @@ -5369,7 +5380,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt block_fees.reserve(bl.tx_hashes.size()); //process transactions TIME_MEASURE_START_PD(all_txs_insert_time_5); - if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_actual_timestamp(bl))) + if (!add_transaction_from_block(bl.miner_tx, get_transaction_hash(bl.miner_tx), id, get_current_blockchain_size(), get_block_datetime(bl))) { LOG_PRINT_L0("Block with id: " << id << " failed to add transaction to blockchain storage"); bvc.m_verification_failed = true; @@ -5444,7 +5455,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt TIME_MEASURE_START_PD(tx_prapare_append); uint64_t current_bc_size = get_current_blockchain_size(); - uint64_t actual_timestamp = get_actual_timestamp(bl); + uint64_t actual_timestamp = get_block_datetime(bl); TIME_MEASURE_FINISH_PD(tx_prapare_append); TIME_MEASURE_START_PD(tx_append_time); if(!add_transaction_from_block(tx, tx_id, id, current_bc_size, actual_timestamp)) @@ -5612,7 +5623,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt stringstream powpos_str_entry, timestamp_str_entry; if (is_pos_bl) { // PoS - int64_t actual_ts = get_actual_timestamp(bei.bl); // signed int is intentionally used here + int64_t actual_ts = get_block_datetime(bei.bl); // signed int is intentionally used here int64_t ts_diff = actual_ts - m_core_runtime_config.get_core_time(); powpos_str_entry << "PoS:\t" << proof_hash << ", stake amount: " << print_money_brief(pos_coinstake_amount) << ", final_difficulty: " << this_coin_diff; timestamp_str_entry << ", actual ts: " << actual_ts << " (diff: " << std::showpos << ts_diff << "s) block ts: " << std::noshowpos << bei.bl.timestamp << " (shift: " << std::showpos << static_cast(bei.bl.timestamp) - actual_ts << ")"; diff --git a/src/currency_core/blockchain_storage.h b/src/currency_core/blockchain_storage.h index 5c3b995..cad2ca9 100644 --- a/src/currency_core/blockchain_storage.h +++ b/src/currency_core/blockchain_storage.h @@ -73,33 +73,35 @@ namespace currency epee::math_helper::average target_calculating_calc; //tx processing zone - epee::math_helper::average tx_check_inputs_time; - epee::math_helper::average tx_add_one_tx_time; - epee::math_helper::average tx_process_extra; - epee::math_helper::average tx_process_attachment; - epee::math_helper::average tx_process_inputs ; - epee::math_helper::average tx_push_global_index; - epee::math_helper::average tx_check_exist; - epee::math_helper::average tx_print_log; - epee::math_helper::average tx_prapare_append; + epee::math_helper::average tx_check_inputs_time; + epee::math_helper::average tx_add_one_tx_time; + epee::math_helper::average tx_process_extra; + epee::math_helper::average tx_process_attachment; + epee::math_helper::average tx_process_inputs ; + epee::math_helper::average tx_push_global_index; + epee::math_helper::average tx_check_exist; + epee::math_helper::average tx_print_log; + epee::math_helper::average tx_prapare_append; - epee::math_helper::average tx_append_time; - epee::math_helper::average tx_append_rl_wait; - epee::math_helper::average tx_append_is_expired; + epee::math_helper::average tx_append_time; + epee::math_helper::average tx_append_rl_wait; + epee::math_helper::average tx_append_is_expired; - epee::math_helper::average tx_store_db; + epee::math_helper::average tx_store_db; - epee::math_helper::average tx_check_inputs_prefix_hash; - epee::math_helper::average tx_check_inputs_attachment_check; - epee::math_helper::average tx_check_inputs_loop; - epee::math_helper::average tx_check_inputs_loop_kimage_check; - epee::math_helper::average tx_check_inputs_loop_ch_in_val_sig; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_get_item_size; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_find_tx; - epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_handle_output; + epee::math_helper::average tx_check_inputs_prefix_hash; + epee::math_helper::average tx_check_inputs_attachment_check; + epee::math_helper::average tx_check_inputs_loop; + epee::math_helper::average tx_check_inputs_loop_kimage_check; + epee::math_helper::average tx_check_inputs_loop_ch_in_val_sig; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_get_item_size; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_relative_to_absolute; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_get_subitem; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_find_tx; + epee::math_helper::average tx_check_inputs_loop_scan_outputkeys_loop_handle_output; + + epee::math_helper::average tx_mixin_count; //TODO: move this to suitable place or remove it all @@ -394,7 +396,7 @@ namespace currency else { CHECK_AND_ASSERT_MES(*block_ind_ptr < m_db_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id) - << " have index record with offset=" << *block_ind_ptr << ", bigger then m_blocks.size()=" << m_db_blocks.size()); + << " have index record with offset=" << *block_ind_ptr << ", bigger then m_db_blocks.size()=" << m_db_blocks.size()); blocks.push_back(m_db_blocks[*block_ind_ptr]->bl); } } diff --git a/src/currency_core/checkpoints.cpp b/src/currency_core/checkpoints.cpp index 2d99769..bbce981 100644 --- a/src/currency_core/checkpoints.cpp +++ b/src/currency_core/checkpoints.cpp @@ -36,11 +36,11 @@ namespace currency if(height > blockchain_last_block_height) return false; - auto it = m_points.lower_bound(height); + auto it = m_points.lower_bound(height); // if found, it->first >= height if(it == m_points.end()) return false; if(it->first <= blockchain_last_block_height) - return true; + return true; // this is the case only if height <= it->first <= blockchain_last_block_height else return false; } @@ -68,4 +68,27 @@ namespace currency return false; } } + //--------------------------------------------------------------------------- + uint64_t checkpoints::get_checkpoint_before_height(uint64_t height) const + { + // returns height of the leftmost CP with height that is LESS than the given height + // ex: + // If there are two CP at 11 and 15: + // get_checkpoint_before_height(10) = 0 + // get_checkpoint_before_height(11) = 0 + // get_checkpoint_before_height(12) = 11 + // get_checkpoint_before_height(13) = 11 + // get_checkpoint_before_height(14) = 11 + // get_checkpoint_before_height(15) = 11 + // get_checkpoint_before_height(16) = 15 + + uint64_t top_cp = get_top_checkpoint_height(); + if (height > top_cp) + return top_cp; + + auto it = m_points.lower_bound(height); // if found, it->first >= height + if (it == m_points.end() || it == m_points.begin()) + return 0; + return (--it)->first; + } } diff --git a/src/currency_core/checkpoints.h b/src/currency_core/checkpoints.h index a845e6e..76675e6 100644 --- a/src/currency_core/checkpoints.h +++ b/src/currency_core/checkpoints.h @@ -20,6 +20,8 @@ namespace currency bool is_height_passed_zone(uint64_t height, uint64_t blockchain_last_block_height) const; bool check_block(uint64_t height, const crypto::hash& h) const; uint64_t get_top_checkpoint_height() const; + + uint64_t get_checkpoint_before_height(uint64_t height) const; private: std::map m_points; }; diff --git a/src/currency_core/checkpoints_create.h b/src/currency_core/checkpoints_create.h index ea87d78..059d190 100644 --- a/src/currency_core/checkpoints_create.h +++ b/src/currency_core/checkpoints_create.h @@ -17,13 +17,14 @@ namespace currency inline bool create_checkpoints(currency::checkpoints& checkpoints) { #ifdef TESTNET - //ADD_CHECKPOINT(50000, "492ef71f5d722a8a182d65eb0ff731b740e023a2d64881f43db9af7b39ba7988"); + #else // MAINNET - ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8"); - ADD_CHECKPOINT(525000, "8c1ac57e67448130207a224b2d6e33ccdc64d6dd1c59dbcf9ad2361dc0d07d51"); - ADD_CHECKPOINT(600000, "d9fe316086e1aaea07d94082973ec764eff5fc5a05ed6e1eca273cee59daeeb4"); - ADD_CHECKPOINT(900000, "2205b73cd79d4937b087b02a8b001171b73c34464bc4a952834eaf7c2bd63e86"); + ADD_CHECKPOINT(425000, "46a6c36d5dec2d484d5e4845a8525ca322aafc06915ed9c8da2a241b51b7d1e8"); + ADD_CHECKPOINT(525000, "8c1ac57e67448130207a224b2d6e33ccdc64d6dd1c59dbcf9ad2361dc0d07d51"); + ADD_CHECKPOINT(600000, "d9fe316086e1aaea07d94082973ec764eff5fc5a05ed6e1eca273cee59daeeb4"); + ADD_CHECKPOINT(900000, "2205b73cd79d4937b087b02a8b001171b73c34464bc4a952834eaf7c2bd63e86"); + ADD_CHECKPOINT(1161000, "96990d851b484e30190678756ba2a4d3a2f92b987e2470728ac1e38b2bf35908"); #endif return true; diff --git a/src/currency_core/currency_basic.h b/src/currency_core/currency_basic.h index 274a2f2..dc973a6 100644 --- a/src/currency_core/currency_basic.h +++ b/src/currency_core/currency_basic.h @@ -383,11 +383,25 @@ namespace currency FIELD(security) FIELD(flags) END_SERIALIZE() + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(service_id) + KV_SERIALIZE(instruction) + KV_SERIALIZE_BLOB_AS_HEX_STRING(body) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(security) + KV_SERIALIZE(flags) + END_KV_SERIALIZE_MAP() }; // applicable flags for tx_service_attachment::flags, can be combined using bitwise OR -#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast(1 << 0) -#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast(1 << 1) +#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast(1 << 0) +#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast(1 << 1) + +// with this flag enabled body encrypted/decrypted with the key created as a derivation from onetime key and "spend keys" of receiver +#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE static_cast(1 << 2) +// add proof of content, without revealing secrete +#define TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF static_cast(1 << 3) + //, @@ -690,6 +704,7 @@ namespace currency return k; } }; + const static keypair null_keypair = AUTO_VAL_INIT(null_keypair); //--------------------------------------------------------------- //PoS //based from ppcoin/novacoin approach diff --git a/src/currency_core/currency_config.h b/src/currency_core/currency_config.h index 1b658a6..4dfa5e1 100644 --- a/src/currency_core/currency_config.h +++ b/src/currency_core/currency_config.h @@ -148,7 +148,9 @@ #define WALLET_FILE_SIGNATURE_OLD 0x1111012101101011LL // Bender's nightmare #define WALLET_FILE_SIGNATURE_V2 0x1111011201101011LL // another Bender's nightmare -#define WALLET_FILE_BINARY_HEADER_VERSION 1001 +#define WALLET_FILE_BINARY_HEADER_VERSION_INITAL 1000 +#define WALLET_FILE_BINARY_HEADER_VERSION_2 1001 +//#define WALLET_FILE_BINARY_HEADER_VERSION_3 1002 #define WALLET_FILE_MAX_KEYS_SIZE 10000 // #define WALLET_BRAIN_DATE_OFFSET 1543622400 @@ -209,7 +211,7 @@ #define MINER_CONFIG_FILENAME "miner_conf.json" #define GUI_SECURE_CONFIG_FILENAME "gui_secure_conf.bin" #define GUI_CONFIG_FILENAME "gui_settings.json" -#define GUI_INTERNAL_CONFIG "gui_internal_config.bin" +#define GUI_INTERNAL_CONFIG2 "gui_internal_config.json" @@ -223,9 +225,11 @@ #define BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER CURRENCY_FORMATION_VERSION + BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 9 #define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin" - +#ifndef TESTNET +#define WALLET_FILE_SERIALIZATION_VERSION 153 +#else #define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+69) - +#endif #define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31) diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index 7c014f2..3eb451c 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -26,6 +26,7 @@ using namespace epee; #include "bc_payments_id_service.h" #include "bc_escrow_service.h" #include "bc_attachments_helpers.h" +#include "bc_block_datetime_service.h" #include "genesis.h" #include "genesis_acc.h" #include "common/mnemonic-encoding.h" @@ -64,11 +65,6 @@ namespace currency pos_entry()); }*/ //--------------------------------------------------------------- - uint64_t get_coinday_weight(uint64_t amount) - { - return amount; - } - //--------------------------------------------------------------- wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff) { //delta=delta*(0.75^n) @@ -594,12 +590,12 @@ namespace currency std::string generate_origin_for_htlc(const txout_htlc& htlc, const account_keys& acc_keys) { std::string blob; - string_tools::apped_pod_to_strbuff(blob, htlc.pkey_redeem); - string_tools::apped_pod_to_strbuff(blob, htlc.pkey_refund); - string_tools::apped_pod_to_strbuff(blob, acc_keys.spend_secret_key); + string_tools::append_pod_to_strbuff(blob, htlc.pkey_redeem); + string_tools::append_pod_to_strbuff(blob, htlc.pkey_refund); + string_tools::append_pod_to_strbuff(blob, acc_keys.spend_secret_key); crypto::hash origin_hs = crypto::cn_fast_hash(blob.data(), blob.size()); std::string origin_blob; - string_tools::apped_pod_to_strbuff(origin_blob, origin_hs); + string_tools::append_pod_to_strbuff(origin_blob, origin_hs); return origin_blob; } //--------------------------------------------------------------- @@ -759,8 +755,12 @@ namespace currency struct encrypt_attach_visitor : public boost::static_visitor { bool& m_was_crypted_entries; + const keypair& m_onetime_keypair; + const account_public_address& m_destination_addr; const crypto::key_derivation& m_key; - encrypt_attach_visitor(bool& was_crypted_entries, const crypto::key_derivation& key) :m_was_crypted_entries(was_crypted_entries), m_key(key) + + encrypt_attach_visitor(bool& was_crypted_entries, const crypto::key_derivation& key, const keypair& onetime_keypair = null_keypair, const account_public_address& destination_addr = null_pub_addr) : + m_was_crypted_entries(was_crypted_entries), m_key(key), m_onetime_keypair(onetime_keypair), m_destination_addr(destination_addr) {} void operator()(tx_comment& comment) { @@ -789,6 +789,7 @@ namespace currency } void operator()(tx_service_attachment& sa) { + const std::string original_body = sa.body; if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) { zlib_helper::pack(sa.body); @@ -796,7 +797,28 @@ namespace currency if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY) { - crypto::chacha_crypt(sa.body, m_key); + crypto::key_derivation derivation_local = m_key; + if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE) + { + CHECK_AND_ASSERT_THROW_MES(m_destination_addr.spend_public_key != currency::null_pkey && m_onetime_keypair.sec != currency::null_skey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized"); + //encrypt with "spend keys" only, to prevent auditable watchers decrypt it + bool r = crypto::generate_key_derivation(m_destination_addr.spend_public_key, m_onetime_keypair.sec, derivation_local); + CHECK_AND_ASSERT_THROW_MES(r, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: Failed to make derivation"); + crypto::chacha_crypt(sa.body, derivation_local); + } + else + { + crypto::chacha_crypt(sa.body, derivation_local); + } + if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF) + { + //take hash from derivation and use it as a salt + crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local)); + std::string salted_body = original_body; + string_tools::append_pod_to_strbuff(salted_body, derivation_hash); + crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size()); + sa.security.push_back(*(crypto::public_key*)&proof_hash); + } m_was_crypted_entries = true; } } @@ -808,12 +830,18 @@ namespace currency struct decrypt_attach_visitor : public boost::static_visitor { + const account_keys& m_acc_keys; + const crypto::public_key& m_tx_onetime_pubkey; const crypto::key_derivation& rkey; std::vector& rdecrypted_att; decrypt_attach_visitor(const crypto::key_derivation& key, - std::vector& decrypted_att) : + std::vector& decrypted_att, + const account_keys& acc_keys = null_acc_keys, + const crypto::public_key& tx_onetime_pubkey = null_pkey) : rkey(key), - rdecrypted_att(decrypted_att) + rdecrypted_att(decrypted_att), + m_acc_keys(acc_keys), + m_tx_onetime_pubkey(tx_onetime_pubkey) {} void operator()(const tx_comment& comment) { @@ -825,15 +853,44 @@ namespace currency void operator()(const tx_service_attachment& sa) { tx_service_attachment local_sa = sa; + crypto::key_derivation derivation_local = rkey; if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY) { - crypto::chacha_crypt(local_sa.body, rkey); + if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE) + { + if (m_acc_keys.spend_secret_key == null_skey) + { + //this watch only wallet, decrypting supposed to be impossible + return; + } + CHECK_AND_ASSERT_THROW_MES(m_acc_keys.spend_secret_key != currency::null_skey && m_tx_onetime_pubkey != currency::null_pkey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized"); + bool r = crypto::generate_key_derivation(m_tx_onetime_pubkey, m_acc_keys.spend_secret_key, derivation_local); + CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate_key_derivation at TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE"); + crypto::chacha_crypt(local_sa.body, derivation_local); + + } + else + { + crypto::chacha_crypt(local_sa.body, derivation_local); + } } if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY) { zlib_helper::unpack(local_sa.body); } + + if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY && sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF) + { + CHECK_AND_ASSERT_MES(sa.security.size() == 1, void(), "Unexpected key in tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE"); + //take hash from derivation and use it as a salt + crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local)); + std::string salted_body = local_sa.body; + string_tools::append_pod_to_strbuff(salted_body, derivation_hash); + crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size()); // proof_hash = Hs(local_sa.body || Hs(s * R)), s - spend secret, R - tx pub + CHECK_AND_ASSERT_MES(*(crypto::public_key*)&proof_hash == sa.security.front(), void(), "Proof hash missmatch on decrypting with TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF"); + } + rdecrypted_att.push_back(local_sa); } @@ -870,9 +927,10 @@ namespace currency //--------------------------------------------------------------- template - bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector& decrypted_att) + bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector& decrypted_att, const account_keys& acc_keys = null_acc_keys, + const crypto::public_key& tx_onetime_pubkey = null_pkey) { - decrypt_attach_visitor v(derivation, decrypted_att); + decrypt_attach_visitor v(derivation, decrypted_att, acc_keys, tx_onetime_pubkey); for (auto& a : items_to_decrypt) boost::apply_visitor(v, a); @@ -955,8 +1013,8 @@ namespace currency return true; } - decrypt_payload_items(derivation, tx.extra, decrypted_items); - decrypt_payload_items(derivation, tx.attachment, decrypted_items); + decrypt_payload_items(derivation, tx.extra, decrypted_items, is_income ? acc_keys: account_keys(), get_tx_pub_key_from_extra(tx)); + decrypt_payload_items(derivation, tx.attachment, decrypted_items, is_income ? acc_keys : account_keys(), get_tx_pub_key_from_extra(tx)); return true; } @@ -969,11 +1027,11 @@ namespace currency bool was_attachment_crypted_entries = false; bool was_extra_crypted_entries = false; - encrypt_attach_visitor v(was_attachment_crypted_entries, derivation); + encrypt_attach_visitor v(was_attachment_crypted_entries, derivation, tx_random_key, destination_addr); for (auto& a : tx.attachment) boost::apply_visitor(v, a); - encrypt_attach_visitor v2(was_extra_crypted_entries, derivation); + encrypt_attach_visitor v2(was_extra_crypted_entries, derivation, tx_random_key, destination_addr); for (auto& a : tx.extra) boost::apply_visitor(v2, a); @@ -994,26 +1052,26 @@ namespace currency } } //--------------------------------------------------------------- - void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x) - { - x.is_service = currency::is_service_tx(x.tx); - x.is_mixing = currency::does_tx_have_only_mixin_inputs(x.tx); - x.is_mining = currency::is_coinbase(x.tx); - if (!x.is_mining) - x.fee = currency::get_tx_fee(x.tx); - else - x.fee = 0; - x.show_sender = currency::is_showing_sender_addres(x.tx); - tx_out htlc_out = AUTO_VAL_INIT(htlc_out); - txin_htlc htlc_in = AUTO_VAL_INIT(htlc_in); + // void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x) + // { + // x.is_service = currency::is_service_tx(x.tx); + // x.is_mixing = currency::does_tx_have_only_mixin_inputs(x.tx); + // x.is_mining = currency::is_coinbase(x.tx); + // if (!x.is_mining) + // x.fee = currency::get_tx_fee(x.tx); + // else + // x.fee = 0; + // x.show_sender = currency::is_showing_sender_addres(x.tx); + // tx_out htlc_out = AUTO_VAL_INIT(htlc_out); + // txin_htlc htlc_in = AUTO_VAL_INIT(htlc_in); - x.tx_type = get_tx_type_ex(x.tx, htlc_out, htlc_in); - if(x.tx_type == GUI_TX_TYPE_HTLC_DEPOSIT && x.is_income == true) - { - //need to override amount - x.amount = htlc_out.amount; - } - } + // x.tx_type = get_tx_type_ex(x.tx, htlc_out, htlc_in); + // if(x.tx_type == GUI_TX_TYPE_HTLC_DEPOSIT && x.is_income == true) + // { + // //need to override amount + // x.amount = htlc_out.amount; + // } + // } //--------------------------------------------------------------- uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in) @@ -2000,8 +2058,8 @@ namespace currency crypto::hash hash_together(const pod_operand_a& a, const pod_operand_b& b) { std::string blob; - string_tools::apped_pod_to_strbuff(blob, a); - string_tools::apped_pod_to_strbuff(blob, b); + string_tools::append_pod_to_strbuff(blob, a); + string_tools::append_pod_to_strbuff(blob, b); return crypto::cn_fast_hash(blob.data(), blob.size()); } //------------------------------------------------------------------ @@ -2051,6 +2109,8 @@ namespace currency return median_fee * 10; } //--------------------------------------------------------------- + // NOTE: this function is obsolete and depricated + // PoS block real timestamp is set using a service attachment in mining tx extra since 2021-10 uint64_t get_actual_timestamp(const block& b) { uint64_t tes_ts = b.timestamp; @@ -2062,6 +2122,41 @@ namespace currency } return tes_ts; } + //--------------------------------------------------------------- + // returns timestamp from BC_BLOCK_DATETIME_SERVICE_ID via tx_service_attachment in extra + // fallbacks to old-style actual timestamp via etc_tx_time, then to block timestamp + uint64_t get_block_datetime(const block& b) + { + // first try BC_BLOCK_DATETIME_SERVICE_ID + tx_service_attachment sa = AUTO_VAL_INIT(sa); + if (get_type_in_variant_container(b.miner_tx.extra, sa)) + { + if (sa.service_id == BC_BLOCK_DATETIME_SERVICE_ID && sa.instruction == BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT) + { + uint64_t ts; + if (epee::string_tools::get_pod_from_strbuff(sa.body, ts)) + return ts; + } + } + + // next try etc_tx_time + etc_tx_time t = AUTO_VAL_INIT(t); + if (get_type_in_variant_container(b.miner_tx.extra, t)) + return t.v; + + // otherwise return default: block.ts + return b.timestamp; + } + //--------------------------------------------------------------- + void set_block_datetime(uint64_t datetime, block& b) + { + tx_service_attachment sa = AUTO_VAL_INIT(sa); + sa.service_id = BC_BLOCK_DATETIME_SERVICE_ID; + sa.instruction = BC_BLOCK_DATETIME_INSTRUCTION_DEFAULT; + sa.flags = 0; + epee::string_tools::append_pod_to_strbuff(sa.body, datetime); + b.miner_tx.extra.push_back(sa); + } //------------------------------------------------------------------ bool validate_alias_name(const std::string& al) { @@ -2720,7 +2815,7 @@ namespace currency pei_rpc.timestamp = bei_chain.bl.timestamp; pei_rpc.id = epee::string_tools::pod_to_hex(h); pei_rpc.prev_id = epee::string_tools::pod_to_hex(bei_chain.bl.prev_id); - pei_rpc.actual_timestamp = get_actual_timestamp(bei_chain.bl); + pei_rpc.actual_timestamp = get_block_datetime(bei_chain.bl); pei_rpc.type = is_pos_block(bei_chain.bl) ? 0 : 1; pei_rpc.already_generated_coins = boost::lexical_cast(bei_chain.already_generated_coins); pei_rpc.this_block_fee_median = bei_chain.this_block_tx_fee_median; @@ -2888,6 +2983,13 @@ namespace currency return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (normal) } //----------------------------------------------------------------------- + bool is_address_like_wrapped(const std::string& addr) + { + if (addr.length() == 42 && addr.substr(0, 2) == "0x") + return true; + else return false; + } + //----------------------------------------------------------------------- std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id) { if (addr.flags == 0) diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 6474307..e9b7854 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -28,7 +28,7 @@ #include "currency_format_utils_blocks.h" #include "currency_format_utils_transactions.h" #include "core_runtime_config.h" -#include "wallet/wallet_public_structs_defs.h" +// #include "wallet/wallet_public_structs_defs.h" // ------ get_tx_type_definition ------------- @@ -289,7 +289,8 @@ namespace currency bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector& decrypted_items); void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key); bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation); - void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x); + bool is_address_like_wrapped(const std::string& addr); + // void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x); uint64_t get_tx_type(const transaction& tx); uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in); size_t get_multisig_out_index(const std::vector& outs); @@ -328,8 +329,10 @@ namespace currency // prints amount in format "3.14", "0.0" std::string print_money_brief(uint64_t amount); - uint64_t get_actual_timestamp(const block& b); - + uint64_t get_actual_timestamp(const block& b); // obsolete and depricated, use get_block_datetime + uint64_t get_block_datetime(const block& b); + void set_block_datetime(uint64_t datetime, block& b); + bool addendum_to_hexstr(const std::vector& add, std::string& hex_buff); bool hexstr_to_addendum(const std::string& hex_buff, std::vector& add); bool set_payment_id_to_tx(std::vector& att, const std::string& payment_id); @@ -345,7 +348,6 @@ namespace currency //PoS bool is_pos_block(const block& b); bool is_pos_block(const transaction& tx); - uint64_t get_coinday_weight(uint64_t amount); wide_difficulty_type correct_difficulty_with_sequence_factor(size_t sequence_factor, wide_difficulty_type diff); void print_currency_details(); std::string print_reward_change_first_blocks(size_t n_of_first_blocks); diff --git a/src/currency_core/offers_services_helpers.h b/src/currency_core/offers_services_helpers.h index fc2203f..1484622 100644 --- a/src/currency_core/offers_services_helpers.h +++ b/src/currency_core/offers_services_helpers.h @@ -97,8 +97,8 @@ namespace bc_services inline currency::blobdata make_offer_sig_blob(const update_offer& uo) { currency::blobdata bd; - epee::string_tools::apped_pod_to_strbuff(bd, uo.tx_id); - epee::string_tools::apped_pod_to_strbuff(bd, uo.offer_index); + epee::string_tools::append_pod_to_strbuff(bd, uo.tx_id); + epee::string_tools::append_pod_to_strbuff(bd, uo.offer_index); bd += epee::serialization::store_t_to_binary(uo.of); return bd; } @@ -106,8 +106,8 @@ namespace bc_services inline currency::blobdata make_offer_sig_blob(const cancel_offer& co) { currency::blobdata bd; - epee::string_tools::apped_pod_to_strbuff(bd, co.tx_id); - epee::string_tools::apped_pod_to_strbuff(bd, co.offer_index); + epee::string_tools::append_pod_to_strbuff(bd, co.tx_id); + epee::string_tools::append_pod_to_strbuff(bd, co.offer_index); return bd; } diff --git a/src/currency_protocol/currency_protocol_handler.inl b/src/currency_protocol/currency_protocol_handler.inl index 6599306..39e42a3 100644 --- a/src/currency_protocol/currency_protocol_handler.inl +++ b/src/currency_protocol/currency_protocol_handler.inl @@ -914,7 +914,8 @@ namespace currency LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_CHAIN_ENTRY, with \r\nm_total_height=" << arg.total_height << "\r\nm_start_height=" << arg.start_height << "\r\nm_block_ids.size()=" << arg.m_block_ids.size()); - //m_p2p->drop_connection(context); + m_p2p->drop_connection(context); + m_p2p->add_ip_fail(context.m_remote_ip); } BOOST_FOREACH(auto& bl_details, arg.m_block_ids) diff --git a/src/main.cc b/src/main.cc index 4445ad1..825857f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -38,14 +38,21 @@ blobdata uint64be_to_blob(uint64_t num) { return res; } +const size_t MM_NONCE_SIZE = 1 + 2 + sizeof(crypto::hash); +NAN_METHOD(get_merged_mining_nonce_size) { + Local returnValue = Nan::New(static_cast(MM_NONCE_SIZE)); + info.GetReturnValue().Set(returnValue); +} NAN_METHOD(convert_blob) { if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument."); - Local target = info[0]->ToObject(); + //Local target = info[0]->ToObject(); + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); @@ -72,7 +79,9 @@ void address_decode(const Nan::FunctionCallbackInfo& info) { if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument."); - Local target = info[0]->ToObject(); + //Local target = info[0]->ToObject(); + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); @@ -89,7 +98,7 @@ void address_decode(const Nan::FunctionCallbackInfo& info) { account_public_address adr; - if (!::serialization::parse_binary(data, adr) || !crypto::check_key(adr.m_spend_public_key) || !crypto::check_key(adr.m_view_public_key)) + if (!::serialization::parse_binary(data, adr) || !crypto::check_key(adr.spend_public_key) || !crypto::check_key(adr.view_public_key)) { if(data.length()) { @@ -111,24 +120,26 @@ void address_decode(const Nan::FunctionCallbackInfo& info) { } } -#define SET_BUFFER_RETURN(x, len) \ - v8::Isolate* isolate = args.GetIsolate(); \ - args.GetReturnValue().Set(Buffer::Copy(isolate, x, len).ToLocalChecked()); - /* Arguments: 1: block_header_hash - 32-byte buffer 2: nonce - 8-byte buffer 2: height - 8-byte buffer */ -void get_pow_hash(const Nan::FunctionCallbackInfo& args) { +void get_pow_hash(const Nan::FunctionCallbackInfo& info) { - if (args.Length() < 3) + if (info.Length() < 3) return THROW_ERROR_EXCEPTION("You must provide 3 arguments."); - Local block_header_hash = args[0]->ToObject(); - Local nonce = args[1]->ToObject(); - Local height = args[2]->ToObject(); + //Local block_header_hash = args[0]->ToObject(); + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local block_header_hash = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + + //Local nonce = args[1]->ToObject(); + Local nonce = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + + //Local height = args[2]->ToObject(); + Local height = info[2]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if(!Buffer::HasInstance(block_header_hash)) return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); @@ -159,7 +170,10 @@ void get_pow_hash(const Nan::FunctionCallbackInfo& args) { crypto::hash h = currency::get_block_longhash(height_val, block_header_hash_val, nonce_val); - SET_BUFFER_RETURN((const char*)&h, 32); + //SET_BUFFER_RETURN((const char*)&h, 32); + char *cstr = reinterpret_cast(&h); + v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); + info.GetReturnValue().Set(returnValue); } /* @@ -167,13 +181,17 @@ Arguments: 1: block_template_buffer - n-byte buffer 2: extra_data - n-byte buffer(job identification) */ -void get_hash_from_block_template_with_extra(const Nan::FunctionCallbackInfo& args) { +void get_hash_from_block_template_with_extra(const Nan::FunctionCallbackInfo& info) { - if (args.Length() < 2) + if (info.Length() < 2) return THROW_ERROR_EXCEPTION("You must provide 2 arguments."); - Local block_template_buffer = args[0]->ToObject(); - Local extra_data = args[1]->ToObject(); + //Local block_template_buffer = args[0]->ToObject(); + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + + //Local extra_data = args[1]->ToObject(); + Local extra_data = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if (!Buffer::HasInstance(block_template_buffer)) @@ -201,7 +219,10 @@ void get_hash_from_block_template_with_extra(const Nan::FunctionCallbackInfo(&h); + v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); + info.GetReturnValue().Set(returnValue); } /* @@ -210,14 +231,20 @@ Arguments: 2: extra_data - n-byte buffer(job identification) 3: nonce - 8-byte buffer - nonce */ -void get_blob_from_block_template(const Nan::FunctionCallbackInfo& args) { +void get_blob_from_block_template(const Nan::FunctionCallbackInfo& info) { - if (args.Length() < 3) + if (info.Length() < 3) return THROW_ERROR_EXCEPTION("You must provide 3 arguments."); - Local block_template_buffer = args[0]->ToObject(); - Local extra_data = args[1]->ToObject(); - Local nonce = args[2]->ToObject(); + //Local block_template_buffer = args[0]->ToObject(); + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + + //Local extra_data = args[1]->ToObject(); + Local extra_data = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + + //Local nonce = args[2]->ToObject(); + Local nonce = info[2]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if (!Buffer::HasInstance(block_template_buffer)) @@ -258,17 +285,19 @@ void get_blob_from_block_template(const Nan::FunctionCallbackInfo& ar crypto::hash h = currency::get_block_hash(b); - SET_BUFFER_RETURN(result_blob.data(), result_blob.size()); + //SET_BUFFER_RETURN(result_blob.data(), result_blob.size()); + v8::Local returnValue = Nan::CopyBuffer((char*)result_blob.data(), result_blob.size()).ToLocalChecked(); + info.GetReturnValue().Set(returnValue); } -void get_id_hash(const Nan::FunctionCallbackInfo& args) { +void get_id_hash(const Nan::FunctionCallbackInfo& info) { - if (args.Length() < 1) + if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide 2 arguments."); - - Local block_buffer = args[0]->ToObject(); - + + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local block_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); if (!Buffer::HasInstance(block_buffer)) return THROW_ERROR_EXCEPTION("Argument 1 should be a buffer object."); @@ -285,7 +314,10 @@ void get_id_hash(const Nan::FunctionCallbackInfo& args) { crypto::hash h = currency::get_block_hash(b); - SET_BUFFER_RETURN((const char*)&h, 32); + //SET_BUFFER_RETURN((const char*)&h, 32); + char *cstr = reinterpret_cast(&h); + v8::Local returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked(); + info.GetReturnValue().Set(returnValue); } @@ -295,8 +327,10 @@ void is_address_valid(const Nan::FunctionCallbackInfo& info) if (info.Length() < 1) return THROW_ERROR_EXCEPTION("You must provide one argument."); - Local target = info[0]->ToObject(); - + + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + Local target = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked(); + if (!Buffer::HasInstance(target)) return THROW_ERROR_EXCEPTION("Argument should be a buffer object."); @@ -324,7 +358,8 @@ NAN_MODULE_INIT(init) { Nan::Set(target, Nan::New("get_blob_from_block_template").ToLocalChecked(), Nan::GetFunction(Nan::New(get_blob_from_block_template)).ToLocalChecked()); Nan::Set(target, Nan::New("get_id_hash").ToLocalChecked(), Nan::GetFunction(Nan::New(get_id_hash)).ToLocalChecked()); Nan::Set(target, Nan::New("is_address_valid").ToLocalChecked(), Nan::GetFunction(Nan::New(is_address_valid)).ToLocalChecked()); + Nan::Set(target, Nan::New("get_merged_mining_nonce_size").ToLocalChecked(), Nan::GetFunction(Nan::New(get_merged_mining_nonce_size)).ToLocalChecked()); } -NODE_MODULE(cryptonote, init) +NODE_MODULE(cryptonote, init) \ No newline at end of file diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 301b4cd..5c0fb12 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -81,7 +81,8 @@ namespace nodetool m_last_stat_request_time{}, m_use_only_priority_peers(false), m_peer_livetime{}, - m_debug_requests_enabled(false) + m_debug_requests_enabled(false), + m_ip_auto_blocking_enabled(false) {} static void init_options(boost::program_options::options_description& desc); @@ -215,6 +216,8 @@ namespace nodetool bool urgent_alert_worker(); bool critical_alert_worker(); bool remove_dead_connections(); + bool is_ip_good_for_adding_to_peerlist(uint32_t adress); + bool is_ip_in_blacklist(uint32_t adress); //debug functions @@ -245,6 +248,7 @@ namespace nodetool bool m_hide_my_port; bool m_offline_mode; bool m_debug_requests_enabled; + bool m_ip_auto_blocking_enabled; uint64_t m_startup_time; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 5042548..477d7e8 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -26,18 +26,19 @@ namespace nodetool namespace { - const command_line::arg_descriptor arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"}; - const command_line::arg_descriptor arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)}; - const command_line::arg_descriptor arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0}; - const command_line::arg_descriptor arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"}; - const command_line::arg_descriptor > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"}; - const command_line::arg_descriptor > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"}; + const command_line::arg_descriptor arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"}; + const command_line::arg_descriptor arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)}; + const command_line::arg_descriptor arg_p2p_external_port = {"p2p-external-port", "External port for p2p network protocol (if port forwarding used with NAT)", 0}; + const command_line::arg_descriptor arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"}; + const command_line::arg_descriptor > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"}; + const command_line::arg_descriptor > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"}; const command_line::arg_descriptor arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"}; - const command_line::arg_descriptor > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"}; - const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; - const command_line::arg_descriptor arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true }; - const command_line::arg_descriptor arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true }; -} + const command_line::arg_descriptor > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"}; + const command_line::arg_descriptor arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; + const command_line::arg_descriptor arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true }; + const command_line::arg_descriptor arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true }; + const command_line::arg_descriptor arg_p2p_ip_auto_blocking = { "p2p-ip-auto-blocking", "Enable (1) or disable (0) peers auto-blocking by IP <0|1>. Default: 0", 0, false }; + } //----------------------------------------------------------------------------------- template @@ -53,7 +54,8 @@ namespace nodetool command_line::add_arg(desc, arg_p2p_hide_my_port); command_line::add_arg(desc, arg_p2p_offline_mode); command_line::add_arg(desc, arg_p2p_disable_debug_reqs); - command_line::add_arg(desc, arg_p2p_use_only_priority_nodes); + command_line::add_arg(desc, arg_p2p_use_only_priority_nodes); + command_line::add_arg(desc, arg_p2p_ip_auto_blocking); } //----------------------------------------------------------------------------------- template @@ -65,7 +67,14 @@ namespace nodetool CHECK_AND_ASSERT_MES(r, false, "Failed to parse P2P_MAINTAINERS_PUB_KEY = " << P2P_MAINTAINERS_PUB_KEY); std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME; - tools::unserialize_obj_from_file(*this, state_file_path); + boost::system::error_code ec = AUTO_VAL_INIT(ec); + std::time_t last_update_time = boost::filesystem::last_write_time(state_file_path, ec); + //let's assume that if p2p peer list file stored more then 2 weeks ago, + //then it outdated and we need to fetch peerlist from seed nodes + if (!ec && time(nullptr) - last_update_time < 86400 * 14) + { + tools::unserialize_obj_from_file(*this, state_file_path); + } //always use new id, to be able differ cloned computers m_config.m_peer_id = crypto::rand(); @@ -100,21 +109,39 @@ namespace nodetool if (m_offline_mode) return false; - //@#@ temporary workaround - return true; -#if 0 + if (!m_ip_auto_blocking_enabled) + return true; + + return !is_ip_in_blacklist(addr); + } + //----------------------------------------------------------------------------------- + template + bool node_server::is_ip_good_for_adding_to_peerlist(uint32_t addr) + { + if (m_offline_mode) + return false; + + // even if IP auto blocking is disabled, bad peers should not be added to peerlists and be shared with other nodes + + return !is_ip_in_blacklist(addr); + } + //----------------------------------------------------------------------------------- + template + bool node_server::is_ip_in_blacklist(uint32_t addr) + { CRITICAL_REGION_LOCAL(m_blocked_ips_lock); auto it = m_blocked_ips.find(addr); - if(it == m_blocked_ips.end()) - return true; - if(time(nullptr) - it->second > P2P_IP_BLOCKTIME ) + if (it == m_blocked_ips.end()) + return false; + + if (time(nullptr) - it->second > P2P_IP_BLOCKTIME) { m_blocked_ips.erase(it); - LOG_PRINT_CYAN("Ip " << string_tools::get_ip_string_from_int32(addr) << "is unblocked.", LOG_LEVEL_0); - return true; + LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " is unblocked due to blocking expiration.", LOG_LEVEL_0); + return false; } - return false; -#endif + + return true; } //----------------------------------------------------------------------------------- template @@ -122,7 +149,8 @@ namespace nodetool { CRITICAL_REGION_LOCAL(m_blocked_ips_lock); m_blocked_ips[addr] = time(nullptr); - LOG_PRINT_CYAN("Ip " << string_tools::get_ip_string_from_int32(addr) << " blocked.", LOG_LEVEL_0); + m_peerlist.remove_peers_by_ip_from_all(addr); + LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(addr) << " blocked and removed from peerlist", LOG_LEVEL_0); return true; } //----------------------------------------------------------------------------------- @@ -138,6 +166,10 @@ namespace nodetool it->second = P2P_IP_FAILS_BEFOR_BLOCK/2; block_ip(address); } + else + { + LOG_PRINT_CYAN("IP " << string_tools::get_ip_string_from_int32(address) << ": fail recorded, total fails count: " << fails, LOG_LEVEL_2); + } return true; } //----------------------------------------------------------------------------------- @@ -162,6 +194,9 @@ namespace nodetool m_allow_local_ip = command_line::get_arg(vm, arg_p2p_allow_local_ip); m_offline_mode = command_line::get_arg(vm, arg_p2p_offline_mode); m_debug_requests_enabled = !command_line::get_arg(vm, arg_p2p_disable_debug_reqs); + m_ip_auto_blocking_enabled = (command_line::get_arg(vm, arg_p2p_ip_auto_blocking) != 0); + + LOG_PRINT_L0("p2p peers auto-blocking is " << (m_ip_auto_blocking_enabled ? "enabled" : "disabled")); if (m_offline_mode) { @@ -679,7 +714,6 @@ namespace nodetool << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port) /*<< ", try " << try_count*/); - //m_peerlist.set_peer_unreachable(pe); return false; } peerid_type pi = AUTO_VAL_INIT(pi); @@ -701,12 +735,15 @@ namespace nodetool return true; } - peerlist_entry pe_local = AUTO_VAL_INIT(pe_local); - pe_local.adr = na; - pe_local.id = pi; - time(&pe_local.last_seen); - m_peerlist.append_with_peer_white(pe_local); - //update last seen and push it to peerlist manager + if (is_ip_good_for_adding_to_peerlist(na.ip)) // additional check to avoid IP shown up in peers in the case of non-blocking incoming connections + { + //update last seen and push it to peerlist manager + peerlist_entry pe_local = AUTO_VAL_INIT(pe_local); + pe_local.adr = na; + pe_local.id = pi; + time(&pe_local.last_seen); + m_peerlist.append_with_peer_white(pe_local); + } LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK with peer " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port), LOG_LEVEL_2); return true; @@ -1373,7 +1410,8 @@ namespace nodetool //associate peer_id with this connection context.peer_id = arg.node_data.peer_id; - if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port) + if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port + && is_ip_good_for_adding_to_peerlist(context.m_remote_ip)) { peerid_type peer_id_l = arg.node_data.peer_id; uint32_t port_l = arg.node_data.my_port; diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index 5cdfa0e..f133683 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019 Zano Project +// Copyright (c) 2014-2021 Zano Project // Copyright (c) 2014-2018 The Louisdor Project // Copyright (c) 2012-2013 The Cryptonote developers // Distributed under the MIT/X11 software license, see the accompanying @@ -11,8 +11,6 @@ #include #include #include -//#include -//#include #include #include #include @@ -55,10 +53,10 @@ namespace nodetool bool append_with_peer_gray(const peerlist_entry& pr); bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port); bool set_peer_just_seen(peerid_type peer, const net_address& addr); - bool set_peer_unreachable(const peerlist_entry& pr); bool is_ip_allowed(uint32_t ip); void trim_white_peerlist(); void trim_gray_peerlist(); + bool remove_peers_by_ip_from_all(const uint32_t ip); private: @@ -110,17 +108,6 @@ namespace nodetool > > peers_indexed; - typedef boost::multi_index_container< - peerlist_entry, - boost::multi_index::indexed_by< - // access by peerlist_entry::id< - boost::multi_index::ordered_unique, boost::multi_index::member >, - // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique, boost::multi_index::member >, - // sort by peerlist_entry::last_seen< - boost::multi_index::ordered_non_unique, boost::multi_index::member > - > - > peers_indexed_old; public: template @@ -134,9 +121,7 @@ namespace nodetool ar & m_peers_gray; } - private: - bool peers_indexed_from_old(const peers_indexed_old& pio, peers_indexed& pi); - + private: friend class boost::serialization::access; epee::critical_section m_peerlist_lock; std::string m_config_folder; @@ -188,21 +173,6 @@ namespace nodetool return true; } //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::peers_indexed_from_old(const peers_indexed_old& pio, peers_indexed& pi) - { - for(auto x: pio) - { - auto by_addr_it = pi.get().find(x.adr); - if(by_addr_it == pi.get().end()) - { - pi.insert(x); - } - } - - return true; - } - //-------------------------------------------------------------------------------------------------- inline void peerlist_manager::trim_white_peerlist() { CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -393,6 +363,33 @@ namespace nodetool return true; } //-------------------------------------------------------------------------------------------------- + inline + bool peerlist_manager::remove_peers_by_ip_from_all(const uint32_t ip) + { + TRY_ENTRY(); + + CRITICAL_REGION_LOCAL(m_peerlist_lock); + + for (auto it = m_peers_white.begin(); it != m_peers_white.end();) + { + if (it->adr.ip == ip) + it = m_peers_white.erase(it); + else + ++it; + } + + for (auto it = m_peers_gray.begin(); it != m_peers_gray.end();) + { + if (it->adr.ip == ip) + it = m_peers_gray.erase(it); + else + ++it; + } + + return true; + CATCH_ENTRY_L0("peerlist_manager::remove_peers_by_ip_from_all()", false); + } + //-------------------------------------------------------------------------------------------------- } BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER) diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 6238bed..c16efca 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -180,7 +180,7 @@ namespace currency res.pos_block_ts_shift_vs_actual = 0; auto last_pos_block_ptr = m_core.get_blockchain_storage().get_last_block_of_type(true); if (last_pos_block_ptr) - res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_actual_timestamp(last_pos_block_ptr->bl); + res.pos_block_ts_shift_vs_actual = last_pos_block_ptr->bl.timestamp - get_block_datetime(last_pos_block_ptr->bl); } if (req.flags&COMMAND_RPC_GET_INFO_FLAG_OUTS_STAT) m_core.get_blockchain_storage().get_outs_index_stat(res.outs_stat); @@ -210,6 +210,7 @@ namespace currency res.performance_data.tx_append_time = pd.tx_append_time.get_avg(); res.performance_data.tx_append_rl_wait = pd.tx_append_rl_wait.get_avg(); res.performance_data.tx_append_is_expired = pd.tx_append_is_expired.get_avg(); + res.performance_data.tx_mixin_count = pd.tx_mixin_count.get_avg(); res.performance_data.tx_store_db = pd.tx_store_db.get_avg(); @@ -915,17 +916,6 @@ namespace currency error_resp.message = "Block not accepted"; return false; } - //@#@ - //temporary double check timestamp - if (time(NULL) - static_cast(get_actual_timestamp(b)) > 5) - { - LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b) - << ") is suspiciously less (" << time(NULL) - static_cast(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")"); - //mark node to make it easier to find it via scanner - m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true; - } - // - res.status = "OK"; return true; @@ -972,17 +962,6 @@ namespace currency error_resp.message = "Block not accepted"; return false; } - //@#@ - //temporary double check timestamp - if (time(NULL) - static_cast(get_actual_timestamp(b)) > 5) - { - LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b) - << ") is suspiciously less (" << time(NULL) - static_cast(get_actual_timestamp(b)) << ") than current time ( " << time(NULL) << ")"); - //mark node to make it easier to find it via scanner - m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true; - } - // - res.status = "OK"; return true; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 2ef811a..531cbe7 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -500,6 +500,8 @@ namespace currency uint64_t tx_print_log; uint64_t tx_prapare_append; + uint64_t tx_mixin_count; + uint64_t tx_store_db; @@ -547,6 +549,7 @@ namespace currency KV_SERIALIZE(tx_store_db) KV_SERIALIZE(tx_print_log) KV_SERIALIZE(tx_prapare_append) + KV_SERIALIZE(tx_mixin_count) KV_SERIALIZE(tx_check_inputs_prefix_hash) KV_SERIALIZE(tx_check_inputs_attachment_check)