diff --git a/src/crypto/crypto-sugar.h b/src/crypto/crypto-sugar.h index 8fe7890a..9dad0b4e 100644 --- a/src/crypto/crypto-sugar.h +++ b/src/crypto/crypto-sugar.h @@ -51,38 +51,42 @@ namespace crypto } - template - std::string pod_to_hex_reversed(const pod_t &h) + inline std::string buff_to_hex(const void* pdata, size_t len, bool reversed = false) { constexpr char hexmap[] = "0123456789abcdef"; - const unsigned char* data = reinterpret_cast(&h); - size_t len = sizeof h; + const unsigned char* data = reinterpret_cast(pdata); std::string s(len * 2, ' '); - for (size_t i = 0; i < len; ++i) + if (!reversed) { - s[2 * i] = hexmap[data[len - 1 - i] >> 4]; - s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F]; + for (size_t i = 0; i < len; ++i) + { + s[2 * i] = hexmap[data[i] >> 4]; + s[2 * i + 1] = hexmap[data[i] & 0x0F]; + } + } + else + { + for (size_t i = 0; i < len; ++i) + { + s[2 * i] = hexmap[data[len - 1 - i] >> 4]; + s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F]; + } } return s; } + template + std::string pod_to_hex_reversed(const pod_t &h) + { + return buff_to_hex(&h, sizeof h, true); + } + template std::string pod_to_hex(const pod_t &h) { - constexpr char hexmap[] = "0123456789abcdef"; - const unsigned char* data = reinterpret_cast(&h); - size_t len = sizeof h; - - std::string s(len * 2, ' '); - for (size_t i = 0; i < len; ++i) - { - s[2 * i] = hexmap[data[i] >> 4]; - s[2 * i + 1] = hexmap[data[i] & 0x0F]; - } - - return s; + return buff_to_hex(&h, sizeof h); } template diff --git a/src/currency_core/currency_format_utils.cpp b/src/currency_core/currency_format_utils.cpp index bb04b760..fc3cc932 100644 --- a/src/currency_core/currency_format_utils.cpp +++ b/src/currency_core/currency_format_utils.cpp @@ -4,7 +4,7 @@ // Copyright (c) 2012-2013 The Boolberry developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. - +#include #include "include_base_utils.h" #include #ifndef MOBILE_WALLET_BUILD @@ -4442,6 +4442,45 @@ namespace currency } } //------------------------------------------------------------------ +#define ASSET_TICKER_REGEXP "[A-Za-z0-9]{1,14}" +#define ASSET_FULL_NAME_REGEXP "[A-Za-z0-9.,:!?\\-() ]{0,400}" + bool validate_asset_ticker(const std::string& ticker) + { + static std::regex asset_ticker_regexp(ASSET_TICKER_REGEXP); + return std::regex_match(ticker, asset_ticker_regexp); + } + //------------------------------------------------------------------ + bool validate_asset_full_name(const std::string& full_name) + { + static std::regex asset_full_name_regexp(ASSET_FULL_NAME_REGEXP); + return std::regex_match(full_name, asset_full_name_regexp); + } + //------------------------------------------------------------------ + bool validate_asset_ticker_and_full_name(const asset_descriptor_base& adb) + { + if (!validate_asset_ticker(adb.ticker)) + return false; + + if (!validate_asset_full_name(adb.full_name)) + return false; + + //CHECK_AND_ASSERT_MES(validate_asset_ticker(adb.ticker), false, "asset's ticker isn't valid: " << adb.ticker); + //CHECK_AND_ASSERT_MES(validate_asset_full_name(adb.full_name), false, "asset's full_name isn't valid: " << adb.full_name); + return true; + } + //------------------------------------------------------------------ + void replace_asset_ticker_and_full_name_if_invalid(asset_descriptor_base& adb, const crypto::public_key& asset_id) + { + if (!validate_asset_ticker(adb.ticker)) + adb.ticker = "#BADASSET#"; + + if (!validate_asset_full_name(adb.full_name)) + { + std::string abcd = crypto::pod_to_hex(asset_id).substr(60, 4); // last 4 hex chars + adb.full_name = "#bad asset name " + abcd + "#"; + } + } + //------------------------------------------------------------------ std::string dump_ring_sig_data(const crypto::hash& hash_for_sig, const crypto::key_image& k_image, const std::vector& output_keys_ptrs, const std::vector& sig) { std::stringstream s; diff --git a/src/currency_core/currency_format_utils.h b/src/currency_core/currency_format_utils.h index 0928a142..f1706b54 100644 --- a/src/currency_core/currency_format_utils.h +++ b/src/currency_core/currency_format_utils.h @@ -276,6 +276,11 @@ namespace currency bool validate_asset_operation_amount_commitment(asset_op_verification_context& context); const char* get_asset_operation_type_string(size_t asset_operation_type, bool short_name = false); + bool validate_asset_ticker(const std::string& ticker); + bool validate_asset_full_name(const std::string& full_name); + bool validate_asset_ticker_and_full_name(const asset_descriptor_base& adb); + void replace_asset_ticker_and_full_name_if_invalid(asset_descriptor_base& adb, const crypto::public_key& asset_id); + //--------------------------------------------------------------- bool construct_miner_tx(size_t height, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t current_block_size, diff --git a/tests/functional_tests/crypto_tests_performance.h b/tests/functional_tests/crypto_tests_performance.h index 0996add2..fff2f461 100644 --- a/tests/functional_tests/crypto_tests_performance.h +++ b/tests/functional_tests/crypto_tests_performance.h @@ -5,6 +5,7 @@ // #pragma once #include +#include "crypto/crypto-sugar.h" // just for intellysense uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_count) { @@ -1338,3 +1339,60 @@ TEST(perf, point_eq_vs_iszero) return true; } + +TEST(perf, buff_to_hex) +{ + std::vector in_buffs; + std::vector out_hexs; + std::vector timings1, timings2; + + size_t N = 10000; + in_buffs.reserve(N); + out_hexs.reserve(N); + + for(size_t i = 0; i < N; ++i) + { + size_t len = (crypto::rand() % 128) + 1; // [1; 128] + std::string& buff = in_buffs.emplace_back(); + buff.resize(len); + generate_random_bytes(len, buff.data()); + } + + size_t rounds = 100, warmup_rounds = 20; + for(size_t i = 0; i < warmup_rounds + rounds; ++i) + { + out_hexs.clear(); + TIME_MEASURE_START(t1); + for(size_t j = 0; j < N; ++j) + out_hexs.push_back(epee::string_tools::buff_to_hex_nodelimer(in_buffs[j])); + TIME_MEASURE_FINISH(t1); + + uint64_t h1 = 0; + for(size_t j = 0; j < N; ++j) + h1 ^= hash_64(out_hexs[j].data(), out_hexs[j].size()); + + out_hexs.clear(); + TIME_MEASURE_START(t2); + for(size_t j = 0; j < N; ++j) + out_hexs.push_back(crypto::buff_to_hex(in_buffs[j].data(), in_buffs[j].size())); + TIME_MEASURE_FINISH(t2); + + uint64_t h2 = 0; + for(size_t j = 0; j < N; ++j) + h2 ^= hash_64(out_hexs[j].data(), out_hexs[j].size()); + + ASSERT_EQ(h1, h2); + + if (i >= warmup_rounds) + { + timings1.push_back(t1); + timings2.push_back(t2); + } + } + + std::cout << "After " << rounds << " rounds:" << ENDL << + "epee::string_tools::buff_to_hex_nodelimer : " << epee::misc_utils::median(timings1) << " mcs" << ENDL << + "crypto::buff_to_hex : " << epee::misc_utils::median(timings2) << " mcs" << ENDL; + + return true; +}