Merge pull request #2 from muscleman/master

updated to zano latest code base, correctly hashes and finds blocks
This commit is contained in:
cryptozoidberg 2022-01-17 20:56:52 +01:00 committed by GitHub
commit 78f73e6221
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 1678 additions and 302 deletions

View file

@ -1 +1,7 @@
module.exports = require('bindings')('cryptonote.node')
const bignum = require('bignum');
module.exports.baseDiff = function() {
return bignum('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16);
};

View file

@ -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",

View file

@ -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 );}

View file

@ -151,7 +151,7 @@ namespace command_line
}
template<typename F>
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<typename F>
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<typename T, bool required>
bool has_arg(const boost::program_options::variables_map& vm, const arg_descriptor<T, required>& arg)
{

View file

@ -15,20 +15,20 @@ bool parse_hash256(const std::string str_hash, crypto::hash& hash);
template <class T>
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 <class T>
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 <class T>
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) + "..";
}

View file

@ -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<MDBX_dbi>(h), &key, data, 0);
//MDBX_put_flags_t flags = MDBX_put_flags_t();
unsigned flags = 0;
res = mdbx_put(get_current_tx(), static_cast<MDBX_dbi>(h), &key, data, flags);
CHECK_AND_ASSERT_MESS_MDBX_DB(res, false, "Unable to mdbx_put");
return true;
}

View file

@ -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"

View file

@ -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()
};
}

View file

@ -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);

View file

@ -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<bool>(no_srv_param_adapter<t_server, t_handler>, _1, _2, handlr), prompt, usage);
return console_handler.run(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, boost::placeholders::_1, boost::placeholders::_2, handlr), prompt, usage);
}
template<class t_server, class t_handler>
@ -460,7 +460,7 @@ namespace epee
/*template<class t_srv>
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<class t_srv>
bool run_handling(t_srv& srv, const std::string& usage_string)
{
return run_default_console_handler_no_srv_param(&srv, boost::bind<bool>(&console_handlers_binder::process_command_str, this, _1), usage_string);
return run_default_console_handler_no_srv_param(&srv, boost::bind<bool>(&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<t_server>::process_command_str, this, _1, _2), prompt, usage_string);
return m_console_handler.run(psrv, boost::bind(&srv_console_handlers_binder<t_server>::process_command_str, this, boost::placeholders::_1, boost::placeholders::_2), prompt, usage_string);
}
void stop_handling()

View file

@ -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 base_class>
class namespace_accessor: public base_class{};

View file

@ -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
{

View file

@ -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<class _Ty1, class _Ty2>
struct kvserializable_pair : public std::pair<_Ty1, _Ty2>
{
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(first)
KV_SERIALIZE(second)
END_KV_SERIALIZE_MAP()
};
}

View file

@ -115,7 +115,7 @@ public: \
template<t_uint mask>
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;
}
};

View file

@ -26,6 +26,7 @@
#pragma once
#include <boost/mpl/vector.hpp>
#include <deque>
namespace epee

View file

@ -94,9 +94,28 @@ namespace epee
return serialization::load_t_from_binary(result_struct, pri->m_body);
}
template<class t_request, class t_response, class t_transport>
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<t_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<t_response, epee::json_rpc::error> 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<class t_request, class t_response, class t_transport>
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<t_request> req_t = AUTO_VAL_INIT(req_t);
req_t.jsonrpc = "2.0";
req_t.id = req_id;

View file

@ -28,6 +28,7 @@
#pragma once
#include <boost/mpl/contains.hpp>
#include "misc_language.h"
#include "portable_storage_base.h"
#include "portable_storage_to_bin.h"

View file

@ -284,12 +284,19 @@ POP_GCC_WARNINGS
typedef std::map<std::wstring, std::wstring> command_line_params_w;
template<typename t_pod_data>
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<const char*>(&pod), sizeof(pod));
}
template<typename pod_t>
bool get_pod_from_strbuff(const std::string& buff, pod_t& output)
{
if (buff.size() != sizeof(pod_t))
return false;
output = *reinterpret_cast<const pod_t*>(buff.data());
return true;
}
template<class t_string>
bool parse_commandline(std::map<t_string, t_string>& res, int argc, char** argv)

View file

@ -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;

View file

@ -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<const unsigned char*>(&pk)) == 0;
@ -710,19 +734,151 @@ namespace crypto
}; // struct point_g_t
//
// vector of scalars
//
struct scalar_vec_t : public std::vector<scalar_t>
{
typedef std::vector<scalar_t> super_t;
scalar_vec_t() {}
scalar_vec_t(size_t n) : super_t(n) {}
scalar_vec_t(std::initializer_list<scalar_t> 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<size_t N>
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<scalar_t> 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

View file

@ -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;
}

823
src/crypto/range_proofs.h Normal file
View file

@ -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<point_t>& 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<point_t> 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<public_key> L; // size = log_2(m * n)
std::vector<public_key> 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<typename CT>
bool bpp_gen(const std::vector<uint64_t>& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector<point_t>& 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<c_bpp_n> 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<c_bpp_n> 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<point_t> 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 = <a1, ((y, y^2, ...) o b2)> -- 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 = <a2, ((y, y^2, ...) o b1)> * 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<typename CT>
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<point_t>& commitments)
: sig(sig)
, commitments(commitments)
{}
const bpp_signature& sig;
const std::vector<point_t>& commitments;
};
template<typename CT>
bool bpp_verify(const std::vector<bpp_sig_commit_ref_t>& 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<point_t> L;
std::vector<point_t> R;
};
std::vector<intermediate_element_t> 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<point_t> 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<<j) & i) - 1) (counting both from 0)
//
// 2) we gonna aggregate all (**) for each round by multiplying them to a random weights and then sum up
// insert A_hat into (**) =>
// (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<c_bpp_n> 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<CT>(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

View file

@ -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())

View file

@ -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<unsigned char> 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);

View file

@ -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 ""

View file

@ -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<int64_t>(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<int64_t>(bei.bl.timestamp) - actual_ts << ")";

View file

@ -73,33 +73,35 @@ namespace currency
epee::math_helper::average<uint64_t, 5> target_calculating_calc;
//tx processing zone
epee::math_helper::average<uint64_t, 5> tx_check_inputs_time;
epee::math_helper::average<uint64_t, 5> tx_add_one_tx_time;
epee::math_helper::average<uint64_t, 5> tx_process_extra;
epee::math_helper::average<uint64_t, 5> tx_process_attachment;
epee::math_helper::average<uint64_t, 5> tx_process_inputs ;
epee::math_helper::average<uint64_t, 5> tx_push_global_index;
epee::math_helper::average<uint64_t, 5> tx_check_exist;
epee::math_helper::average<uint64_t, 5> tx_print_log;
epee::math_helper::average<uint64_t, 5> tx_prapare_append;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_time;
epee::math_helper::average<uint64_t, 1> tx_add_one_tx_time;
epee::math_helper::average<uint64_t, 1> tx_process_extra;
epee::math_helper::average<uint64_t, 1> tx_process_attachment;
epee::math_helper::average<uint64_t, 1> tx_process_inputs ;
epee::math_helper::average<uint64_t, 1> tx_push_global_index;
epee::math_helper::average<uint64_t, 1> tx_check_exist;
epee::math_helper::average<uint64_t, 1> tx_print_log;
epee::math_helper::average<uint64_t, 1> tx_prapare_append;
epee::math_helper::average<uint64_t, 5> tx_append_time;
epee::math_helper::average<uint64_t, 5> tx_append_rl_wait;
epee::math_helper::average<uint64_t, 5> tx_append_is_expired;
epee::math_helper::average<uint64_t, 1> tx_append_time;
epee::math_helper::average<uint64_t, 1> tx_append_rl_wait;
epee::math_helper::average<uint64_t, 1> tx_append_is_expired;
epee::math_helper::average<uint64_t, 5> tx_store_db;
epee::math_helper::average<uint64_t, 1> tx_store_db;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_prefix_hash;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_attachment_check;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_kimage_check;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_ch_in_val_sig;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_get_item_size;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_relative_to_absolute;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_loop;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_loop_get_subitem;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_loop_find_tx;
epee::math_helper::average<uint64_t, 5> tx_check_inputs_loop_scan_outputkeys_loop_handle_output;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_prefix_hash;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_attachment_check;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_kimage_check;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_ch_in_val_sig;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_get_item_size;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_relative_to_absolute;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_loop;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_loop_get_subitem;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_loop_find_tx;
epee::math_helper::average<uint64_t, 1> tx_check_inputs_loop_scan_outputkeys_loop_handle_output;
epee::math_helper::average<uint64_t, 1> 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);
}
}

View file

@ -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;
}
}

View file

@ -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<uint64_t, crypto::hash> m_points;
};

View file

@ -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;

View file

@ -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<uint8_t>(1 << 0)
#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast<uint8_t>(1 << 1)
#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast<uint8_t>(1 << 0)
#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast<uint8_t>(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<uint8_t>(1 << 2)
// add proof of content, without revealing secrete
#define TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF static_cast<uint8_t>(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

View file

@ -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)

View file

@ -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<void>
{
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<void>
{
const account_keys& m_acc_keys;
const crypto::public_key& m_tx_onetime_pubkey;
const crypto::key_derivation& rkey;
std::vector<payload_items_v>& rdecrypted_att;
decrypt_attach_visitor(const crypto::key_derivation& key,
std::vector<payload_items_v>& decrypted_att) :
std::vector<payload_items_v>& 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<class items_container_t>
bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector<payload_items_v>& decrypted_att)
bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector<payload_items_v>& 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<std::string>(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)

View file

@ -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<payload_items_v>& 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<tx_out>& 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<crypto::hash>& add, std::string& hex_buff);
bool hexstr_to_addendum(const std::string& hex_buff, std::vector<crypto::hash>& add);
bool set_payment_id_to_tx(std::vector<attachment_v>& 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);

View file

@ -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;
}

View file

@ -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)

View file

@ -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<Integer> returnValue = Nan::New(static_cast<uint32_t>(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<Object> target = info[0]->ToObject();
//Local<Object> target = info[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> 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<v8::Value>& info) {
if (info.Length() < 1)
return THROW_ERROR_EXCEPTION("You must provide one argument.");
Local<Object> target = info[0]->ToObject();
//Local<Object> target = info[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& args) {
void get_pow_hash(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (args.Length() < 3)
if (info.Length() < 3)
return THROW_ERROR_EXCEPTION("You must provide 3 arguments.");
Local<Object> block_header_hash = args[0]->ToObject();
Local<Object> nonce = args[1]->ToObject();
Local<Object> height = args[2]->ToObject();
//Local<Object> block_header_hash = args[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> block_header_hash = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
//Local<Object> nonce = args[1]->ToObject();
Local<Object> nonce = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
//Local<Object> height = args[2]->ToObject();
Local<Object> 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<v8::Value>& 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<char*>(&h);
v8::Local<v8::Value> 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<v8::Value>& args) {
void get_hash_from_block_template_with_extra(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (args.Length() < 2)
if (info.Length() < 2)
return THROW_ERROR_EXCEPTION("You must provide 2 arguments.");
Local<Object> block_template_buffer = args[0]->ToObject();
Local<Object> extra_data = args[1]->ToObject();
//Local<Object> block_template_buffer = args[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
//Local<Object> extra_data = args[1]->ToObject();
Local<Object> 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<v8:
crypto::hash h = currency::get_block_header_mining_hash(b);
SET_BUFFER_RETURN((const char*)&h, 32);
//SET_BUFFER_RETURN((const char*)&h, 32);
char *cstr = reinterpret_cast<char*>(&h);
v8::Local<v8::Value> 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<v8::Value>& args) {
void get_blob_from_block_template(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (args.Length() < 3)
if (info.Length() < 3)
return THROW_ERROR_EXCEPTION("You must provide 3 arguments.");
Local<Object> block_template_buffer = args[0]->ToObject();
Local<Object> extra_data = args[1]->ToObject();
Local<Object> nonce = args[2]->ToObject();
//Local<Object> block_template_buffer = args[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> block_template_buffer = info[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
//Local<Object> extra_data = args[1]->ToObject();
Local<Object> extra_data = info[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
//Local<Object> nonce = args[2]->ToObject();
Local<Object> 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<v8::Value>& 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<v8::Value> returnValue = Nan::CopyBuffer((char*)result_blob.data(), result_blob.size()).ToLocalChecked();
info.GetReturnValue().Set(returnValue);
}
void get_id_hash(const Nan::FunctionCallbackInfo<v8::Value>& args) {
void get_id_hash(const Nan::FunctionCallbackInfo<v8::Value>& info) {
if (args.Length() < 1)
if (info.Length() < 1)
return THROW_ERROR_EXCEPTION("You must provide 2 arguments.");
Local<Object> block_buffer = args[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> 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<v8::Value>& 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<char*>(&h);
v8::Local<v8::Value> returnValue = Nan::CopyBuffer(cstr, 32).ToLocalChecked();
info.GetReturnValue().Set(returnValue);
}
@ -295,8 +327,10 @@ void is_address_valid(const Nan::FunctionCallbackInfo<v8::Value>& info)
if (info.Length() < 1)
return THROW_ERROR_EXCEPTION("You must provide one argument.");
Local<Object> target = info[0]->ToObject();
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Local<Object> 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<FunctionTemplate>(get_blob_from_block_template)).ToLocalChecked());
Nan::Set(target, Nan::New("get_id_hash").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(get_id_hash)).ToLocalChecked());
Nan::Set(target, Nan::New("is_address_valid").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(is_address_valid)).ToLocalChecked());
Nan::Set(target, Nan::New("get_merged_mining_nonce_size").ToLocalChecked(), Nan::GetFunction(Nan::New<FunctionTemplate>(get_merged_mining_nonce_size)).ToLocalChecked());
}
NODE_MODULE(cryptonote, init)
NODE_MODULE(cryptonote, init)

View file

@ -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;

View file

@ -26,18 +26,19 @@ namespace nodetool
namespace
{
const command_line::arg_descriptor<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
const command_line::arg_descriptor<std::string> arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)};
const command_line::arg_descriptor<uint32_t> 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<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
const command_line::arg_descriptor<std::vector<std::string> > 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<std::string> arg_p2p_bind_ip = {"p2p-bind-ip", "Interface for p2p network protocol", "0.0.0.0"};
const command_line::arg_descriptor<std::string> arg_p2p_bind_port = {"p2p-bind-port", "Port for p2p network protocol", boost::to_string(P2P_DEFAULT_PORT)};
const command_line::arg_descriptor<uint32_t> 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<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
const command_line::arg_descriptor<std::vector<std::string> > 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<bool> arg_p2p_use_only_priority_nodes = {"use-only-priority-nodes", "Try to connect only to priority nodes"};
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true };
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true };
}
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_p2p_offline_mode = { "offline-mode", "Don't connect to any node and reject any connections", false, true };
const command_line::arg_descriptor<bool> arg_p2p_disable_debug_reqs = { "disable-debug-p2p-requests", "Disable p2p debug requests", false, true };
const command_line::arg_descriptor<uint32_t> 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<class t_payload_net_handler>
@ -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<class t_payload_net_handler>
@ -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<uint64_t>();
@ -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<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::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<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::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<class t_payload_net_handler>
@ -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;

View file

@ -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 <map>
#include <iterator>
#include <boost/foreach.hpp>
//#include <boost/bimap.hpp>
//#include <boost/bimap/multiset_of.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/version.hpp>
@ -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::tag<by_id>, boost::multi_index::member<peerlist_entry,uint64_t,&peerlist_entry::id> >,
// access by peerlist_entry::net_adress
boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >,
// sort by peerlist_entry::last_seen<
boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,time_t,&peerlist_entry::last_seen> >
>
> peers_indexed_old;
public:
template <class Archive, class t_version_type>
@ -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<by_addr>().find(x.adr);
if(by_addr_it == pi.get<by_addr>().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)

View file

@ -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<int64_t>(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<int64_t>(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<int64_t>(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<int64_t>(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;

View file

@ -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)